JavaWeb之04_http

HTTP协议


落叶他乡树,寒灯独夜人

一、概述

1. 概念

  • 1)HTTP:Hyper Text Transfer Protocol,超文本传输协议
  • 2)传输协议:定义了客户端和服务端通信时,发送数据的格式
  • 3)特点:
    • 基于TCP/IP的高级协议
    • 默认端口:80
    • 基于请求 / 响应模型,一一对应
    • 无状态的协议,每次请求相互独立,不能交互数据
  • 4)历史版本:
    • 1.0:每一次请求响应都会建立一次连接
    • 1.1:复用连接

2 .请求格式

2.1 请求消息数据格式

① 请求行:请求方式 请求url 请求协议/版本

  • 1)例如:GET /login.html HTTP/1.1

  • 2)请求方式(7中):

    • GET:
      • 请求参数在请求行中。在url后
      • 请求的url长度又限制
      • 不太安全
    • POST
      • 请求参数在请求体中
      • 请求的url长度没有限制
      • 相对安全

② 请求头:请求头名称:请求头值

  • 1)常见的请求头
    • **1.(★)User-Agent:**浏览器告诉服务器,我访问你使用的浏览器版本信息
      • 可以在服务器端获取该头的信息,解决浏览器的兼容性问题
    • 2.Accept:浏览器可以解析哪种格式的信息
    • 3.Accept-Language:浏览器支持语言
    • 4.Accept-Encoding:浏览器支持压缩格式
    • **5.(★)Referer:**告诉服务器,当前请求从哪里来
      • 作用:
        • 防盗链
        • 统计工作
    • 6.Connection:连接

③ 请求空行

  • 空行,用于分割请求头和请求体

④ 请求体(正文)

  • 封装POST请求消息的请求体(请求参数)的
  • GET没有请求体
2.2 响应消息数据格式

① 响应行

  • 1)组成:协议/版本 响应状态码 状态码描述
    • 例如:HTTP/1.1 200 OK
  • 2)响应状态码:服务器告诉客户端浏览器本次请求和响应的一个状态
    • 1xx:服务器接收客户端消息,但没有接收完成,等待一段时间后,发送1xx状态码
    • 2xx:成功。代表:200
    • 3xx:重定向。代表:302(重定向)、304(访问缓存)
    • 4xx:客户端错误。代表:404(请求路径无对应资源)、405(没有对应的请求方式的方法)
    • 5xx:服务器错误。代表:500(服务器内部异常)

② 响应头

  • 1)组成:头名称:值
  • 2)常见响应头
    • Content-Type:服务器告诉客户端本次响应体的数据格式
    • Content-Length:字节个数
    • Date:日期
    • Content-disposition:服务器告诉客户端以什么格式打开响应体数据
      • 默认:in-line,在当前页面内打开
      • attachment;filename=xxx:以附件形式打开响应体。文件下载

③ 响应空行

④ 响应体

  • 传输的数据

二、Request

1. 概念

① request和response的原理

  • 1)request和response对象时由服务器创建的。我们来使用
  • 2)request对象时获取请求消息,response对象时来设置响应消息
  • 在这里插入图片描述

② request对象继承体系结构

  • ServletRequest(接口)—> HttpServletRequest(接口)—> org.apache.catalina.connector.RequestFacade(类)

2. 功能

① 获取请求行

  • 1)格式:GET /day14/demo1?name=zhangsan HTTP/1.1

  • 2)方法:

    • ① 获取请求方式:String getMethod():(GET)
    • (★)获取虚拟目录String getContextPath():(/day14)
    • ③ 获取servlet路径:String getServletPath():(/demo1)
    • ④ 获取get方式的请求参数:String getQueryString():(name=zhangsan)
    • (★)获取请求uriString getRequestURI():(/day14/demo1)
      • URL:String getRequestURL():(http://localhost/day14/demo1)
    • ⑥ 获取协议及版本:String getProtocol():(HTTP/1.1)
    • ⑦ 获取客户机IP地址:String getRemoteAddr()
  • 3)URL、RUI的区别

    • URL:统一资源定位符:http://localhost/day14/demo1
    • URI:统一资源标识符:/day14/demo1
  • 4)代码:

    • String method = req.getMethod();
      System.out.println("method = " + method);
      
      String contextPath = req.getContextPath();
      System.out.println("contextPaht = " + contextPath);
      
      String servletPath = req.getServletPath();
      System.out.println("servletPath = " + servletPath);
      
      String queryString = req.getQueryString();
      System.out.println("queryString = " + queryString);
      
      String requestURI = req.getRequestURI();
      System.out.println("requestURI = " + requestURI);
      
      StringBuffer requestURL = req.getRequestURL();
      System.out.println("requestURL = " + requestURL);
      
      String protocol = req.getProtocol();
      System.out.println("protocol = " + protocol);
      
      String remoteAddr = req.getRemoteAddr();
      System.out.println("remoteAddr = " + remoteAddr);
      

