主要内容:
拦截器的定义拦截器的配置拦截器的执行流程拦截器(Interceptor)与学习Java Web基础中的过滤器(Filter)类似,主要用于拦截用户请求并做出相应的处理。
应用场景:
权限验证:比如管理员页面,客户是不能访问的。记录请求信息的日志判断用户是否登陆:有些页面未登录用户是无法访问的。主意回顾一下@ModelAttribute的作用,它也可以应用于登陆验证、权限验证。
拦截器的使用步骤:
定义拦截器配置拦截器定义一个拦截器的方法有两种:
实现HandlerInterceptor接口或继承其实现类实现WebRequestInterceptor接口或继承其实现类下面是实现HandlerInterceptor接口来定义拦截器的示例:
package com.tao.interceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; /** * 拦截器类 * 通过实现HandlerInterceptor接口来定义一个拦截器 * @author 12505 * */ public class TestInterceptor implements HandlerInterceptor{ /** * afterCompletion方法在控制器的处理请求方法执行完成后,即视图渲染结束之后执行 */ @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("[afterCompletion方法] 执行"); } /** * postHandle方法在控制器的处理请求方法调用之后,解析视图之前执行 */ @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("[postHandle方法] 执行"); } /** * preHandle方法在控制器的处理请求方法之前执行 */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("[preHandle方法] 执行"); return true; } }通过上面可以看到HandlerInterceptor接口主要有三个方法。
preHandle方法: 该方法在控制器处理请求的方法前执行,其返回值表示是否中断后续操作,false表示中断, true表示继续执行。postHandle方法:该方法在控制器处理请求的方法调用之后,视图解析之前执行。因此,可以通过该方法对请求域中的模型和视图做进一步处理。afterCompletion方法:该方法在视图解析之后执行。可以通过此方法实现一些资源清理、记录日志信息等工作。这些方法的执行顺序将在1.2.拦截器的执行顺序中做进一步的学习。
定义完拦截器之后,要想让其生效,就要在配置文件中进行配置。
其配置代码如下:
springmvc-servlet.xml
<!-- 拦截器的配置 --> <mvc:interceptors> <!-- 全局的拦截器,拦截所有请求(在这配置的bean是全局拦截器 ) --> <bean class="com.tao.interceptor.TestInterceptor"/> <!--指定路径的拦截器--> <mvc:interceptor> <!-- 配置拦截器的作用路径 --> <mvc:mapping path="/**"/> <!-- 配置不需要拦截的作用路径 --> <mvc:exclude-mapping path="/login" /> <!-- 指定路径拦截器,拦截指定路径的请求(在这配置的bean是指定路径的拦截器) --> <bean class="com.tao.interceptor.Interceptor1"/> </mvc:interceptor> <mvc:interceptor> <mvc:mapping path="/goToTest"/> <bean class="com.tao.interceptor.Interceptor2"/> </mvc:interceptor> </mvc:interceptors> <mvc:interceptors>元素用于配置一组拦截器 <bean>元素全局拦截器,即拦截所有的请求。<mvc:interceptor>元素定义指定路径的拦截器 <mvc:mapping>用于配置拦截器作用的路径<mvc:exclude-mapping>用于配置不需要拦截的路径<bean>配置指定路径拦截器。##1.2.拦截器的执行顺序
先看一下一个拦截器的执行流程:
程序首先执行拦截器的preHandle方法如果preHandle方法返回true,则执行控制器处理请求的方法;否则中断执行。执行拦截器的postHandle方法解析视图执行拦截器的afterCompletion方法结束下面通过代码验证一下:
①创建web应用程序
②导入jar包
③配置web.xml文件
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1"> <display-name>ssm01</display-name> <!-- ①Spring IOC 容器的配置 --> <!-- 加载类路径下的applicationContext.xml文件 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <!-- 指定以ContextLoaderListener方式启动Spring容器 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- ③配置DispatcherServlet [springmvc] --> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc-servlet.xml</param-value> </init-param> <!-- 启动容器时立即加载servlet --> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>④创建控制器类
package com.tao.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; /** * 测试拦截器的控制器类 * @author 12505 * */ @Controller public class InterceptorController { /** * 进入test的页面 * @return */ @RequestMapping("goToTest") public String goToTest() { System.out.println("[处理请求的方法] 正在测试拦截器,执行控制器的处理请求方法中"); return "test"; } }⑤创建拦截器类
package com.tao.interceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; /** * 拦截器类 * 通过实现HandlerInterceptor接口来定义一个拦截器 * @author 12505 * */ public class TestInterceptor implements HandlerInterceptor{ /** * afterCompletion方法在控制器的处理请求方法执行完成后,即视图渲染结束之后执行 */ @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("[afterCompletion方法] 执行"); } /** * postHandle方法在控制器的处理请求方法调用之后,解析视图之前执行 */ @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("[postHandle方法] 执行"); } /** * preHandle方法在控制器的处理请求方法之前执行 */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("[preHandle方法] 执行"); return true; } }⑤springmvc-servlet.xml文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!-- ①开启扫描机制扫描控制器的包 --> <context:component-scan base-package="com.tao.controller"/> <!-- ②开启Controller的注解, 这样注解才有效 --> <mvc:annotation-driven/> <!-- ③配置视图解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"></property> </bean> <!-- 配置拦截器 --> <mvc:interceptors> <!-- 这是一个全局的拦截器,拦截所有请求(interceptors的子元素bean是全局拦截器 ) --> <bean class="com.tao.interceptor.TestInterceptor"/> </mvc:interceptors> </beans>⑥创建视图jsp文件
test.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>测试拦截器</title> </head> <body> 这是视图 <% System.out.println("视图渲染结束。"); %> </body> </html>执行结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iD4VH1nv-1599210679549)(D:\笔记图片集\1599209632809.png)]
在web应用程序中通常是多个web同时工作,这时他们的preHandle方法将按照配置文件中拦截器的配置顺序执行,postHandle和afterCompletion方法则按照配置顺序的反序执行:
执行Interceptor1的preHandle方法执行Interceptor2的preHandle方法执行控制器中处理请求的方法执行Interceptor2的postHandle方法执行Interceptor1的postHandle方法渲染视图执行Interceptor2的afterCompletion方法执行Interceptor1的afterCompletion方法顺序用图片表示如下:
还是用上web应用。
新建Interceptor1、Interceptor2两个拦截器:
package com.tao.interceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; /** * 拦截器1号 * 用于测试多个拦截器的执行顺序 * @author 12505 * */ public class Interceptor1 implements HandlerInterceptor { @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println(this.getClass().getName()+" afterCompletion方法执行"); } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println(this.getClass().getName()+" postHandle方法执行"); } @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println(this.getClass().getName()+" preHandle方法执行"); return true; } } package com.tao.interceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; /** * 拦截器2号 * 用于测试多个拦截器的执行顺序 * @author 12505 * */ public class Interceptor2 implements HandlerInterceptor { @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println(this.getClass().getName()+" afterCompletion方法执行"); } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println(this.getClass().getName()+" postHandle方法执行"); } @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println(this.getClass().getName()+" preHandle方法执行"); return true; } }springmvc-servlet.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!-- ①开启扫描机制扫描控制器的包 --> <context:component-scan base-package="com.tao.controller"/> <!-- ②开启Controller的注解, 这样注解才有效 --> <mvc:annotation-driven/> <!-- ③配置视图解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"></property> </bean> <!-- 配置拦截器 --> <mvc:interceptors> <mvc:interceptor> <!-- 配置拦截路径 --> <mvc:mapping path="/**"/> <!-- 配置拦截器的bean --> <bean class="com.tao.interceptor.Interceptor1"/> </mvc:interceptor> <mvc:interceptor> <mvc:mapping path="/goToTest"/> <bean class="com.tao.interceptor.Interceptor2"/> </mvc:interceptor> </mvc:interceptors> </beans>执行结果:
