• HTTP


    HTTP

    1. 概念

    超文本传输协议(HyperText Transport Protocol),基于TCP/IP的应用层协议,默认端口号是80,基于请求响应模型(一次请求对应一次响应),是无状态的(每次请求是项目独立的)。

    1. 1.0版本:每次请求响应都会建立一次HTTP连接
    2. 1.1版本:HTTP连接会被复用,一次连接可以传输多次数据

    2. Request对象和Response对象

    1. 服务器在收到一次请求消息后做的事情:
      1. Tomcat服务器根据请求URL的资源路径创建对应的Servlet对象
      2. Tomcat服务器创建Request对象和Response对象,其中在Request对象中封装请求消息数据
      3. Tomcat将Request对象和Response对象传递给service方法,并且通过Servlet对象调用该方法
      4. 在该方法中,可以根据Request对象获取请求消息数据,并通过Response对象设置响应消息数据
      5. 服务器在给浏览器做出响应之前会从Response对象中得到设置好的响应消息数据

    3. HTTP请求消息数据格式

    1. Request对象的继承体系结构:

      ServletRequest -- 接口
      	|继承
      HttpServletRequest -- 接口
      	|实现
      RequestFacade -- 实现类
      

      该实现类有Apache编写,org.apache.catalina.connector.RequestFacade

    2. 请求行

      请求方法 请求URL 请求协议/版本
      
      1. 请求方法:HTTP有7中请求方式,常用的有两种
        1. GET:
          1. 请求参数在请求行中(在URL后)
          2. 请求的URL长度有限制
          3. 相对没那么安全
        2. POST:
          1. 请求参数在请求体中
          2. 请求URL长度没有限制
          3. 相对安全
    3. 请求头

      请求头名称:请求头值
      

      常用的请求头:

      1. User-Agent:告诉服务器浏览器版本信息
        1. 可以用来解决浏览器版本兼容性问题
      2. Accept:可以接收、解析的信息
      3. Connection:keep-alive,1.1版本、连接复用
      4. Referer:Referer: http://localhost/login.html,告诉服务器,当前请求是从哪里来的
        1. 作用有:防止盗链、统计流量来源数量等
    4. 请求空行:就是一个空行,用来分隔请求头和请求体

    5. 请求体:封装POST请求消息的请求参数的

      1. GET方法没有请求体,POST方法的请求体为 name=值
    6. 一个简单的完整的请求消息如下:

      POST /demo3 HTTP/1.1 -- 请求行
      Host: localhost
      Connection: keep-alive
      Content-Length: 13
      Cache-Control: max-age=0
      Origin: http://localhost
      Upgrade-Insecure-Requests: 1
      Content-Type: application/x-www-form-urlencoded
      User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36
      Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
      x-xyst: KHgiNG8mJjdUdnVPSnIxRYrXQyBkSfrS47T_FU7_372biFAU4QMaRw==
      Referer: http://localhost/login.html
      Accept-Encoding: gzip, deflate, br
      Accept-Language: en-US,en;q=0.9,is;q=0.8,zh;q=0.7,zh-CN;q=0.6,zh-TW;q=0.5,ja;q=0.4,nl;q=0.3
      Cookie: Idea-ba272247=a33d6b38-3af8-4b08-b337-f1e8c3cc1311; JSESSIONID=F43308216BD55AAF85AF182BEA04824F
      														-- 请求空行
      														
      username=bobby -- 请求体
      
      

    4.Request对象的功能

    1. 获取请求消息数据

      1. 获取请求行数据,假如请求行是这个:GET /servlet/demo3?username=aaa HTTP/1.1

        1. 获取请求方式(GET):String getMethod()
        2. (*)获取虚拟目录(/servlet):String getContextPath(),一般用来动态获取虚拟目录,而不是写死。
        3. 获取Servlet路径(/demo3):String getServletPath()
        4. 获取get方式的请求参数(username=aaa):String getQueryString()
        5. (*)获取请求的URI(/servlet/demo3)
          1. String getRequestURI(): /servlet/demo3
          2. String getRequestURL(): http://localhost/servlet/demo3
        6. 获取协议版本(HTTP/1.1):String getProtocol()
        7. 获取客户机的IP地址:String getRemoteAddr()
      2. 获取请求头数据

        1. String getHeader(String name):根据请求头名称,获取请求头的值
        2. Enumeration< String > getHeaderNames():获取所有的请求头名称
      3. 获取请求体的数据

        1. 只有POST方法才有请求体,在请求体中封装了POST请求的请求参数

        2. 步骤:

          1. 获取流对象

            1. BufferReader getReader():获取字符输入流,只能操作字符数据
            2. ServletInputStream getInputStream():获取字节输入流,可以操作所有的数据类型
          2. 从流对象里拿到参数数据

            protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                BufferedReader br = request.getReader();
                String str = null;
                while ((str = br.readLine()) != null) {
                    System.out.println(str);// username=bbbb&password=bbbb
                }
            }
            
    2. 其他的功能

      1. 获取请求参数的通用方式(兼容GET和POST)

        1. String getParameter(String name) :根据参数名获取参数值
        2. String[] getParameterValues(String name):根据参数名获取参数值的数组,针对复选框的情况
        3. Enumeration< String > getParameterNames():获取所有请求的参数名
        4. Map<String, String[]> getParameterMap():获取所有参数的map集合

        注意:获取请求参数时会可能出现乱码情况,修改编码格式即可:

        request.setCharacterEncoding("utf-8"); -- utf-8为输入参数的注册页面格式
        
      2. 请求转发:一种在服务器内部的资源跳转方式

        1. 通过request对象获取请求转发器对象:RequestDispatcher getRequestDispatcher(String path)

        2. RequestDispatcher对象调用forward方法进行转发:forward(ServletRequest request,ServletResponse)

          System.out.println("demo8888888888888888");
          request.getRequestDispatcher("/requestDemo7").forward(request,response);
          
          // 这样不仅可以访问到demo8,还可以访问到demo7,因为在demo8里请求转发到demo7
          
        3. 请求转发的特点:

          1. 浏览器地址栏的路径不会改变
          2. 只能请求转发本服务器内部的资源,不能请求其他资源
          3. 转发只是一次请求,不会因为访问了多个资源就是多个请求
      3. 共享数据:请求转发实际上是两个Servlet之间的通信,可以使用共享数据的方法进行通信,一个Servlet了可以存储数据,另一个Servlet可以读取数据

        1. 域对象:一个有作用范围的对象,可以在范围内共享数据
        2. request域:值得是一次请求的范围,该范围可以因为请求转发而被扩大,一般用于在发生请求转发的多个资源中进行数据的共享。
        3. 方法:
          1. void setAttribute(String name, Object obj):存储数据
          2. Object getAttribute(String name):根据键获取数据
          3. void removeAttribute(String name):根据键移除数据
      4. 获取ServletContext

        1. 方法:servletContext getServletContext()

    5. HTTP响应消息的数据格式

    1. 响应行

      HTTP/1.1 200 OK
      

      组成:协议版本、响应的状态码、响应的状态

      状态码对应的状态:

      1. 1XX:服务器接收到信息,但是没有完成,在等待一段时间后,发送1XX给客户端
      2. 2XX:成功,如:200
      3. 3XX:重定向,如:302(重定向)、304(访问缓存)
      4. 4XX:客户端错误,如:404(访问路径没有对应资源)、405(请求方法没有对应的doGet或者doPost方法)
      5. 5XX:服务器内部出现异常,如:500(服务器内部出现异常)
    2. 响应头

      Content-Type: text/html;charset=UTF-8
      Content-Length: 101
      Date: Thu, 25 Apr 2019 07:43:37 GMT
      

      格式:响应头名称:响应值

      常见的响应头:

      1. Content-Type:服务器告知客户端本次响应的数据格式以及编码方式
      2. Content-Length:响应体的长度,以字节为单位
      3. Content-disposition:服务器告诉客户端以什么格式打开响应体的数据
        1. 值为 in-line:默认值,在当前页面打开响应体
        2. 值为 attachment;filename=xxx:以附件形式打开响应体,一般用于文件下载
    3. 响应空行

    4. 响应体:真实的传输的数据

      <html>
        <head>
          <title>index.jsp</title>
        </head>
        <body>
          response.jsp
        </body>
      </html>
      

    6. Response对象的功能

    1. 设置响应消息

      1. 设置响应行:HTTP/1.1 200 OK
        1. 设置状态码:setStatus(int sc)
      2. 设置响应头:setHeader(String name, String value)
      3. 设置响应体:
        • 使用步骤:
          1. 获取输出流
            1. 获取字节输出流:ServletOutputStream getOutputStream()
            2. 获取字符输出流:PrintWriter getWrite()
          2. 使用输出流影数据输出到浏览器
    2. Response对象的功能:

      1. 实现重定向

        1. 代码实现
        response.setStatus(302);
        response.setHeader("location", "/response/ResponseDemo2");
        /***********或者**************/
        response.sendRedirect("/response/ResponseDemo2");
        
        1. 重定向和转发的区别

          重定向(redirect) 转发(forward)
          地址栏发生变化 地址栏不发生变化
          可以访问其他站点的资源 只能访问本服务器内部的资源
          重定向是两次请求 转发是一次请求

          解析:由于转发是一次请求,因此可以使用Request对象来共享数据,但是重定向是两次请求,因此有两个Request对象,不能通过Request对象共享数据。

        2. 路径的写法:

      2. 输出数据

        1. 服务器输出字符到浏览器:

          //获取字符输出流之前先设置编码格式为utf-8,避免中文乱码
          response.setContentType("text/html; charset=utf-8");
          PrintWriter writer = response.getWriter();
          writer.write("<h1>我写几个中文吧,hello, i am a response message!</h1>");
          
        2. 服务器输出字节浏览器:(一般用来输出图片等信息)

          response.setContentType("text/html; charset = utf-8");
          ServletOutputStream os = response.getOutputStream();
          os.write("猪八戒".getBytes());
          
        3. 验证码的小demo

          @WebServlet("/checkCodeServlet")
          public class CheckCodeServlet extends HttpServlet {
              protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                  this.doGet(request, response);
              }
          
              protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                  int width  = 100;
                  int height = 50;
                  BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
          
                  // 填充背景色
                  Graphics graphics = image.getGraphics();
                  graphics.setColor(Color.pink);
                  graphics.fillRect(0, 0, width, height);
          
                  // 画边框
                  graphics.setColor(Color.BLUE);
                  graphics.drawRect(0, 0, width - 1, height - 1);
          
                  // 随机画四个字母
                  String str = "ABCDEFGHIJKLMNOPQTSTUVWXYZabcdefghijkilmnopqrstuvwxyz0123456789";
                  Random random = new Random();
                  for(int i = 1; i < 5; i++) {
          
                      int index = random.nextInt(str.length());
                      char c = str.charAt(index);
                      graphics.drawString(c+"", i * 20, height / 2);
                  }
          
                  // 随机画干扰线
                  graphics.setColor(Color.GREEN);
                  for(int i = 0; i < 15; i++) {
                      int x1 = random.nextInt(width);
                      int y1 = random.nextInt(height);
                      int x2 = random.nextInt(width);
                      int y2 = random.nextInt(height);
                      graphics.drawLine(x1, y1, x2, y2);
                  }
          
                  boolean jpg = ImageIO.write(image, "jpg", response.getOutputStream());
              }
          }
          

          验证码切换

          <script>
              window.onload = function () {
                  var image = document.getElementById("checkCode");
                  image.onclick = function () {
                      // 由于其实每次都是访问一样的Servlet,因此要加时间戳,欺骗服务器每次请求不一样,这样就可以不访问浏览器的本地缓存
                      var date = new Date().getTime();
                      image.src = "/response/checkCodeServlet" + "?" + date;
                  }
                  
                  var link = document.getElementById("change");
                  link.onclick = function () {
                      var date = new Date().getTime();
                      image.src = "/response/checkCodeServlet" + "?" + date;
                  }
              }
          </script>
          

    7. ServletContext对象

    ServletContext对象概念:ServletContext用来存放全局变量,每个Java虚拟机每个Web项目只有一个ServletContext,这个ServletContext是由Web服务器创建的,来保证它的唯一性。由于一个WEB应用中的所有Servlet共享同一个ServletContext对象,因此Servlet对象之间可以通过ServletContext对象通讯。ServletContext对象通常也被称之为Context域对象。来源:JAVA School

    1. 获取ServletContext对象:要注意两种方法获取的ServletContext对象是同一个,因为一个项目就唯一的一个Servlet对象。

      • Request对象的getServletContext方法

        ServletContext context1 = request.getServletContext();
        
      • HttpServlet对象的方法(自己写的Servlet继承了HttpServlet)

        ServletContext context2 = this.getServletContext();
        
    2. 获取MIME类型

      1. MIME(Multipurpose Internet Mail Extensions)类型

              最早的HTTP协议中,并没有附加的数据类型信息,所有传送的数据都被客户程序解释为超文本标记语言HTML 文档,而为了支持多媒体数据类型,HTTP协议中就使用了附加在文档之前的MIME数据类型信息来标识数据类型。MIME意为多功能Internet邮件扩展,它设计的最初目的是为了在发送电子邮件时附加多媒体数据,让邮件客户程序能根据其类型进行处理。然而当它被HTTP协议支持之后,它的意义就更为显著了。它使得HTTP传输的不仅是普通的文本,而变得丰富多彩。每个MIME类型由两部分组成,前面是数据的大类别,例如声音audio、图象image等,后面定义具体的种类。
        常见的MIME类型(通用型):
        超文本标记语言文本 .html text/html
        xml文档 .xml text/xml
        XHTML文档 .xhtml application/xhtml+xml
        普通文本 .txt text/plain
        RTF文本 .rtf application/rtf
        PDF文档 .pdf application/pdf
        Microsoft Word文件 .word application/msword
        PNG图像 .png image/png
        GIF图形 .gif image/gif
        JPEG图形 .jpeg,.jpg image/jpeg
        au声音文件 .au audio/basic
        MIDI音乐文件 mid,.midi audio/midi,audio/x-midi
        RealAudio音乐文件 .ra, .ram audio/x-pn-realaudio
        MPEG文件 .mpg,.mpeg video/mpeg
        AVI文件 .avi video/x-msvideo
        GZIP文件 .gz application/x-gzip
        TAR文件 .tar application/x-tar

      2. ServletContext对象获取MIME类型的方法

        1. String getMimeType():

          String filename = "p.jpg";
          String mimeType = context1.getMimeType(filename);
          System.out.println(mimeType);
          //输出 image/jpeg ,表明JPG文件的MIME类型是 image/jpeg
          
      3. 域对象:共享数据

        ServletContext域代表着整个web项目,这个域是最大的,可以共享所有用户所有请求的数据,该对象的声明周期很长,从服务器启动到服务器关闭,一般来说使用该对象存储数据应该谨慎,因为很容易就造成服务器的压力。和Request域类似,也是有三个方法存储数据,获取数据,移除数据:

        1. void setAttribute(String name, Object obj):存储数据
        2. Object getAttribute(String name):根据键获取数据
        3. void removeAttribute(String name):根据键移除数据
      4. 获取文件的真实路径(Tomcat服务器路径)

        1. 方法:String getRealPath(String 资源名称)

          返回资源的真实路径, 根据资源的具体位置不同不同参数有不同的写法,资源位置一般是在:

          • web目录下:"/a.txt"
          • web目录下的WEB-INF目录下:"/WEB-INF/a.txt"
          • src目录下:"/WEB-INF/classes/a.txt"
            • 当然src下的资源还可以通过classloader来获取
  • 相关阅读:
    网络层-数据平面:路由器工作原理
    文件系统和目录:目录
    文件系统与目录:文件系统
    运输层-可靠数据传输原理:选择重传 Selective Repeat Protocol
    运输层-可靠数据传输原理:回退N步 Go-Back_N Protocol
    JAVA学习笔记之多态
    约瑟夫环的递归解法C
    题目:汉诺塔问题
    题目:在同一坐标中输出sinx和cosx两条曲线
    n!的溢出问题及处理
  • 原文地址:https://www.cnblogs.com/zhuobo/p/10776798.html
Copyright © 2020-2023  润新知