Request,Response

442 阅读10分钟

Request&Response

image.png

一. Request和Response的概述

Request是请求对象,Response是响应对象。(这两个对象可以在servlet中使用)

1. request:获取请求数据

    - 浏览器会发送HTTP请求到后台服务器[Tomcat]
    - HTTP的请求中会包含很多请求数据[请求行+请求头+请求体]
    - 后台服务器[Tomcat]会对HTTP请求中的数据进行解析并把解析结果存入到一个对象中
    - 所存入的对象即为request对象,所以我们可以从request对象中获取请求的相关参数
    - 获取到数据后就可以继续后续的业务,比如获取用户名和密码就可以实现登录操作的相关业务
    
2. response:设置响应数据

    - 业务处理完后,后台就需要给前端返回业务处理的结果即响应数据
    - 把响应数据封装到response对象中
    - 后台服务器[Tomcat]会解析response对象,按照[响应行+响应头+响应体]格式拼接结果
    - 浏览器最终解析结果,把内容展示在浏览器给用户浏览
    
3.requestresponse对象的使用。(在servlet的doGet或者doPost方法中使用)

    //使用request对象 获取请求数据
    String name = request.getParameter("name");//url?name=zhangsan
    //使用response对象 设置响应数据
    response.setHeader("content-type","text/html;charset=utf-8");
    response.getWriter().write("<h1>"+name+",欢迎您!</h1>");

二. Request对象

1. Request继承体系

image.png
1. Request的继承体系为ServletRequest-->HttpServletRequest-->RequestFacade
2. Tomcat需要解析请求数据,封装为request对象,并且创建request对象传递到service方法
3. 使用request对象,可以查阅JavaEE API文档的HttpServletRequest接口中方法说明

2. Request获取请求数据

HTTP请求数据总共分为三部分内容,分别是请求行、请求头、请求体

1. 获取请求行数据

请求行包含三块内容,分别是请求方式、请求资源路径、HTTP协议及版本

image.png

    1. 获取请求方式: GET
        String getMethod()
    
    2. 获取虚拟目录(项目访问路径): /request-demo
        String getContextPath()

    3. 获取URL(统一资源定位符): http://localhost:8080/request-demo/req1
        StringBuffer getRequestURL()
    
    4. 获取URI(统一资源标识符): /request-demo/req1
        String getRequestURI()

    5. 获取请求参数(GET方式): username=zhangsan&password=123
        String getQueryString()

2. 获取请求头数据

对于请求头的数据,格式为key: value如下:

image.png

根据请求头名称获取对应值的方法为:

    String getHeader(String name)
    例如://获取请求头: user-agent: 浏览器的版本信息\
          String agent = request.getHeader("user-agent");

3. 获取请求体数据

浏览器在发送GET请求的时候是没有请求体的,所以需要把请求方式变更为POST,请求体中的数据格式如下:

image.png

1. 获取请求体中数据的两种方式:

    a.ServletInputStream getInputStream() //该方法可以获取字节数据
    获取字节输入流,如果前端发送的是字节数据,比如传递的是文件数据,则使用该方法
    
    b.BufferedReader getReader()
    获取字符输入流,如果前端发送的是纯文本数据,则使用该方法
    
    例如:
        //获取post 请求体:请求参数
        //1. 获取字符输入流
        BufferedReader br = req.getReader();
        //2. 读取数据
        String line = br.readLine();
        System.out.println(line);

2. 注意:BufferedReader流是通过request对象来获取的,当请求完成后request对象就会被销毁,
request对象被销毁后,BufferedReader流就会自动关闭,所以此处就不需要手动关闭流了。

总结:

请求行
    getMethod()获取请求方式
    getContextPath()获取项目访问路径
    getRequestURL()获取请求URL
    getRequestURI()获取请求URI
    getQueryString()获取GET请求方式的请求参数
    
请求头
    getHeader(String name)根据请求头名称获取其对应的值
    
请求体
    注意: 浏览器发送的POST请求才有请求体
    如果是纯文本数据:getReader()
    如果是字节数据如文件数据:getInputStream()

