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 就不会被执行。
闲来无事,吃饭睡觉打代码