② 获取请求头

  • 1)方法

    • (★)String getHeader(String name):通过请求头的名称获取请求头的值
    • Enumeration<String> getHeaderNames():获取所有请求头的名称
    • 注:Enumeration可以当作迭代器使用
  • 2)代码

    • //1.获取所有请求头名称
      Enumeration<String> headerNames = request.getHeaderNames();
      
      //2.遍历
      while (headerNames.hasMoreElements()) {
          String name = headerNames.nextElement();
          //根据名称获取请求头的值
          String value = request.getHeader(name);
          System.out.println(name + " = " + value);
      }
      

③ 获取请求体

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

  • 2)步骤:

    • 获取流对象(字节流、字符流)
      • Buffered getReader():注册字符
      • ServletInputStream getInputStream():处理任意类型
        • 文件上传中学习
    • 从流对象中读取数据
  • 3)代码

    • //1.获取字符流
      BufferedReader br = request.getReader();
      
      //2.读取数据
      String data = null;
      while ((data = br.readLine()) != null) {
          System.out.println(data);
      }
      

3. 其他功能(★)

① 获取请求参数(通用)

  • String getParameter(String name):根据参数名称获取参数值

  • String[] getParameterValues(String name):根据参数名称获取参数值的数值

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

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

  • 中文乱码问题:

    • get方式:tomcat8已经解决参数乱码问题
    • post方式:在获取参数前设置request的流的编码(因为post获取参数的方式是先获取流,在获取参数)
      • request.setCharacterEncodinf("utf-8")

② 请求转发

  • 1)定义:一种在服务器内部的资源跳转方式

  • 2)步骤:

    • 通过request对象获取请求转发器对象:RequestDispatcher getRequestDispatcher(String path)
    • 使用RequestDispatcher 对象进行转发:forward(ServletReuqest req, ServletResponse resp)
  • 3)特点

    • 浏览器地址栏路径没有发送变化
    • 只能转发到当前服务器内部资源中
    • 转发是一次请求(可以在request域中共享数据)
  • 4)代码

    • //转发资源
      RequestDispatcher requestDispatcher = request.getRequestDispatcher("/requestDemo4_2");
      requestDispatcher.forward(request, response);
      

③ 共享数据

  • 1)概念:
    • 域对象:一个有作用范围的对象,可以在范围内共享数据
    • request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据
  • 2)方法
    • setAttribute(String name, Object obj):存储数据
    • Object getAttribute(String name):通过键获取对象
    • removeAttribute(String name):通过键移除键值对

④ 获取ServletContext对象

  • 方法:ServletContext getServletContext()
  • 功能:详情(看四)

三、Response

1. 概念

2. 功能

① 设置响响应行

  • 1)格式:HTTP/1.1 200 OK
  • 2)设置状态码:setStatus(int sc)

② 设置响应头

  • 1)方法
    • setHeader(String name, String value)

③ 设置响应体

  • 1)步骤
    • 获取输出流
      • 字节输出流:ServletOutputStream getOutputStream()
      • 字符输出流:PrintWriter getWriter()
    • 使用输出流将数据输出到客户端

3. 案例

