HTTP-request

1.HTTP协议

  • 概念:Hyber Text Transfer Protocal 超文本传输协议

  • 定义了客户端和服务器端通信时,发送数据的格式

  • 特点:

    1. 基于TCP/IP的高级协议
    2. 默认端口号80
    3. 基于请求/响应模型:一次请求对应一次响应
    4. 无状态:每次请求之间相互独立,不能交互数据
  • 历史版本

    • 1.0版本:每次请求都会重新建立连接
    • 1.1版本:复用连接

2.HTTP请求消息数据格式

  1. 请求行

    请求方式 请求url 请求协议/版本

    • GET
      1. 请求参数在请求行中,在url后
      2. 请求的url长度有限制
    • POST
      1. 请求参数在请求体中
      2. 请求的url长度没有限制
  2. 请求头:请求头名称:请求头值,键值对格式

    • Host:请求的主机
    • User-Agent:浏览器告诉服务器浏览器版本信息。可以在服务器端获取该头的信息,解决浏览器的兼容性问题
    • Accept:本浏览器可以接受的资源格式
    • Accept-Lanuage:支持语言环境
    • Accept-Encoding:压缩格式
    • Referer:告诉服务器,当前请求从哪里来。
      1. 防盗链
      2. 统计工作
  3. 请求空行

    空行,分割POST请求消息的请求头和请求体

  4. 请求体(正文)

    • 封装POST请求消息的请求参数

3.请求响应原理

  1. tomcat服务器会根据请求url中的资源路径,创建对应的servlet对象。
  2. tomcat服务器会创建request和response对象,request对象中封装请求消息数据。
  3. tomcat将request和response两个对象传递给service方法,并且调用service
  4. 在service方法中可以通过request对象获取请求消息数据通过response对象设置响应消息数据。
  5. 服务器在给浏览器做出响应之前,会从response对象中取设置的响应消息数据。

4.request对象

4.1request对象继承体系结构

  • ServletRequest:接口
  • HttpServletRequest:接口,继承ServletRequest
  • org.apache.catalina.connector.RequestFacade:实现HttpServletRequest接口