4. 获取请求参数的通用方式

1.请求参数: 比如登录的时候,提交的用户名和密码就是请求参数
2.请求数据: 请求数据则是包含请求行、请求头和请求体的所有数据
3.请求参数的获取,request对象为我们提供了如下方法:

    a.获取所有参数Map集合
    Map<String,String[]> getParameterMap()
    
    b.根据名称获取参数值(数组)
    String[] getParameterValues(String name)
    
    c.根据名称获取参数值(单个值)
    String getParameter(String name)
    
4.request的getParameterMap方法获取请求参数的原理是:

    首先获取请求参数,然后将内容进行分割,将分割的数据放到一个Map集合中,Map的值的类型为String数组

总结:

public class RequestDemo1 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //采用request提供的获取请求参数的通用方式来获取请求参数
        //编写其他的业务代码...
    } 
    
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {
        this.doGet(req,resp);
    }
}

3. IDEA快速创建Servlet

使用IDEA提供的模板来制作一个Servlet的模板,后期创建servlet更高效

1.打开IDEA的setting设置 > Editor > File and Code Templates > 右侧找到other > Web > Servlet Annotated Class > 修改代码模板

image.png

4. 请求参数中文乱码问题

中文请求乱码问题的解决

1. Post请求中文乱码原因:

    POST的请求参数是通过request的getReader()来获取流中的数据
    TOMCAT在获取流的时候采用的编码是ISO-8859-1
    ISO-8859-1编码是不支持中文的,所以会出现乱码

Post请求中文乱码解决方案:

    页面设置的编码格式为UTF-8
    把TOMCAT在获取流数据之前的编码设置为UTF-8
    通过request.setCharacterEncoding("UTF-8")设置编码,UTF-8也可以写成小写

2. GET请求中文乱码原因:

    浏览器把中文参数按照UTF-8进行URL编码
    Tomcat对获取到的内容进行了ISO-8859-1的URL解码  
    在控制台就会出现类上å¼ ä¸的乱码,最后一位是个空格
    
Get请求中文乱码解决方案:

    虽然编码不同会导致解码后得到的数据是乱码,但是如果将它们转换为字节,还是一样的
    所以可以将得到的乱码转换为字节,在把字节通过UTF-8字符集转换为字符串就可以了

总结:

1.中文乱码解决方案
    POST请求和GET请求的参数中如果有中文,后台接收数据就会出现中文乱码问题
    GET请求在Tomcat8.0以后的版本就不会出现了
  
  POST请求解决方案是:设置输入流的编码
  request.setCharacterEncoding("UTF-8");
  注意:设置的字符集要和页面保持一致
  
  通用方式(GET/POST):需要先解码,再编码
  new String(username.getBytes("ISO-8859-1"),"UTF-8");
  
2. URL编码实现方式:
    编码: URLEncoder.encode(str,"UTF-8");
    解码: URLDecoder.decode(s,"ISO-8859-1");

5. Request请求转发

image.png

  1. 请求转发(forward):一种在服务器内部的资源跳转方式.

  2. 请求转发的实现方式:

    A转发到B,就在A里面写转发代码。
    req.getRequestDispatcher("资源B路径").forward(req,resp);
    
  3. 请求转发资源间共享数据:使用Request对象

    需要使用request对象提供的三个方法:
        1.存储数据到request域[范围,数据是存储在request对象]中
        
            void setAttribute(String name,Object o);
        
        2.根据key获取值
        
            Object getAttribute(String name);
        
        3.根据key删除该键值对
    
            void removeAttribute(String name);
            
    举例:A转发到B,并在转发的过程中,传递一个数据。
        1.在A中通过setAttribute方法,将数据存入request域对象中
        2.在B中从request域对象中,通过getAttribute方法获取数据。
    
  4. 请求转发的特点

    1.请求转发后,浏览器地址栏路径不发生变化。
    2.只能转发到当前服务器的内部资源,不能从一个服务器通过转发访问另一台服务器
    3.一次请求,可以在转发资源间使用request共享数据。
    

三. Response对象

image.png

image.png Request:使用request对象来获取请求数据