① 完成重定向

  • 1)重定向:资源跳转的方式。状态码302

  • 2)方式一:

    • /*
      * 方式一:设置状态码,设置响应头
      * */
      //1.设置状态码
      response.setStatus(302);
      
      //2.设置响应头
      response.setHeader("location", "/servlet/responseDemo1_2");
      
  • 3)方式二:

    • /*
      * 方式二:sendRedirect(资源路径)
      * */
      response.sendRedirect("/servlet/responseDemo1_2");
      
  • 4)特点

    • 重定向特点:
      • 地址栏发生变化
      • 可以访问其他站点(服务器)资源
      • 重定向是两次请求,意味着不可以使用request域对象共享数据
    • 转发特点:
      • 地址栏路径不变
      • 只能访问当前服务器下的资源
      • 转发时一次请求,意味着可以使用request域对象共享数据
  • 5)路径写法

    • 相对目录:找到当前目录与目标资源之间的相对位置关系
    • 绝对目录:
      • 给客户端用(当前请求从浏览器发出):需要加虚拟目录
      • 给服务器用(当前请求从服务器发出):不需要加虚拟目录
    • 例如:
      • 重定向(当前请求从浏览器发出):
        • 需要加虚拟目录:response.sendRedirect("/servlet/responseDemo1_2");
      • 请求转发(当前请求从服务器发出):
        • 不需要虚拟目录:request.getRequestDispatcher("/requestDemo4_2").forward(request, response)

② 服务器输出字符数据到浏览器

  • 1)代码

    • //1.获取字符输出流
      PrintWriter writer = response.getWriter();
      
      //2.输出数据
      writer.write("hello ...");
      writer.write("中文测试 ...");
      
  • 2)中文乱码:

    • 原因:浏览器默认编码为系统编码(GBK),而服务器中response.getWriter();获取的流的编码为tomcat编写时的编码(ISO-8859-1)。由于编码与解码方式不一致,故导致中文乱码。
    • 解决1:在获取流之前设置编码为浏览器默认编码(GBK):response.setCharacterEncoding("gbk");
    • 解决2:或者设置响应头的Content-Tyoe告诉浏览器本次响应的数据格式
    • 解决3(★):直接设置:response.setContextType("text/html;charset=utf-8")

③ 服务器输出字节数据到浏览器

  • 1)代码

    • //0.设置响应头,防止乱码
      response.setContentType("text/html;charset=utf-8");
      
      //1.获取字节输出流
      ServletOutputStream os = response.getOutputStream();
      
      //2.输出数据
      os.write("你好!".getBytes("utf-8"));
      

④ 验证码

  • 本质:图片

  • 目的:防止恶意的表单注册

  • 代码:

    • servlet:

      • @WebServlet("/checkCode")
        public class Test05_CheckCode extends HttpServlet {
            @Override
            protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                int width = 100;
                int height = 50;
                //1.创建对象,在内存中画图(验证码图片对象)BufferedImage
                BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
        
        
                //2.美化图片
                //2.1填充画笔色
                Graphics g = image.getGraphics(); //画笔对象
                g.setColor(Color.pink);
                g.fillRect(0, 0, width, height);
                //2.2画边框
                g.setColor(Color.blue);
                g.drawRect(0, 0, width - 1, height - 1);
                //2.3写验证码
                String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
                Random ran = new Random();
        
                for (int i = 1; i <= 4; i++) {
                    int index = ran.nextInt(str.length());
                    char ch = str.charAt(index);//随机字符
                    g.drawString(ch+"", width/5*i, height/2);
                }
                //2.4画干扰线
                g.setColor(Color.green);
                for (int i = 0; i < 10; i++) {
                    int x1 = ran.nextInt(width);
                    int x2 = ran.nextInt(width);
                    int y1 = ran.nextInt(height);
                    int y2 = ran.nextInt(height);
                    g.drawLine(x1,y1,x2,y2);
                }
        
                /*
                * 3.将图片输出到页面展示
                * ImageIO对象,可以将图片写入到任意流
                * */
                ImageIO.write(image, "jpg", resp.getOutputStream());
            }
        
            @Override
            protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                this.doPost(req, resp);
            }
        }
        
    • html

      • <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <title>验证码案例</title>
        
            <script>
                /*
                * 分析:点击超链接或者图片,需要换一张图片
                *   1.给超链接和图片绑定单击事件
                *   2.重新设置图片的src属性值
                * */
                window.onload = function () {
                    //1.获取图片对象
                    var img = document.getElementById("checkCode");
                    //2.绑定单击事件
                    img.onclick = function () {
                        //加时间戳
                        var date = new Date().getTime();
                        img.src = "/servlet/checkCode?" + date;
                    }
                }
        
            </script>
        
        </head>
        <body>
        
            <img src="/servlet/checkCode">
            <a href="">看不清?换一张!</a>
        
        </body>
        </html>
        

