• Servlet详解


    一.Servlet生命周期

    • 初始化
    • 提供服务
    • 销毁

    1.测试生命周期

    package com.demo.servlet;
    
    import javax.servlet.*;
    import java.io.IOException;
    
    public class LifeServlet implements Servlet {
        @Override
        public void init(ServletConfig servletConfig) throws ServletException {
            System.out.println("Servlet init");
        }
    
        @Override
        public void service(ServletRequest servletRequest, ServletResponse servletResponse)
                throws ServletException, IOException {
            System.out.println("Servlet service");
        }
    
        @Override
        public void destroy() {
            System.out.println("Servlet destroy");
        }
    
        @Override
        public ServletConfig getServletConfig() {
            return null;
        }
    
        @Override
        public String getServletInfo() {
            return null;
        }
    }
    
    • 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

    2.初始化:init()

    (1)默认情况

    • 默认情况下,第一次被请求的时候初始化,初始化在整个生命中只有一次

    在这里插入图片描述

    (2)设置初始化时间

    • 某种原因,导致第一次请求时初始化很慢,这时就可以修改Servlet的初始化时间

    • 使用其值为大于等于0的整数时,该Servlet就会在服务器启动时初始化,初始化在整个生命中只有一次

    在这里插入图片描述

    3.提供服务:service()

    • 生命周期中会提供n次

    在这里插入图片描述

    4.销毁:destroy()

    • 服务器关闭时自动销毁,生命周期中只有一次

    在这里插入图片描述

    二.Servlet的映射路径

    1.web.xml配置

    (1)标签

    • 的子标签,用于给Servlet配置访问路径

    (2)注意

    1. 路径最前面加上/,代表根目录
    2. 路径中可以出现文件夹的,如/user/test/urlServlet

    (3)示例

    • http://localhost:8888/day02_war_exploded/user/test/lifeServlet
    • http://localhost:8888/day02_war_exploded/user/life.html

    2.模块前端文件的访问路径

    1. 访问文件时,只需要关注自己创建的目录,自动生成的不管
    2. 访问Servlet时,照着url-pattern设置的值来找

    3.Servlet3.0注解配置

    (1)使用前提

    • Servlet3.0和JDK1.5及以后的版本才能使用

    (2)使用

    在这里插入图片描述

    (3)注意

    • 同一个Servlet,要么使用web.xml文件配置,要么使用注解配置,但是不能使用两种方式同时配置

    • 注解中的参数有name、serviceName;若是只写name参数,可以省略key值,只写value;除此之外要写key-value的形式

    三.Servlet请求对象

    1.HttpServletRequest接口

    • 请求对象
    • 父接口:ServletRequest
    • 包含请求行,请求头和请求体

    在这里插入图片描述

    2.请求行

    (1)包含

    • 请求方式
    • 请求的资源
    • 协议及其版本

    (2)获取信息

        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            System.out.println(req.getMethod());
            System.out.println(req.getRequestURL());
            System.out.println(req.getRequestURI());
            System.out.println(req.getServerName());
            System.out.println(req.getServerPort());
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    3.请求头

    (1)获取信息

        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            String value1 = req.getHeader("Host");
            System.out.println(value1);
            Enumeration names = req.getHeaderNames();
            while (names.hasMoreElements()) {
                String name = names.nextElement();
                String value = req.getHeader(name);
                System.out.println(name+":"+value);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    4.请求体

    • 就是请求的数据,也就是Servlet中获取的参数

    (1)Servlet中获取请求的数据的方法

    • request.getParameter(“name属性的值”);返回值类型为String
    • request.getParameterValues(“name属性的值”);返回值类型为String[]

    (2)示例

        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            String username = req.getParameter("username");
            String password = req.getParameter("password");
            String gender = req.getParameter("gender");
            String hobbies[] = req.getParameterValues("hobbies");
            System.out.println(username+","+password+","+gender+","+ Arrays.toString(hobbies));
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    5.Servlet获取参数乱码问题

    (1)问题

    • 中文乱码,Servlet的默认编码集是ISO-8859-1(纯英文)
    • 页面输入中文进行提交,会乱码

    (2)解决方案

    在这里插入图片描述

    四.文件上传

    • 就是在指定的位置复制出一个跟源文件一模一样的文件

    1.页面编写

    • 表单的method属性的值必须是pos
    • 表单上加上enctype,值为multipart/form-data

    在这里插入图片描述

    2.Servlet

    • 在Servlet上加上@MultipartConfig

    在这里插入图片描述

    3.Post方法编写

    • 不同浏览器上传文件的路径不一样
    • 绝对路径(不带盘符)
    • 文件名+文件类型后缀
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            //设置请求体编码集
            req.setCharacterEncoding("utf-8");
            String username = req.getParameter("username");
            String password = req.getParameter("password");
            String gender = req.getParameter("gender");
            String hobbies[] = req.getParameterValues("hobbies");
            System.out.println(username+","+password+","+gender+","+ Arrays.toString(hobbies));
    
            //文件相关处理
            //获取用户提交的文件对象
            Part part = req.getPart("photo");
            //指定上传路径
            String path = "d://upload";
            //判断该路径是否存在
            File file = new File(path);
            if (!file.exists()) {
                //不存在则创建
                file.mkdirs();
            }
            //获取上传的文件的名字
            String fileName = part.getSubmittedFileName();
            //在指定位置创建指定文件
            part.write(path+"/"+fileName);
        }
    
    • 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

    五.Servlet响应对象

    1.HttpServletResponse接口

    • 服务器响应对象
    • 父接口:ServletResponse
    • 包含响应行,响应头和响应体。

    在这里插入图片描述

    2.响应行

    • 包含协议及其版本,状态码

    (1)状态码

    状态码说明
    1**请求已到达服务器,但未完成,需要再次请求
    2**请求已到达服务器,并且已完成
    3**服务器内部资源重定向
    4**资源找不到
    5**服务器内部异常,代码异常
    200成功
    404找不到,原因:路径有问题
    500代码有问题,90%以上都是空指针

    (2)设置状态码

       @Override
       protected void doGet(HttpServletRequest req, HttpServletResponse resp)
               throws ServletException, IOException {
           resp.setStatus(404);
       }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    3.响应头

    响应头keyvalue
    Location这个头通常配合302状态码使用,它用于告诉浏览器你去找谁。
    Server告诉浏览器,服务器的类型
    Content-Encoding服务器通过这个头,告诉浏览器,回送的数据采用的压缩格式。
    Content-Length0
    Content-Languagezh-cn
    Content-Type这个头用于告诉浏览器,回送数据的类型
    Last-Modified这个头用于告诉浏览器,数据的最后修改时间
    Transfer-Encoding用于通知浏览器,数据是以分块形式回送的
    Cache-Controlno-cache 通知浏览器不要缓存
    Refresh1;url=http://www.it315.org 隔多少秒以后,让当前页面去访问哪个地址(例如网页登陆成功后,跳回原来的界面,就是用的这个头)
    Content-Dispositionattachment;filename=aaa.zip 和下载相关,通知浏览器以附件的形式下载服务器发送过去的数据
    Set-CookieSS=Q0=5Lb_nQ; path=/search 和cookie相关的头
    ETagW/“83794-1208174400000” 和cookie相关的头
    Expires-1 通知浏览器是否缓存当前资源:如果这个头的值是一个以毫秒为单位值,则通知浏览器缓存资源到指定的时间点;如果值是0或-1,则通知浏览器禁止缓存
    Pragmano-cache 通知浏览器是否缓存资源
    Connectionclose/Keep-Alive 是否继续保持连接
    DateTue, 11 Jul 2000 18:23:51 GMT 当前响应的时间

    (1)Location的使用

        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            resp.setStatus(302);
            resp.setHeader("location","http://www.baidu.com");
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    (2)Refresh的使用

        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            resp.setHeader("refresh","2;url=http://www.qidian.com");
        }
    
    • 1
    • 2
    • 3
    • 4

    4.响应体

    • 响应的数据,会将HTML,text等信息返回给客户端。

    (1)响应数据传递方式

    • 响应数据需要通过流来传递,response自带两个输出流
    • 这两个流不能同时使用
    ServletOutputStream out = response.getOutputStream();//字节流
    
    PrintWriter out = response.getWriter();//字符流
    
    • 1
    • 2
    • 3

    (2)示例

        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            resp.setContentType("text/html;charset=utf-8");
            PrintWriter out = resp.getWriter();
            out.print("

    今天天气不错

    "); out.close(); }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    六.文件下载

    1.创建下载文件的页面

    DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Titletitle>
    head>
    <body>
        <a href="responseServlet">下载a>
    body>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    2.添加测试图片操作

    • 去除原来的 exploded

    • 重新添加exploded

    在这里插入图片描述

    3.Servlet编写代码

    • 下载的源文件直接放在src目录下
        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            //告诉浏览器,以附件的形式打开数据
            resp.setHeader("Content-Disposition","attachment;filename=erha.png");
            //输入流读取文件
            //this.getClass().getClassLoader().getResourceAsStream("gouza.png")用于快速的获取src当中问文件对象流
            InputStream in = this.getClass().getClassLoader().getResourceAsStream("gouza.png");
            //输出流写文件
            ServletOutputStream out = resp.getOutputStream();
            //边读边写
            byte[] b = new byte[1024];
            int len = 0;
            while ((len = in.read(b)) != -1) {
                out.write(b,0,len);
            }
            out.close();
            in.close();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    七.请求转发与重定向

    1.Servlet进行跳转的方式

    跳转方式方法
    请求转发request.getRequestDispatcher(“跳转的文件路径”).forward(request,response);
    重定向response.sendRedirect(“跳转的文件路径”);

    2.请求转发

    在这里插入图片描述

    (1)请求转发概述

    • 服务器行为,客户端不知道整个操作在服务器中到底处理了多少次,所以地址栏不会发生改变
    • 整个过程中只发送了一个请求,所以request对整个转发过程中所有的Servlet是共享的
    • 请求转发的是那种数据提交方式,那么第二个servlet也是该方式,出form表单和超链接

    (2)创建FirstServlet

    package com.demo.servlet;
    
    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.io.IOException;
    
    @WebServlet("/firstServlet")
    public class FirstServlet extends HttpServlet {
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            System.out.println("进入FirstServlet");
            req.setAttribute("color","red");
            System.out.println(req.getAttribute("color"));
            req.getRequestDispatcher("secondServlet").forward(req,resp);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    (3)创建SecondServlet

    package com.demo.servlet;
    
    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.io.IOException;
    
    @WebServlet("/secondServlet")
    public class SecondServlet extends HttpServlet {
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            System.out.println("进入SecondServlet");
            System.out.println(req.getAttribute("color"));
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    (4)index.html,点击测试跳转

    
    
    
        
        Title
    
    
        测试请求转发
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    (5)结果

    在这里插入图片描述

    3.重定向

    在这里插入图片描述

    (1)重定向概述

    • 客户端行为,客户端向FirstServlet发送请求,FirstServlet给了客户端响应告诉客户端去找SecondServlet,客户端向SecondServlet发送请求
    • 地址栏会变,request不共享

    (2)创建FirstServlet

    package com.demo.servlet;
    
    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.io.IOException;
    
    @WebServlet("/firstServlet")
    public class FirstServlet extends HttpServlet {
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            System.out.println("进入FirstServlet");
            req.setAttribute("color","red");
            System.out.println(req.getAttribute("color"));
            resp.sendRedirect("secondServlet");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    (3)创建SecondServlet

    package com.demo.servlet;
    
    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.io.IOException;
    
    @WebServlet("/secondServlet")
    public class SecondServlet extends HttpServlet {
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            System.out.println("进入SecondServlet");
            System.out.println(req.getAttribute("color"));
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    (4)测试

    在这里插入图片描述

    4.请求转发与重定向的区别

    请求转发重定向
    发出位置服务器行为客户端行为
    地址栏内容地址栏不会发生改变地址栏会发生改变
    请求次数只有一次请求至少两次请求
    request共享equest是共享的request不共享的
    转发效率较低
    发送范围只能在当前模块中进行可以跳转到其他模块的作用域容器对象:作用域里面的作为容器的对象

    --------------------------------------------------------: |
    | 发出位置 | 服务器行为 | 客户端行为 |
    | 地址栏内容 | 地址栏不会发生改变 | 地址栏会发生改变 |
    | 请求次数 | 只有一次请求 | 至少两次请求 |
    | request共享 | equest是共享的 | request不共享的 |
    | 转发效率 | 高 | 较低 |
    | 发送范围 | 只能在当前模块中进行 | 可以跳转到其他模块的作用域容器对象:作用域里面的作为容器的对象 |

  • 相关阅读:
    SSD写放大的优化策略要统一标准了吗?
    grafana展示的CPU利用率与实际不符的问题探究
    顶顶顶顶顶顶顶顶顶顶顶顶顶顶是
    用python实现基本数据结构【02/4】
    JVM基础06_StringTable
    leetcode 字符串
    【译】.NET 8 网络改进(一)
    记一次 .NET 某新能源系统 线程疯涨 分析
    本地部署FastGPT使用在线大语言模型
    线程池的使用及ThreadPoolExecutor源码分析
  • 原文地址:https://blog.csdn.net/weixin_53903929/article/details/134216557