• 互联网轻量级框架整合之JavaEE基础II


    编写本篇代码并实际执行之前请仔细阅读前一篇互联网轻量级框架整合之JavaEE基础I

    Servlet

    Servlet容器中,Servlet是最基础的组件,也可以把JSP当做Servlet,JSP的存在意义只在于方便编写动态页面,使Java语言能和HTML相互结合,然后在前后端分离大势下,JSP的讨论已经意义不大;按照Servlet3.0以后的规范,组件都可以使用注解来配置,而不必使用web.xml配置,随着Spring Boot的流行,使用注解开发的方式成为主流

    首先在pom文件中添加如下依赖

        
        <dependency>
          <groupId>javax.servletgroupId>
          <artifactId>javax.servlet-apiartifactId>
          <version>4.0.1version>
          <scope>providedscope>
        dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    新建路径src/mian/java/com/ssm/servlet,在该路径下新建java文件,并命名为MyServlet(Java基础关于命名规则此处不解)

    package com.ssm.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将类标识为Servlet, Servlet容器会自动识别
    @WebServlet(
            name="myServlet",
            urlPatterns="/my"    //Servlet拦截路径,可以使用正则
    )
    public class MyServlet extends HttpServlet {
        @Override
        public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException{
            response.getWriter().print("Hello Servlet");  //写入返回信息
        }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    在编译器中直接执行,并访问路径/my,浏览器会展示如下内容
    在这里插入图片描述

    代码解析

    首先代码中使用@WebServlet自定义了一个servlet,并命名为myServlet,该servlet会拦截/my这个路径下的动作,然后定义了一个MySeervlet类它扩展了HttpServlet这个基础类,将其doGet方法重写从而返回Hello Servlet字符串,基础类中的doGet方法源码如下

        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            String protocol = req.getProtocol();
            String msg = lStrings.getString("http.method_get_not_supported");
            if (protocol.endsWith("1.1")) {
                resp.sendError(405, msg);
            } else {
                resp.sendError(400, msg);
            }
    
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    面向对象编程中的重写(override)指的是子类可以重写其父类中的非private方法,使得子类在调用该方法时会使用自己的实现而不是父类的实现
    面向对象编程中的重载(Overload)指的是在同一个类中声明多个方法,它们拥有相同的名称,但是参数类型或数量不同

    Servlet生命周期

    Servlet在Java中是个接口,在它基础上实现了两个抽象类GenerticServlet和HttpServlet,两个抽象类中分别实现了若干方法
    在这里插入图片描述

    package com.ssm.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将类标识为Servlet, Servlet容器会自动识别
    @WebServlet(
            name="myServlet",
            urlPatterns="/my"    //Servlet拦截路径,可以使用正则
    )
    public class MyServlet extends HttpServlet {
    
        @Override
        public void init(){
            System.out.println("init方法调用");
        }
    
        @Override
        public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException{
            System.out.println("doGet方法调用");
            response.getWriter().print("Hello Servlet");  //写入返回信息
        }
    
        @Override
        public void destroy(){
            System.out.println("destroy方法调用");
        }
    
    }
    
    
    • 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

    代码解析

    代码中新增了init()方法和destroy()方法,均是重写了原方法,但细看HttpServlet这个基础抽象类中并没有这两个方法的实现,发现HttpServlet是扩展了GenericServlet类,在这个类中实现了init()方法和Destroy()方法
    在这里插入图片描述
    上边代码在第一次执行的时候,会在控制台输出init方法调用doGet方法调用字样,刷新页面(再次请求)控制台只会输出doGet方法调用,表明在第一次请求时,Servlet容器会构建Servlet实例,然后进行初始化,接着调用服务类方法而响应请求;在第二次请求则是直接调用服务类方法响应请求不会再调用init方法进行初始化Servlet实例的动作,可见这个过程Servlet只有一个实例而并非多个,而该Servlet实例会在Servlet容器正常关闭或者Servlet实例超时的时候执行destroy()方法,从而销毁该Servlet实例

    在这里插入图片描述
    在这里插入图片描述

    Servlet参数配置

    package com.ssm.servlet;
    
    import javax.servlet.ServletConfig;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebInitParam;
    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将类标识为Servlet, Servlet容器会自动识别
    @WebServlet(
            name="myServlet",
            urlPatterns="/my", //Servlet拦截路径,可以使用正则
            asyncSupported = true, //是否异步执行默认为false, 表示不使用异步线程运行Servlet,设置为true代表支持多线程异步
            loadOnStartup = 1, //启动顺序,如果小于或者等于0,则不在项目启动时加载,只会在第一次请求时才会初始化,如果大于0,则在项目启动时加载
            initParams = { //Servlet参数
                    @WebInitParam(name = "init.param1", value = "init-value1"),
                    @WebInitParam(name = "init.param2", value = "init.value2")
            }
    )
    public class MyServlet extends HttpServlet {
    
        @Override
        public void init(ServletConfig servletConfig){
            System.out.println("init方法调用");
            String param1 = servletConfig.getInitParameter("init.param1");
            String param2 = servletConfig.getInitParameter("init.param2");
            System.out.println(param1);
            System.out.println(param2);
        }
    
        @Override
        public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException{
            System.out.println("doGet方法调用");
            response.getWriter().print("Hello Servlet");  //写入返回信息
        }
    
        @Override
        public void destroy(){
            System.out.println("destroy方法调用");
        }
    
    }
    
    
    • 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
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    01-Apr-2024 14:22:34.934 信息 [main] org.apache.catalina.core.StandardService.startInternal 正在启动服务[Catalina]
    01-Apr-2024 14:22:34.934 信息 [main] org.apache.catalina.core.StandardEngine.startInternal 正在启动 Servlet 引擎:[Apache Tomcat/9.0.87]
    01-Apr-2024 14:22:34.953 信息 [main] org.apache.coyote.AbstractProtocol.start 开始协议处理句柄["http-nio-8080"]
    01-Apr-2024 14:22:34.976 信息 [main] org.apache.catalina.startup.Catalina.start [94]毫秒后服务器启动
    Connected to server
    [2024-04-01 02:22:35,311] Artifact Chapterone:war: Artifact is being deployed, please wait...
    init方法调用
    init-value1
    init.value2
    [2024-04-01 02:22:35,907] Artifact Chapterone:war: Artifact is deployed successfully
    [2024-04-01 02:22:35,908] Artifact Chapterone:war: Deploy took 597 milliseconds
    01-Apr-2024 14:22:44.999 信息 [Catalina-utility-2] org.apache.catalina.startup.HostConfig.deployDirectory 把web 应用程序部署到目录 [D:\apache-tomcat-9.0.87\webapps\manager]
    01-Apr-2024 14:22:45.067 信息 [Catalina-utility-2] org.apache.catalina.startup.HostConfig.deployDirectory Web应用程序目录[D:\apache-tomcat-9.0.87\webapps\manager]的部署已在[67]毫秒内完成
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    在控制台输出中可以看到,页面并没有请求/my路径的(并未请求定义的servlet)情况下,也输出了配置信息,表明虽为请求但项目启动就已经加载了该servlet

    HttpServletRequest

    package com.ssm.servlet;
    
    import javax.servlet.ServletContext;
    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 javax.servlet.http.HttpSession;
    import java.io.IOException;
    
    @WebServlet(
            name = "reqServlet",
            urlPatterns = "/request/*"
    )
    
    public class RequestServlet extends HttpServlet {
    
        @Override
        public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
            //获取请求信息
            int prot = request.getServerPort();
            String url = request.getRequestURI().toString();
            String uri = request.getRequestURI();
            System.out.println("服务器端口:" + prot);
            System.out.println("url:" + url);
            System.out.println("uri:" + uri);
    
            //获取请求头
            String userAgent = request.getHeader("User-Agent");
            System.out.println("User-Agent:" + userAgent);
    
            //获取参数
            String param1 = request.getParameter("param1");
            String param2 = request.getParameter("param2");
    
            //获取上下文
            ServletContext application = request.getServletContext();
    
            //设置上下文属性
            application.setAttribute("application", "application-value");
    
            //设置请求属性
            request.setAttribute("param1", param1);
            request.setAttribute("param2", param2);
    
            //设置Session属性
            HttpSession session = request.getSession();
            // 设置Session超时时间单位s
            session.setMaxInactiveInterval(1800);
            session.setAttribute("session1", "session-value1");
    
            //跳转到JSP页面
            request.getRequestDispatcher("/request-result.jsp") //此时会传递请求和响应的上下文,但浏览器地址不会发生改变
                    .forward(request,response);
    
        }
    
    }
    
    
    • 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
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60

    JSP页面代码,放在src/main/webapp路径下

    <%--
      Created by IntelliJ IDEA.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    
    
        Title
    
    
    <%
        out.print("

    内置对象request

    "); String param1 = (String) request.getAttribute("param1"); String param2 = (String) request.getAttribute("param2"); out.print("param1 =>" + param1 + "
    "); out.print("param1 =>" + param2 + "
    "); out.print("

    内置对象session

    "); String sessionValue = (String) session.getAttribute("session1"); out.print("session1 =>" + sessionValue + "
    "); out.print("

    内置对象application

    "); String appValue = (String) application.getAttribute("application"); out.print("application =>" + appValue + "
    "); %>
    • 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

    在IDEA中执行代码,并使用连接/request/url?param1=value1¶m2=value2请求服务
    在这里插入图片描述
    同时在控制台会输出如下内容

    服务器端口:8080
    url:/Chapterone_war/request/url
    uri:/Chapterone_war/request/url
    User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36
    
    • 1
    • 2
    • 3
    • 4

    代码解析

    这段代码结合了JSP,涉及到了JSP中3个重要内置对象requestsessionapplication,在使用这些内置对象时非常重要的一个概念便是作用域,比如request请求对象的作用域仅当次用户请求有效;session的作用域是浏览器和服务器会话期间有效,它是服务器在浏览器通信期间为了保存会话数据开辟的内存空间,通过一个sessionId进行关联;application的作用域是Web项目在Servlet容器中存活期间有效;还有一个不常用的内置对象page,其作用域只对当前页面有效,使用率很低; 其他解释见注释即可

    HttpServletResponse

    HttpServletRequest和HttpServletResponse这两个类是在Servlet开发中最常用的两个类,HttpServletResponse也被称为响应对象,主要用于设置响应头和响应体,在前后端分离的场景下,页面主要通过AJAX(Asynchronous Javascript And XML)获取数据,移动端应用也类似,因此后端更多的响应类型会以JSON数据集为主,这时就需要通过HttpServletResponse设置响应类型和编码

    package com.ssm.servlet;
    
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.util.HashMap;
    import java.util.Map;
    import com.alibaba.fastjson2.JSON;
    
    @WebServlet(
            name= "respServlet",
            urlPatterns = "/response/*"
    )
    
    
    public class RessponseServlet extends HttpServlet {
    
        @Override
        public void doGet(HttpServletRequest request, HttpServletResponse response)throws IOException{
            //获取参数
            String param1 = request.getParameter("param1");
            String param2 = request.getParameter("param2");
            //将参数写到Map数据结构中
            Map<String, String> resultMap = new HashMap<>();
            resultMap.put("param1", param1);
            resultMap.put("param2", param2);
            //转换为JSON数据集
            String json = JSON.toJSONString(resultMap);
            //设置响应信息为JSON类型
            response.setContentType("application/json");
            //设置响应信息编码为UTF-8
            response.setCharacterEncoding("UTF-8");
            //设置响应头
            response.setHeader("success", "true");
            //设置状态码
            response.setStatus(200);
            //获取输出对象
            PrintWriter out = response.getWriter();
            //输出信息
            out.println(json);
        }
    
    }
    
    
    • 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
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    执行代码并访问链接/response/my?param1=value1¶m2=value2
    在这里插入图片描述
    在这里插入图片描述

    HttpServletResponse进行跳转

    package com.ssm.servlet;
    
    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(
            name= "respJSP",
            urlPatterns = "/resp/jsp/*"
    )
    
    
    public class RessponseJspServlet extends HttpServlet {
    
        @Override
        public void doGet(HttpServletRequest request, HttpServletResponse response)throws IOException{
            //获取参数
            String param1 = request.getParameter("param1");
            String param2 = request.getParameter("param2");
            String param3 = request.getParameter("param3");
            request.setAttribute("param1", param1);
            request.getSession().setAttribute("param2", param2);
            request.getServletContext().setAttribute("param3", param3);
            response.sendRedirect("/Chapterone_war/response-result.jsp"); //这里的跳转需要使用全路径
    
    
    
        }
    
    }
    
    
    • 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
    <%--
      Created by IntelliJ IDEA.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    
    
        Title
    
    
    <%
        out.print("

    内置对象request

    "); String param1 = (String) request.getAttribute("param1"); out.print("param1=>" + param1 + "
    "); out.print("

    内置对象session

    "); String param2 = (String) session.getAttribute("param2"); out.print("param2=>" + param2 + "
    "); out.print("

    内置对象application

    "); String param3 = (String) application.getAttribute("param3"); out.print("param3=>" + param3 + "
    "); %>
    • 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

    重新执行并访问页面/resp/jsp/my?param1=value1¶m2=value2¶m3=value3如下结果
    在这里插入图片描述

    可以看到param1的值为null,也就是并没有获取到,因为HttpServletResponse的跳转并不传递请求上下文,所以不能读取Servlet中HttpServletRequest设置的属性,只能查看Session的属性和ServletContext的属性

    过滤器

    过滤器Filter其作用是在Servlet执行的过程前后执行一些逻辑,例如可以控制对Servlet的访问权限,在Servlet规范中,需要使用注解@WebFilter标识过滤器,同时需要实现Filter接口,该接口代码如下

    package javax.servlet;
    
    import java.io.IOException;
    
    public interface Filter {
    	//初始化方法,在项目启动时先于Servlet的init方法执行
        default void init(FilterConfig filterConfig) throws ServletException {
        }
    	//过滤逻辑,filterChain参数是放行标准
        void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;
    	//过滤器超时或者Servlet容器正常关闭时候会调用,且是在Servlet的destroy方法之后执行
        default void destroy() {
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    package com.ssm.servlet;
    
    import javax.servlet.*;
    import javax.servlet.annotation.WebFilter;
    import javax.servlet.annotation.WebInitParam;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    @WebFilter(
            filterName = "servletFilter",
            //请求拦截的范围
            urlPatterns = {"/request/*", "/response/*"},
            //需要拦截的Servlet,需要提供Servlet名称
            servletNames = {"reqServlet", "respServlet"},
            //初始化参数
            initParams = {
                    @WebInitParam(name="init_param1", value = "init-value-1"),
                    @WebInitParam(name="init_param2", value = "init-value-2")
            }
    )
    
    public class ServletFilter implements Filter {
        //初始化
        @Override
        public void init(FilterConfig filterConfig) throws ServletException{
            String initParam1 = filterConfig.getInitParameter("init_para1");
            String initParam2 = filterConfig.getInitParameter("init_para2");
            System.out.println("Filter初始化参数:param1=>" + initParam1);
            System.out.println("Filter初始化参数:param2=>" + initParam2);
    
        }
    
        /**
         *
         * @param req 请求对象
         * @param resp 响应对象
         * @param filterChain 过滤器责任链
         * @throws IOException
         * @throws ServletException
         */
        @Override
        public void doFilter(ServletRequest req, ServletResponse resp, FilterChain filterChain) throws IOException, ServletException{
            //强制转换
            HttpServletRequest request = (HttpServletRequest) req;
            HttpServletResponse response = (HttpServletResponse) resp;
            request.setCharacterEncoding("UTF-8");
            //获取参数
            String param1 = request.getParameter("param1");
            if(param1 == null || param1.trim().equals("")){
                response.setCharacterEncoding("UTF-8");
                response.setContentType("text/html");
                response.getWriter().println("没有参数:param1, 拦截请求");
                //在过滤器中结束请求,不再转发到Servlet
                return;
            }
            filterChain.doFilter(req,resp);
        }
    
        @Override
        public void destroy(){
            System.out.println("Filter销毁方法");
        }
    }
    
    
    • 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
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 过滤器中doFilter是核心,在此代码中首先从请求中获取参数param1,如果为空,则拦截请求并提示信息,并返回,如果不为空则执行filterChain.doFilter(req, resp);放行该请求

    在编译器中关闭Tomcat服务,如图所示可以看到过滤器的init()、destroy()方法和其他servlet中相关方法的执行顺序
    在这里插入图片描述

    监听器

    在Servlet的规范中存在多种监听,例如监听Servlet上下文属性的ServletContextAttributeListener、监听请求的ServletRequestListener和监听Session属性操作的HttpSessionAttributeListener等

    package com.ssm.servlet;
    
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    import javax.servlet.annotation.WebListener;
    
    @WebListener
    public class WebContextListener implements ServletContextListener {
        /**
         * Servlet上下文初始化后的逻辑
         * @param sce
         */
        public void contextInitialized(ServletContextEvent sce)  {
            System.out.println("Servlet上下文初始化后的逻辑");
        }
    
        /**
         * Servlet上下文销毁后的逻辑
         * @param sce
         */
        public void contextDestroyed(ServletContextEvent sce)  {
            System.out.println("Servlet上下文销毁后的逻辑");
            // 关闭数据库连接池
        }
    }
    
    
    • 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

    在这里插入图片描述
    在这里插入图片描述

    启动项目可以看到contextInitialized方法在过滤器的init方法之前执行,正常关闭Servlet容器,则ContextDestroyed方法在过滤器的destroy方法之后执行

    Servlet容器初始化器

    Servlet容器初始化器ServletContainerInitializer允许将一些第三方的类加载到Servlet容器中,加载哪些类通过注解@HandlesTypes来指定

    package com.ssm.servlet;
    
    public interface OuterService {
        void sayHello(String servlet容器初始化器);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    package com.ssm.servlet;
    
    public class OuterServiceImpl implements OuterService{
        @Override
        public void sayHello(String ss) {
            // TODO 自动生成的方法存根
            System.out.println(ss);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    package com.ssm.servlet;
    
    
    import javax.servlet.ServletContainerInitializer;
    import javax.servlet.ServletContext;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.HandlesTypes;
    import java.lang.reflect.Constructor;
    import java.util.Objects;
    import java.util.Set;
    
    //配置需要加载的类,连同类的实现或者子类加载进来
    @HandlesTypes(value = {OuterService.class})
    public class WebContainInitializer implements ServletContainerInitializer {
        /**
         *
         * @param set 加载类集合
         * @param servletContext Servlet上下文
         * @throws ServletException
         */
        @Override
        public void onStartup(Set<Class<?>> set, ServletContext servletContext) throws ServletException {
            for(Class clazz:set){
                try {
                    Class[] itfs = clazz.getInterfaces();
                    for(Class itf:itfs){
                        if(OuterService.class.equals(itf)){ //符合当前配置的类
                            //获取构造方法数组
                            Constructor<?>[] constructors = Class.forName(clazz.getName()).getConstructors();
                            //通过反射创建对象
                            Object service = constructors[0].newInstance();
                            //强制转换
                            OuterService outerService = (OuterService) service;
                            //执行服务方法
                            outerService.sayHello("Servlet容器初始化器");
                            //将服务对象放入上下文
                            servletContext.setAttribute("outerService",outerService);
                            break;
                        }
                    }
                }catch (Exception e){
                    e.printStackTrace();
                }
    
            }
        }
    }
    
    
    • 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
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    Servlet初始化器标注了@HandlesTypes,并且指定了加载类型为OuterService,同时初始化器实现了ServletContainerInitializer的onStartup方法,该方法会在Servlet上下文构建时执行,它有两个参数,set是一个@HandlesTypes所指定类型的集合,该集合包含所指定类型的实现类或子类,另一个是servletContext,它是Servlet的上下文

    然后在项目结构中如图所示新建文件及内容
    在这里插入图片描述
    文件名 javax.servlet.ServletContainerInitializer文件内容javax.servlet.ServletContainerInitializer, 实际上就是指向刚才写好的初始化类,然后启动项目
    在这里插入图片描述
    在所有监听器、过滤器和Servlet初始化之前,控制台输出Servlet容器初始化器

    使用Cookie

    package com.ssm.servlet;
    
    
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import javax.servlet.http.Cookie;
    
    @WebServlet(
            name = "cookieServlet",
            urlPatterns = "/cookie/*"
    )
    public class CookieServlet extends HttpServlet {
    
        public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException{
            response.setContentType("text/html");
            response.setCharacterEncoding("UTF-8");
            String action = request.getParameter("action");
            if("write".equalsIgnoreCase(action)){
                //写入cookie
                response.getWriter().println("

    写入cookie

    "
    ); this.writeCookie(request, response); }else if("show".equalsIgnoreCase(action)){ //显示cookie this.showCookie(request, response); }else{ response.getWriter().println("

    404

    "
    ); } } private void writeCookie(HttpServletRequest request, HttpServletResponse response) throws IOException{ for(int i=1; i<10; i++){ Cookie cookie = new Cookie("cookie"+i, "cookie"+i); response.addCookie(cookie); } response.getWriter().println("

    写入cookie成功

    "
    ); } private void showCookie(HttpServletRequest request, HttpServletResponse response) throws IOException{ Cookie[] cookies = request.getCookies(); if(cookies != null){ for(Cookie cookie : cookies){ response.getWriter().println("

    "+cookie.getName()+"

    "
    ); response.getWriter().println("

    "+cookie.getValue()+"

    "
    ); } }else { response.getWriter().println("

    没有cookie

    "
    ); } } }
    • 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
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    在这里插入图片描述

    提交表单

    <%--
      Created by IntelliJ IDEA.
      User: Administrator
      Date: 2024/4/1
      Time: 20:46
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    
    
        Test Post Request
    
    
    
    角色名称:
    角色描述:
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    package com.ssm.servlet;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpServletRequest;
    import java.io.IOException;
    import java.io.PrintWriter;
    
    @WebServlet(
            name="postServlet",
            urlPatterns = "/postServlet"
    )
    
    public class PostServlet extends HttpServlet {
        @Override
        public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            String roleName = request.getParameter("roleName"); //input标签里的name值 不是id
            String desc = request.getParameter("roleDesc");//input标签里的name值 不是id
            response.setContentType("text/html");
            response.setCharacterEncoding("UTF-8");
            PrintWriter out = response.getWriter();
            out.println("提交的表单参数【roleName】为:"+roleName);
            out.println("提交的表单参数【desc】为:"+desc);
    
        }
    }
    
    
    • 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

    使用web.xml

    除了使用Servlet.3.0规范给出的各种注解之外,还可以使用web.xml配置Servlet、监听器和过滤器等的内容,将之前写的代码里的注解标识全部去掉,这样Servlet容器就无法识别它了,然后再在web.xml里配置一遍
    在这里插入图片描述

    类似如下方式(猴烦猴烦的)

    
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
             version="4.0">
        
        <listener>
            <listener-class>com.ssm.servlet.WebContextListenerlistener-class>
        listener>
        
        <filter>
            
            <filter-name>servletFilterfilter-name>
            <filter-class>com.ssm.servlet.ServletFilterfilter-class>
            <init-param>
                <param-name>init_param1param-name>
                <param-value>init-value-1param-value>
            init-param>
            <init-param>
                <param-name>init_param2param-name>
                <param-value>init-value-2param-value>
            init-param>
        filter>
        <filter-mapping>
            <filter-name>servletFilterfilter-name>
            <url-pattern>/response/*,/request/*url-pattern>
        filter-mapping>
        <servlet>
            <servlet-name>myServletservlet-name>
            <servlet-class>com.ssm.servlet.MyServletservlet-class>
            <init-param>
                <param-name>init.param1param-name>
                <param-value>init-value-1param-value>
            init-param>
            <init-param>
                <param-name>init.param2param-name>
                <param-value>init-value-2param-value>
            init-param>
            <load-on-startup>1load-on-startup>
        servlet>
        <servlet-mapping>
            <servlet-name>myServletservlet-name>
            <url-pattern>/myurl-pattern>
        servlet-mapping>
        <servlet>
            <servlet-name>CookieServletservlet-name>
            <servlet-class>com.ssm.servlet.CookieServletservlet-class>
            <init-param>
                <param-name>init.param1param-name>
                <param-value>init-value-1param-value>
            init-param>
            <init-param>
                <param-name>init.param2param-name>
                <param-value>init-value-2param-value>
            init-param>
            <load-on-startup>1load-on-startup>
        servlet>
        <servlet-mapping>
            <servlet-name>CookieServletservlet-name>
            <url-pattern>/cookie/*url-pattern>
        servlet-mapping>
        <session-config>
            <session-timeout>30session-timeout>
        session-config>
        <welcome-file-list>
            <welcome-file>index.jspwelcome-file>
        welcome-file-list>
        <error-page>
            <error-code>404error-code>
            <location>/WEB-INF/jsp/404.jsplocation>
        error-page>
        <error-page>
            <error-code>500error-code>
            <location>/WEB-INF/jsp/500.jsplocation>
        error-page>
    
    
    web-app>
    
    • 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
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
  • 相关阅读:
    关于vba代码运行时错误1004 应用程序定义或对象定义错误问题
    计算机网络体系结构——网络层
    基于springboot+vue的便捷网住宿预约系统(前后端分离)
    邮件群发软件
    系统架构设计师(第二版)学习笔记----计算机系统基础
    前端笔记-关于元素定位的深度理解
    Room (三) RecyclerView 呈现列表数据
    Oracle Exadata-ASM异常导致数据库crash
    软件测试(六)自动化测试 Junit5
    集成学习 #数据挖掘 #Python
  • 原文地址:https://blog.csdn.net/dawei_yang000000/article/details/137227765