Spring MVC 复盘录前言

前言

在还没有使用 Spring MVC 之前,我们 WEB 应用可能是这样操作的:

  • 先创建一个 maven web 项目:

  • 导入必要的依赖后,在 java 目录下新建两个 Servlet :

      package org.example;
    
      import javax.servlet.ServletException;
      import javax.servlet.http.HttpServlet;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      import java.io.IOException;
    
      public class TestForwardServlet extends HttpServlet {
    
          @Override
          protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              System.out.println("自定义的重定向 Servlet 运行了");
    
              // 将这个重定向给另一个 Servlet
              resp.sendRedirect("/redirect");
          }
      }
    

    上面这个是重定向 Servlet ,下面那个是请求转发 Servlet:

      package org.example;
    
      import javax.servlet.RequestDispatcher;
      import javax.servlet.ServletContext;
      import javax.servlet.ServletException;
      import javax.servlet.http.HttpServlet;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      import java.io.IOException;
    
      public class TestRedirectServlet extends HttpServlet {
    
          @Override
          protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              System.out.println("自定义的请求转发 Servlet 运行了");
    
              // 获取请求转发器
              ServletContext servletContext = req.getServletContext();
              RequestDispatcher dispatcher = servletContext.getRequestDispatcher(servletContext.getContextPath() + "/jsp/login.jsp");
              
              // 转发请求
              dispatcher.forward(req, resp);
          }
      }
    

    Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。

  • 打开 web.xml ,配置这个 Servlet:

      <!DOCTYPE web-app PUBLIC
       "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
       "http://java.sun.com/dtd/web-app_2_3.dtd" >
    
      <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xmlns="http://java.sun.com/xml/ns/javaee"
               xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
               version="3.0">
        <display-name>Archetype Created Web Application</display-name>
    
        <servlet>
          <servlet-name>forwardServlet</servlet-name>
          <servlet-class>org.example.TestForwardServlet</servlet-class>
        </servlet>
        <servlet-mapping>
          <servlet-name>forwardServlet</servlet-name>
          <url-pattern>/test</url-pattern>
        </servlet-mapping>
    
        <servlet>
          <servlet-name>redirectServlet</servlet-name>
          <servlet-class>org.example.TestRedirectServlet</servlet-class>
        </servlet>
        <servlet-mapping>
          <servlet-name>redirectServlet</servlet-name>
          <url-pattern>/redirect</url-pattern>
        </servlet-mapping>
    
      </web-app>
    

    启动一个WEB项目的时候,WEB容器会去读取它的配置文件 web.xml。

  • 再在 WEB-INF/jsp (无则创建) 目录下创建一个简单的 login.jsp 页面:

      <%@ page contentType="text/html;charset=UTF-8" language="java" %>
      <html>
      <head>
          <title>登录</title>
      </head>
      <body>
      登陆页面
      </body>
      </html>
    

    上述步骤完成后,即可运行,在地址栏输入 http://localhost:8080/test 进入后,运行结果:

      后台打印结果:
      自定义的重定向 Servlet 运行了
      自定义的请求转发 Servlet 运行了
    
  • 添加两个监听器,一个是请求监听器:

     package org.example.listener;
    
     import javax.servlet.ServletRequestEvent;
     import javax.servlet.ServletRequestListener;
     import javax.servlet.http.HttpServletRequest;
    
     public class WebRequestListener implements ServletRequestListener {
         @Override
         public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
    
         }
    
         @Override
         public void requestInitialized(ServletRequestEvent servletRequestEvent) {
             HttpServletRequest request = (HttpServletRequest) servletRequestEvent.getServletRequest();
             System.out.println("监听到一条请求: " + request.getRequestURI());
         }
     }
    

    另一个是Servlet 上下文监听器:

     package org.example.listener;
    
     import javax.servlet.ServletContextEvent;
     import javax.servlet.ServletContextListener;
    
     // Servlet 上下文监听器
     public class WebServletListener implements ServletContextListener {
         @Override
         public void contextInitialized(ServletContextEvent servletContextEvent) {
             System.out.println("Servlet 上下文已初始化");
         }
    
         @Override
         public void contextDestroyed(ServletContextEvent servletContextEvent) {
    
             System.out.println("Servlet 上下文已销毁了");
         }
     }
    
  • 再添加两个过滤器:

      package org.example.filter;
    
      import javax.servlet.*;
      import javax.servlet.http.HttpServletRequest;
      import java.io.IOException;
    
      public class MyFilter2 implements Filter {
    
          private String param;
    
          // 初始化方法在 WEB 应用启动时会被调用
          @Override
          public void init(FilterConfig filterConfig) throws ServletException {
    
              // 可以获取到在 web.xml 中配置的初始化参数,注意名字的一致性
              param = filterConfig.getInitParameter("test");
              System.out.println("配置在 web.xml/filter/init-param 下的初始化参数" + param);
          }
    
          // 在访问 filter-mapping 中指定的 url 时才会被调用
          @Override
          public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
              System.out.println("filter-1 过滤到了一条请求: " + ((HttpServletRequest)servletRequest).getRequestURI());
    
              // 如果初始化参数 test 允许离开,就放行
              if (param.equals("exit")){
                  filterChain.doFilter(servletRequest, servletResponse);
              }
          }
    
          @Override
          public void destroy() {
    
          }
      }
    

    第二个过滤器用来测试是否放行的问题:

      package org.example.filter;
    
      import javax.servlet.*;
      import javax.servlet.http.HttpServletRequest;
      import java.io.IOException;
    
      public class MyFilter2 implements Filter {
    
          private String param;
    
          // 初始化方法在 WEB 应用启动时会被调用
          @Override
          public void init(FilterConfig filterConfig) throws ServletException {
    
              // 可以获取到在 web.xml 中配置的初始化参数,注意名字的一致性
              param = filterConfig.getInitParameter("test");
              System.out.println("配置在 web.xml/filter/init-param 下的初始化参数" + param);
          }
    
          // 在访问 filter-mapping 中指定的 url 时才会被调用
          @Override
          public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
              System.out.println("filter-2 过滤到了一条请求: " + ((HttpServletRequest)servletRequest).getRequestURI());
    
              // 如果初始化参数 test 允许离开,就放行
              if (param.equals("exit")){
                  filterChain.doFilter(servletRequest, servletResponse);
              }
          }
    
          @Override
          public void destroy() {
    
          }
      }
    

    在请求和响应对象在Servlet处理之前和之后,可以通过过滤器对这两个对象进行处理。

  • 最后在 web.xml webapp 标签内中配置这两个监听器和过滤器:

    <listener>
      <listener-class>org.example.listener.WebRequestListener</listener-class>
    </listener>
    
    <listener>
      <listener-class>org.example.listener.WebServletListener</listener-class>
    </listener>
    
    <filter>
      <filter-name>filter-1</filter-name>
      <filter-class>org.example.filter.MyFilter</filter-class>
      <init-param>
        <param-name>test</param-name>
        <param-value>exit1</param-value>
      </init-param>
    </filter>
    <filter-mapping>
      <filter-name>filter-1</filter-name>
      <servlet-name>forwardServlet</servlet-name>
    </filter-mapping>
    
    <filter>
      <filter-name>filter-2</filter-name>
      <filter-class>org.example.filter.MyFilter2</filter-class>
      <init-param>
        <param-name>test</param-name>
        <param-value>exit</param-value>
      </init-param>
    </filter>
    <filter-mapping>
      <filter-name>filter-2</filter-name>
      <servlet-name>forwardServlet</servlet-name>
    </filter-mapping>
    

    从运行结果中可以发现,listener 和 filter 在 WEB 容器启动时就被加载了,重点是过滤器的问题,多个过滤器会组合成一条过滤链,一旦哪里出现中断,对应的 Servlet 就不会被执行。

posted @ 2022-03-30 17:31  lizhpn  阅读(20)  评论(0编辑  收藏  举报