Response:使用response对象来设置响应数据

1. Response设置响应数据功能介绍

  1. 响应行
    设置响应状态码: void setStatus(int sc);
    
  2. 响应头
    设置响应头键值对:void setHeader(String name,String value);
    
  3. 响应体
    对于响应体,是通过字符、字节输出流的方式往浏览器写
    获取字符输出流:PrintWriter getWriter();
    获取字节输出流:ServletOutputStream getOutputStream()
    

2. Respones请求重定向

image.png

  1. Response重定向(redirect):一种资源跳转方式。
重定向讲解:

1.浏览器发送请求给服务器,服务器中对应的资源A接收到请求
2.资源A无法处理请求,给浏览器响应302状态码+location的一个访问资料B路径
3.浏览器接收到响应状态码为302就会重新发送请求到location对应的访问地址去访问资源B
4.资源B收到请求进行处理,并给浏览器响应结果,这个过程叫重定向。
  1. 重定向的实现方式
    浏览器访问A资源地址,A处理不了请求,将B资源地址返回给浏览器并设置状态码和响应头,
    响应头的keyLocation,值为B的资源地址。A重定向到B,就在A中设置响应码和响应头。
    
    重定向方法一:
        //重定向
        //1.设置响应状态码 302
        response.setStatus(302);
        //2. 设置响应头 Location
        response.setHeader("Location","/request-demo/resp2");
    
    重定向方法二:
        resposne.sendRedirect("要重定向到的资源地址")
        该方法同时设置状态代码为302
    
  2. 重定向的特点
    1.浏览器地址栏路径发送变化(重定向访问,浏览器是发送的2次请求,所以地址会变化)
    2.可以重定向到任何位置的资源(服务内容、外部均可)
    3.两次请求,不能在多个资源使用request共享数据(无法通过request对象进行共享数)
    

3. 路径问题

  1. 重定向和转发加不加虚拟目录问题
    重定向需要加虚拟目录,转发不需要加虚拟目录。
    因为重定向是从浏览器发送的请求,转发是从内部服务器发送的请求。
    
    判断依据:
    浏览器使用:需要加虚拟目录(项目访问路径)
    服务端使用:不需要加虚拟目录
    
  2. 如果更改了虚拟目录地址,重定向的地址都要更改,如何解决?
    通过request对象中的getContextPath()方法可以动态获取虚拟目录地址。
    

4. Response响应字符数据

1.返回一个简单的字符串aaa

    将字符数据写回到浏览器:response.getWriter().write("aaa");


2.返回一串html字符串,并且能被浏览器解析

    //content-type,告诉浏览器返回的数据类型是HTML类型数据,浏览器会调用浏览器内不同的程序嵌入模块来处理相应的数据。 
    response.setHeader("content-type","text/html");
    writer.write("<h1>aaa</h1>");

3. 返回一个中文的字符串你好,需要注意设置响应数据的编码为utf-8
    //设置响应的数据格式及数据的编码
    response.setContentType("text/html;charset=utf-8");
    writer.write("你好");

注意:一次请求响应结束后,response对象就会被销毁掉,所以不要手动关闭流。

5. Response响应字节数据

将字节数据写回到浏览器:resp.getOutputStream().write(字节数据);

1. 返回一个图片文件到浏览器

    1.导入依赖
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>
    2.调用工具类方法
        //fis:输入流
        //os:输出流
        IOUtils.copy(fis,os);
        
    3.代码
    //1. 读取文件
    FileInputStream fis = new FileInputStream("d://a.jpg");
    //2. 获取response字节输出流
    ServletOutputStream os = response.getOutputStream();
    //3. 完成流的copy
    IOUtils.copy(fis,os);
    fis.close();

四、重定向和转发的区别

image.png

五、SqlSessionFactory工具类抽取

public class SqlSessionFactoryUtils {

    private static SqlSessionFactory sqlSessionFactory;
    
    static {
    //静态代码块会随着类的加载而自动执行,且只执行一次
        try {
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    } 
    public static SqlSessionFactory getSqlSessionFactory(){
        return sqlSessionFactory;
    }
}