4.2request功能

  • 获取请求消息数据

    1. 获取请求行数据

      eg. GET /test/demo?name=zhangsan HTTP/1.1

      • 获取请求方式:String getMethod(); GET

      • 获取虚拟目录:String getContextPath(); /test

      • 获取Servlet路径:String getServletPath(); /demo

      • 获取GET方式请求参数:String getQueryString(); name=zhangsan

      • 获取请求URI(统一资源标识符):String getRequestURI(); /test/demo

        获取请求URL(统一资源定位符):String getRequestURL(); http://localhost:8080/test/demo

      • 获取请求协议:String getProtocol: HTTP/1.1

      • 获取客户机的IP地址:String getRemoteAddr();

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    @WebServlet("/requestdemo1")
    public class requestdemo1 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    System.out.println(request.getMethod());
    System.out.println(request.getContextPath());
    System.out.println(request.getServletPath());
    System.out.println(request.getQueryString());
    System.out.println(request.getRequestURI());
    System.out.println(request.getRequestURL());
    System.out.println(request.getProtocol());
    System.out.println(request.getRemoteAddr());
    }
    }
    /*输入的链接:http://localhost:8080/test/requestdemo1?name=zhangsan
    GET
    /test
    /requestdemo1
    name=zhangsan
    /test/requestdemo1
    http://localhost:8080/test/requestdemo1
    HTTP/1.1
    0:0:0:0:0:0:0:1
    */
    1. 获取请求头数据
      • String getHeader(String name):通过请求头的名称获取请求头的值
      • Enumeration < String >getHeaderNames():获取所有的请求头名称
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    @WebServlet("/requestdemo2")
    public class requestdemo2 extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //获取请求头数据
    //获取所有请求头名称
    Enumeration<String> headerNames = request.getHeaderNames();
    while (headerNames.hasMoreElements()){
    String name = headerNames.nextElement();
    //根据名称获取请求头的值
    String value = request.getHeader(name);
    System.out.println(name+"---->"+value);
    }
    //简单防盗链
    String referer = request.getHeader("referer");
    System.out.println(referer);
    // http://localhost/test/requestdemo2
    if (referer!=null){
    if (referer.contains("/test")){
    System.out.println("播放");
    }else{
    System.out.println("不播放");
    }
    }
    }
    }
  1. 获取请求体数据

    • 请求体:只有POST请求方式,才有请求体,在请求体中封装了POST请求的请求参数

    • 步骤

      (1) 获取流对象,字节流或字符流

      • BufferedReader getReader():获取字符输入流,只能操作字符数据
      • ServletInputStream():获取字节输入流,可以操作所有数据类型
      1
      2
      3
      4
      5
      6
      7
      8
      9
      protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      //获取请求消息体
      BufferedReader br = request.getReader();
      //读取数据
      String line = null;
      while ((line= br.readLine())!=null){
      System.out.println(line);
      }
      }

      (2) 从流对象中拿数据

  • 获取请求参数通用方式

    1. String getParameter(String name):根据参数名称获取参数值 username=hxx

    2. String[] getParameterValues(String name):根据参数名称获取参数值的数组 hobby=xx&hobby=yy

    3. Enumeration< String >getParameterNames():获取所有请求的参数名称

    4. Map< String,String[] > getParameterMap():获取所有参数的map集合

    5. 中文乱码问题:

      get方式:tomcat8已经将get方式乱码问题解决

      post方式:会乱码,需要在获取参数前设置编码 request.setCharacterEncoding(“utf-8”);

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //设置流的编码,要和所对应的页面格式相同
    request.setCharacterEncoding("utf-8");
    //POST 请求参数
    //根据参数名称获取参数值
    String username = request.getParameter("username");
    System.out.println(username);

    String[] hobbies = request.getParameterValues("hobby");
    for (String hobby : hobbies) {
    System.out.println(hobby);
    }

    //获取所有请求参数的名称
    Enumeration<String> parameterNames = request.getParameterNames();
    while(parameterNames.hasMoreElements()){
    //参数名字
    String name = parameterNames.nextElement();
    //根据参数名字获取参数值
    String parameter = request.getParameter(name);
    System.out.println(name+"---->"+parameter);
    }

    //获取所有参数的map集合
    Map<String, String[]> parameterMap = request.getParameterMap();
    //获取键值
    Set<String> keySet = parameterMap.keySet();
    //根据键值获取值
    for (String name : keySet) {
    String[] values = parameterMap.get(name);
    for (String value : values) {
    System.out.println(value);
    }
    }
    }
  • 请求转发:一种在服务器内部的资源跳转方式

    1. 通过request对象获取请求转发器对象

      RequestDispatcher getRequestDispacher(String path):参数为转发资源的路径

    2. 使用RequestDispatcher对象进行转发

      forward(ServletRequest request, ServletResponse response)

    1
    request.getRequestDispatcher("/requestdemo5").forward(request,response);
    1. 特点
      • 浏览器地址栏路径不发生变化
      • 只能转发到当前服务器内部资源中
      • 转发是一次请求
  • 共享数据

    • 域对象:一个有作用范围的对象,可以在范围内共享数据
    • request域:代表一次请求,一般用于请求转发的多个资源中共享数据
    • 方法
      1. setAttribute(String name,Object obj):存储数据
      2. Object setAttribute(String name):通过键获取值
      3. removeAttribute(String name):通过键移除键值对
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    @WebServlet("/requestdemo4")
    public class requestdemo4 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //设置request域
    request.setAttribute("msg","hxx");
    //转发到demo5
    request.getRequestDispatcher("/requestdemo5").forward(request,response);
    }
    }

    @WebServlet("/requestdemo5")
    public class requestdemo5 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    System.out.println("demo5--------");
    //获取request域值
    Object msg = request.getAttribute("msg");
    System.out.println(msg);

    }
    }
  • 获取ServletContext对象

    • servletContext getServletContext()