zoukankan      html  css  js  c++  java
  • JavaWeb

    1.响应消息数据格式

       1. 响应行

        1. 组成:协议 / 版本 响应状态码 状态码描述  如:HTTP/1.1  200 OK

        2. 响应状态码:服务器告诉客户端浏览器本次请求和响应的一个状态

          1. 状态码都是3位数字

          2. 分类:

            1. 1xx:服务器接收客户端消息,但没有接收完成,等待一段时间后,发送1xx多状态码

            2. 2xx:成功。代表:200

            3. 3xx:重定向。代表:302(重定向) 304(访问缓存)

            4. 4xx:客户端错误。代表:404(请求路径没有对应的资源)405(请求方式没有对应的doXxx方法)

            5. 5xx:服务器端错误。代表:500(服务器内部出现异常)

      2. 响应头

        1. 格式:头名称:值

        2. 常见的响应头:

          1. Content - Type:服务器告诉客户端本次响应消息体数据格式以及编码格式

          2. Content - disposition:服务器告诉客户端以什么格式打开响应体数据

            * 值:

              * in - line:默认值,在当前页面内打开

              * attachment(filename=xxx):以附件形式打开响应体。文件下载时使用

      3. 响应空行

      4. 响应体

      * 字符串格式:

    2.Response

      * 功能:设置相应消息

        1. 设置响应行

          1. 格式: HTTP/1.1 200 ok

          2. 设置状态码:setStatus(int sc)

        2. 设置响应头

          1. setHeader(String name,String value)

        3. 设置响应体

          * 使用步骤:

            1. 获取输出流

              * 字符输出流:PrintWriter getWriter()

              * 字节输出流:ServletOutputStream getOutputStream()

            2. 使用输出流,将数据输出到客户端浏览器

    response.setStatus(302);
    response.setHeader("location","/web_servlet/respnseDemo01")

      ### 简单的重定向方法:sendRedirect()

      * 重定向的特点:

        1. 地址栏发生变化

        2. 重定向可以访问其他站点(服务器)的资源

        3. 重定向是两次请求。不能使用request域来共享数据了

      * 转发的特点:

        1. 转发地址栏路径不变

        2. 转发只能访问当前服务器下的资源

        3. 转发是一次请求,可以使用request对象来共享数据

      * 面试题:forward和redirect的区别,既转发和重定向的区别

      * 路径写法:

        1. 路径分类

          1. 相对路径:通过相对路径不可以确定唯一资源

            * 如: . / index.html 或 ../ index.html

            * 不以 / 开头,以 . 开头

            * 规则:找到访问当前资源和目标资源的相对位置关系  . / 代表当前目录  . . / 代表后退一级的目录

          2. 绝对路径:通过绝对路径可以确定唯一资源

            * 如: http://localhost/web_servlet/ResponseDemo01   或 /web_servlet/ResponseDemo01

            * 以 / 开头的路径

            * 规则:判断定义的路径是给谁用的?判断请求将来从哪发出

              * 给客户端浏览器使用:需要加虚拟目录(项目的访问路径),重定向就是客户端发出的,需要加虚拟目录 

                * 建议:之后动态获取虚拟目录 request.getContextPath() 来获取

                * 如:<a> <href> 重定向

              * 给服务器使用:不需要加虚拟目录  如:转发路径

              

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

      * 步骤:

        1. 获取字符输出流

        2. 输出数据 

      * 注意:

        * 乱码问题:

          1. PrintWriter pw = response.getWriter(); 获取的流的默认编码是ISO-8859-1的拉丁编码

          2. 设置该流的默认编码和响应体数据使用的编码:response.setContentType("text/html;charset=utf-8"); 在获取流之前设置

     @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
            //告诉浏览器,服务器发送的消息体数据的编码
            response.setHeader("Content-type","text/html;charset=utf-8");
    
            //简单形式设置编码
            response.setContentType("text/html;charset=utf-8");
    
            //1.获取字符输出流
            PrintWriter pw = response.getWriter();
    
            //2.输出数据
            pw.write("hello response");
        }

     4. 案例:验证码

      1. 本质:图片

      2. 目的:防止恶意表单注册

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script>
            window.onload = function () {
                // 1.获取图片对象
                var img = document.getElementById("checkcode");
                // 2.绑定单击事件
                img.onclick = function () {
                    //加时间戳
                    var date = new Date().getTime();
                    //因为浏览器会从缓存里拿图片,而不是重新请求,所以我们修改路径,通过传参,达到修改了路径
                    img.src= "/servlet3/checkCode?" + date;
                };
    
                document.getElementById("change").onclick = function () {
                    // 1.获取图片对象
                    var img = document.getElementById("checkcode");
                    //加时间戳
                    var date = new Date().getTime();
                    //因为浏览器会从缓存里拿图片,而不是重新请求,所以我们修改路径,通过传参,达到修改了路径
                    img.src= "/servlet3/checkCode?" + date;
                }
            }
    
        </script>
    </head>
    <body>
        <img id="checkcode" src="/servlet3/checkCode">
        <a id="change" href="">看不清,换一张</a>
    </body>
    </html>
    注册页面
    package web.servlet;
    
    import javax.imageio.ImageIO;
    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.awt.*;
    import java.awt.image.BufferedImage;
    import java.io.IOException;
    import java.util.Random;
    
    @WebServlet("/checkCode")
    public class CheckCode extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
            int width = 100;
            int height = 50;
            // 1.创建一对象,在内存中的图片(验证码图片对象)
            BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
    
            // 2. 美化图片
            // 2.1 填充背景色
            Graphics graphics = image.getGraphics(); //画笔对象
            // 设置画笔填充颜色
            graphics.setColor(Color.PINK);
            graphics.fillRect(0,0,width,height);
    
            // 2.2 画边框
            graphics.setColor(Color.BLUE);
            graphics.drawRect(0,0,width-1,height-1);
    
    
            String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
            // 生产随机角标
            Random random = new Random();
    
            for (int i = 1; i <= 4; i++) {
                int index = random.nextInt(str.length());
                // 获取字符
                char random_char = str.charAt(index);
                // 2.3 写验证码
                graphics.drawString(random_char+"",width/5*i,height/2);
            }
    
            // 2.4画干扰线
            graphics.setColor(Color.GREEN);
    
            for (int i = 0; i < 10; i++) {
                // 随机生成坐标点
                int x1 = random.nextInt(width);
                int x2 = random.nextInt(width);
                int y1 = random.nextInt(height);
                int y2 = random.nextInt(height);
                graphics.drawLine(x1,y1,x2,y2);
            }
    
            // 3.将图片输出到页面展示
            ImageIO.write(image,"jpg",response.getOutputStream());
    
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doPost(request,response);
        }
    }
    验证码生产的Servlet

    5. ServletContext对象

      1. 概念:代表整个web应用,可以和程序的容器(服务器)来通信

      2. 获取:

        1. 通过request对象来获取

          request.getServletContext();

        2. 通过HttpServlet获取

          this.getServletContext();

      3. 功能:

        1. 获取MIME类型:

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

            * 格式:大类型 / 小类型   text / html   image / jpeg

          * 获取:String getMimeType(String file)

        2. 域对象:共享数据

          1. setAttribute(String name,Object value)

          2. getAttribute(String name)

          3. removeAttribute(String name)

          * ServletContext对象范围:可共享所有用户所有请求的数据

        3. 获取文件的真实(服务器)路径(查看文件的工作空间路径)Using CATALINA_BASE 对应的路径去找 conf / Catalina / localhost 下的xml文档中

          1. 方法:String getRealPath(String  path)

            * web目录下的资源路径写法:/ a.txt

            * WEB - INF目录下的资源路径写法:/ WEB - INF / a.txt

            * src目录下的资源路径写法:WEB - INF / classes / a.txt

    6. 案例:图片及任何文件下载

      * 使用响应头设置资源的打开方式:

        * content - dispostion:attachment;filename=xxx

      * 步骤:

        1. 定义页面,编辑超链接的href属性,指向servlet,传递资源名称filename

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>图片下载</title>
    </head>
    <body>
        <a href="img/九尾.jpg">九尾图片</a>
        <hr/>
        <a href="/case_download/downloadServlet?filename=九尾.jpg">九尾图片</a>
    </body>
    </html>
    下载页面

        2. 定义servlet

          1. 获取文件名称

          2. 使用字节输入流加载文件进内存

          3. 指定response的响应头:content - dispostion:attachment;filename=xxx

          4. 将数据写出到response的输出流

    package download;
    
    import utils.DownLoadUtils;
    
    import javax.servlet.ServletContext;
    import javax.servlet.ServletException;
    import javax.servlet.ServletOutputStream;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.FileInputStream;
    import java.io.IOException;
    
    @WebServlet("/downloadServlet")
    public class DownloadServlet extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // 1.获取请求参数,文件名称
            String filename = request.getParameter("filename");
    
            // 2. 使用字节输入流加载文件进内存
            // 2.1 找到文件的服务器路径
            ServletContext servletContext = this.getServletContext();
            String realPath = servletContext.getRealPath("/img/" + filename);
            // 2.2 用字节流关联
            FileInputStream fis = new FileInputStream(realPath);
    
            //3. 设置response的响应头
            //3.1 设置响应头类型:content-type
            String mimeType = servletContext.getMimeType(filename);//获取文件的mime类型
            response.setHeader("content-type",mimeType);
    
            //3.2 设置响应头打开方式 content-disposition
    
            //解决中文文件名问题
            //1. 获取user-agent请求头
            //2. 使用工具类方法编码文件名
            String agent = request.getHeader("user-agent");
            filename = DownLoadUtils.getFileName(agent, filename);
    
            response.setHeader("content-disposition","attachment;filename="+filename);
    
            //4. 将输入流的数据写入到输出流中
            ServletOutputStream sos = response.getOutputStream();
            byte[] buff = new byte[1024*8];
            int len = 0;
            while ((len = fis.read(buff))!=-1){
                sos.write(buff,0,len);
            }
            fis.close();
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doPost(request,response);
        }
    }
    下载的Servlet

      * 问题:

        * 中文文件名问题:

          * 解决思路:

            1. 获取客户端使用的浏览器版本信息

            2. 根据不同的版本信息,响应不同的数据,设置filename的编码格式不同

    package utils;
    
    import sun.misc.BASE64Encoder;
    import java.io.UnsupportedEncodingException;
    import java.net.URLEncoder;
    import java.util.Base64;
    
    
    public class DownLoadUtils {
    
        public static String getFileName(String agent, String filename) throws UnsupportedEncodingException {
            if (agent.contains("MSIE")) {
                // IE浏览器
                filename = URLEncoder.encode(filename, "utf-8");
                filename = filename.replace("+", " ");
            } else if (agent.contains("Firefox")) {
                // 火狐浏览器
                BASE64Encoder base64Encoder = new BASE64Encoder();
                filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";
            } else {
                // 其它浏览器
                filename = URLEncoder.encode(filename, "utf-8");
            }
            return filename;
        }
    }
    中文乱码utils包,jdk8用,jdk9要转换
  • 相关阅读:
    原型模式
    哈希表原理
    Pow共识算法
    C++虚函数的工作原理
    TCP三次握手与四次分手
    TCP重置报文段及RST常见场景分析
    Ping、Traceroute工作原理
    ARP协议
    Rust生命周期bound用于泛型的引用
    Linux下core dump
  • 原文地址:https://www.cnblogs.com/caixiaowu/p/13300188.html
Copyright © 2011-2022 走看看