四、ServletContext

1. 概念

  • ServletContext:代表整个web应用,可以和程序的容器(服务器)通信

2. 获取

  • 1)request.getServletContext()
  • 2)通过HttpServletContext获取:this.getServletContext()

3. 功能

  • 1)获取MIME类型
  • 2)域对象:共享数据
  • 3)获取文件的真实路径(服务器路径)(★)

① 获取MIME类型

  • 1)MIME类型:在互联网通信过程中定义的一种文件数据类型

    • 格式:大类型/小类型,如:text/html
  • 2)方法:

    • String getMimeType(String file)
    • 该方法为什么能获取MIME类型?
      • 因为MIME类型存储在服务器的web.xml文件中,而ServletContext对象能和服务器通信,所有该方法可以获取MIME类型
  • 3)使用:

    • //1.获取ServletContext对象
      ServletContext context = this.getServletContext();
      //2.定义文件名称。在开发中获取文件名称
      String filenamt = "a.jpg";
      //3.获取MIME类型
      String mimeType = context.getMimeType(filename);
      System.out.println(mimeType); //输出:image/jpg
      

② 域对象:共享数据

  • 1)方法
    • setAttribute(String name, Object value)
    • getAttribute(String name)
    • removeAttribute(String name)
  • 2)范围:
    • 所有用户请求的数据

③ 获取文件的真实路径(服务器路径)(★)

  • 1)方法:

    • String getRealPath(String path)
  • 2)使用

    • ServletContext context = this.getServletContext();
      //获取web目录下的文件路径
      String apath = context.getRealPath("/a.txt");
      
      //获取web/WEB-INF目录下的文件
      String bpath = context.getRealPath("/WEB-INF/b.txt");
      
      //获取src目录下的文件
      //java文件生成的class文件在服务器部署中会放在WEB-INF目录下的classes文件夹中
      //故src下的配置文件会放在WEB-INF/classes中
      String cpath = context.getRealPath("/WEB-INF/classes/c.txt");
      

五、案例

1. 文件下载

① 需求

  • 1)页面显示超链接
  • 2)点击超链接后弹出下载提示框
  • 3)完成图片文件下载

② 分析

  • 1)超链接指向的资源如果能够被浏览器解析,则在浏览器中展示;不能被解析,则弹出下载提示框。不满足需求
  • 2)需要任何资源都必须下载提示框
  • 3)使用响应头设置资源的打开方式
    • content-disposition:attachment;filename=xxx

③ 实现

  • 1)定义页面,编辑超链接href属性,指向servlet,传递资源名称filename
  • 2)定义servlet
    • 获取文件名称
    • 加载文件进内存(字节输入流)
    • 设置响应头,以附件形式打开文件
    • 将数据写出到response输出流

④ 文件名中文乱码问题

  • 1)需要根据不同浏览器,设置中文文件名的编码格式
    EB-INF目录下的classes文件夹中
    //故src下的配置文件会放在WEB-INF/classes中
    String cpath = context.getRealPath("/WEB-INF/classes/c.txt");
    
    
    
    

五、案例

1. 文件下载

① 需求

  • 1)页面显示超链接
  • 2)点击超链接后弹出下载提示框
  • 3)完成图片文件下载

② 分析

  • 1)超链接指向的资源如果能够被浏览器解析,则在浏览器中展示;不能被解析,则弹出下载提示框。不满足需求
  • 2)需要任何资源都必须下载提示框
  • 3)使用响应头设置资源的打开方式
    • content-disposition:attachment;filename=xxx

③ 实现

  • 1)定义页面,编辑超链接href属性,指向servlet,传递资源名称filename
  • 2)定义servlet
    • 获取文件名称
    • 加载文件进内存(字节输入流)
    • 设置响应头,以附件形式打开文件
    • 将数据写出到response输出流

④ 文件名中文乱码问题

  • 1)需要根据不同浏览器,设置中文文件名的编码格式
  • 2)网上有很多这样的解决办法:工具类(DownLoadUtils)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值