草庐IT

05-Request&Response

OnlyOnYourself-lzw 2023-04-20 原文

Request&Response

  • Request
    • 获取请求数据
  • Response
    • 设置响应数据

1、Request

1.1、Request继承体系

  • 1、Tomcat需要解析请求数据,封装为request对象,并且创建request对象传递到service方法中
  • 2、使用request对象,查阅JavaEE API文档的HttpServletRequest接口

1.2、Request获取请求数据

1.2.1、获取请求数据的方法

  • 请求行:GET /request-response-demo/req1?username=zhangsan HTTP/1.1

    • 方法 说明 数据
      String getMethod() 获取请求方式 GET
      String getContextPath() 获取虚拟路径(项目访问路径) /request-response-demo
      StringBuffer getRequestURL() 获取URL(统一资源定位符) http://localhost:8080/request-response-demo/req1
      String getRequestURI() 获取URI(统一资源定位符) /request-response-demo/req1
      String getQueryString() 获取请求参数(GET方式) username=zhangsan&password=123
  • 请求头:User-Agent: Mozilla/5.0 Chrome/91.0.4472.106

    • String getHeader(String name):根据请求头名称,获取值
  • 请求体:username=superbaby&password=123

    • ServletInputStream getInputStream():获取字节输入流
    • BufferedReader getReader():获取字符输入流

1.2.2、通用方式获取请求参数

  • 请求参数获取方式
    • GET方式
      • String getQueryString()
    • POST方式
      • BufferedReader getReader()
  • 思考
    • 这里的GET请求方式和POST请求方式,区别主要在于获取请求参数的方式不一样
    • 那么是否有一种统一获取请求参数的方式,从而统一doGet和doPost方法内的代码?
  • 在Tomcat源码中,实现了一个在获取请求方式的时候,将参数赋值给了同一个成员变量param,使得doGet和doPost方法内的请求参数方式的代码有了统一的可能
    • Map<String,String[]> getParameterMap():获取所有参数Map集合
    • String getParameter(String name):根据名称获取参数值(单个值)
    • String[] getParameterValues(String name):根据名称获取参数值(数组)

1.2.3、请求参数中文乱码处理

  • Tomcat 8.0 之后,GET请求乱码的问题已经被解决,设置默认的编码方式为UTF-8,其他Tomcat的默认编码都为 ISO-8859-1;
  • Request解决POST请求参数中文乱码
    • 给POST方法设置输入流的编码
      • request.setCharacterEncoding("UTF-8")
  • URL编码
    • 1.将字符串按照编码方式转为二进制
    • 2.每个字节转为2个16进制数并在前面加上%

1.3、Request请求转发

  • 请求转发(forward):一种在服务器内部的资源跳转方式
  • 实现方式
    • request.getRequestDispatcher("资源B路径").forward(request, response);
  • 请求转发资源间共享数据:使用Request对象
    • void setAttribute(String name, Object o):存储数据到request域中
    • Object getAttribute(String name):根据key,获取值
    • void removeAttribute(String name):根据key,删除键值对
  • 请求转发的特点
    • 浏览器地址栏路径不发生变化
    • 只能转发到当前服务器的内部资源
    • 一次请求,可以在转发资源间使用request共享数据

2、Response

  • Request:使用request对象来获取请求数据
  • Response:使用response对象来设置响应数据

2.1、Response继承体系

2.2、Response设置响应数据

  • 响应数据分为3个部分
    • 响应行
      • HTTP/1.1 200 OK
      • void setStatus(int sc):设置响应状态
    • 响应头
      • Content-Type:text/html
      • void setHeader(String name, String value):设置响应头键值对
    • 响应体
      • <html><head></head><body></body></html>
      • PrintWriter getWriter():获取字符输出流
      • ServletOutputStream getOutputStream():获取字节输出流

2.3、Response重定向

  • 重定向概念
    • 跳转到下一个页面,不需要传递数据,使用重定向
    • 是一种资源跳转方式
  • 实现方式
    • 方式1
      • response.setStatus(302);
      • response.setHeader("location", "资源B的路径");
    • 方式2
      • response.sendRedirect("资源B的路径");
  • 重定向的特点
    • 浏览器地址栏发生变化
    • 可以重定向到任意位置的资源(服务器内部、外部均可)
    • 再次请求,不能在多个资源使用request共享数据

2.4、Response响应字符数据

  • 实现方式
    • 1.通过Response对象获取字符输出流
      • PrintWriter writer = response.getWriter();
    • 2.输出数据
      • writer.write("aaa");
  • 注意事项
    • 该流不需要关闭,随着响应结束,response对象销毁,由服务器关闭
    • 中文数据乱码,原因是通过Response获取的字符输出流默认编码跟Tomcat的默认编码一样都是:ISO-8859-1
      • 解决方式
        • response.setContentType("text/html;charset=utf-8");

2.5、Response响应字节数据

  • 实现方式

    • 1.通过Response对象获取字节输出流
      • ServletOutputStream outputStream = response.getOutputStream();
    • 2.写数据
      • outputStream.write(字节数据);
  • IOUtils工具类的使用

    • 添加依赖

      • <dependency>
          <groupId>commons-io</groupId>
          <artifactId>commons-io</artifactId
          <version>2.6</version>
        </dependency>
        
    • IOUtils.copy(输入流,输出流);

3、额外注意事项

3.1、路径问题

  • 明确路径谁使用?
    • 浏览器使用
      • /开头是绝对路径,会缺少项目访问路径
      • 不加/是相对路径,使用当前访问路径作为参照物,不会缺少项目访问路径
      • 浏览器使用的时候不加/
    • 服务器使用
      • 不加/

4、使用Tomcat实现用户登录和注册功能

  • LoginServlet

    • package com.coolman.servlet;
      
      import com.coolman.mapper.UserMapper;
      import com.coolman.pojo.User;
      import com.coolman.utils.MybatisUtils;
      import org.apache.ibatis.session.SqlSession;
      
      import javax.servlet.ServletException;
      import javax.servlet.annotation.WebServlet;
      import javax.servlet.http.HttpServlet;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      import java.io.IOException;
      import java.io.PrintWriter;
      
      @WebServlet("/loginServlet")
      public class LoginServlet extends HttpServlet {
          protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              doGet(request, response);
          }
      
          protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              // 在这里处理请求
      
              // 处理html表单的POST请求发送数据,中文时存在的编码问题
              request.setCharacterEncoding("utf-8");
      
              // 1. 获取参数
              String username = request.getParameter("username");
              String password = request.getParameter("password");
      
              // 2. 连接数据库
              SqlSession sqlSession = MybatisUtils.openSession();
              UserMapper mapper = sqlSession.getMapper(UserMapper.class);
              User user = mapper.selectUser(username, password);
      
              // 3. 判断表中是否存在该用户信息
              // 输出提示信息之前,需要解决response返回响应数据可能出现中文乱码的问题
              response.setContentType("text/html;charset=utf-8");
      
              PrintWriter writer = response.getWriter();
              if (user != null) {
                  // 输出字符流信息
                  writer.println("登录成功!");
      //            writer.println("<style>window.alert('恭喜您登录成功!')</style>");
              } else {
                  writer.println("登录失败!");
      //            writer.println("<style>window.alert('账号密码错误,登录失败!')</style>");
              }
              sqlSession.close();
          }
      }
      
      
  • RegisterServlet

    • package com.coolman.servlet;
      
      import com.coolman.mapper.UserMapper;
      import com.coolman.pojo.User;
      import com.coolman.utils.MybatisUtils;
      import org.apache.ibatis.session.SqlSession;
      
      import javax.servlet.ServletException;
      import javax.servlet.annotation.WebServlet;
      import javax.servlet.http.HttpServlet;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      import java.io.IOException;
      import java.io.PrintWriter;
      
      @WebServlet("/registerServlet")
      public class RegisterServlet extends HttpServlet {
          protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              doGet(request, response);
          }
      
          protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              // 在这里处理请求
              // 处理POST请求,表单返回的数据可能出现乱码的问题
              request.setCharacterEncoding("utf-8");
      
              // 获取参数
              String username = request.getParameter("username");
              String password = request.getParameter("password");
      
              // 连接数据库
              SqlSession sqlSession = MybatisUtils.openSession();
              UserMapper mapper = sqlSession.getMapper(UserMapper.class);
      
              // 查询该信息是否存在数据库
              User user = mapper.selectUserByUsername(username);
      
              // 解决response响应的数据可能出现乱码的问题
              response.setContentType("text/html;charset=utf-8");
              // 获取字符输出流
              PrintWriter writer = response.getWriter();
      
              // 考虑存在和不存在问题
              if (user != null) {
                  // 如果用户存在
                  writer.println("该用户已经存在,请重新注册!");
              } else {
                  // 如果用户不存在,那么就创建这个用户
                  User userNew = new User();
                  userNew.setUsername(username);
                  userNew.setPassword(password);
                  mapper.addUser(userNew);
                  sqlSession.commit();
      
                  writer.println("注册成功!");
              }
      
              sqlSession.close();
          }
      }
      

有关05-Request&Response的更多相关文章

  1. ruby-on-rails - rails : "missing partial" when calling 'render' in RSpec test - 2

    我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou

  2. ruby-on-rails - 由于 "wkhtmltopdf",PDFKIT 显然无法正常工作 - 2

    我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-

  3. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  4. ruby-on-rails - 如何从 format.xml 中删除 <hash></hash> - 2

    我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为

  5. ruby - 检查 "command"的输出应该包含 NilClass 的意外崩溃 - 2

    为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar

  6. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  7. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  8. ruby - 在 jRuby 中使用 'fork' 生成进程的替代方案? - 2

    在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',

  9. ruby - 主要 :Object when running build from sublime 的未定义方法 `require_relative' - 2

    我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby​​1.9+ 关于ruby-主要:Objectwhenrun

  10. ruby - 无法让 RSpec 工作—— 'require' : cannot load such file - 2

    我花了三天的时间用头撞墙,试图弄清楚为什么简单的“rake”不能通过我的规范文件。如果您遇到这种情况:任何文件夹路径中都不要有空格!。严重地。事实上,从现在开始,您命名的任何内容都没有空格。这是我的控制台输出:(在/Users/*****/Desktop/LearningRuby/learn_ruby)$rake/Users/*******/Desktop/LearningRuby/learn_ruby/00_hello/hello_spec.rb:116:in`require':cannotloadsuchfile--hello(LoadError) 最佳

随机推荐