一、拦截器的配置
- SpringMVC 中的拦截器用于拦截控制器方法的执行
- SpringMVC 中的拦截器需要实现 HandlerInterceptor
1、创建 FirstInterceptor
package com.example.mvc.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class FirstInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("-------------->FirstInterceptor:preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("-------------->FirstInterceptor:postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("-------------->FirstInterceptor:afterCompletion");
}
}
2、springMVC.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:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd">
<!--自动扫描包-->
<context:component-scan base-package="com.example.mvc"></context:component-scan>
<!-- 配置Thymeleaf视图解析器 -->
<bean id="viewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
<property name="order" value="1"/>
<property name="characterEncoding" value="UTF-8"/>
<property name="templateEngine">
<bean class="org.thymeleaf.spring5.SpringTemplateEngine">
<property name="templateResolver">
<bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
<!-- 视图前缀 -->
<property name="prefix" value="/WEB-INF/templates/"/>
<!-- 视图后缀 -->
<property name="suffix" value=".html"/>
<property name="templateMode" value="HTML5"/>
<property name="characterEncoding" value="UTF-8" />
</bean>
</property>
</bean>
</property>
</bean>
<mvc:interceptors>
<bean class="com.example.mvc.interceptor.FirstInterceptor"></bean>
</mvc:interceptors>
</beans>
3、controller
package com.example.mvc.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/test")
public class TestController {
@RequestMapping("/index")
public String index(){
return "index";
}
}
4、结果
-------------->FirstInterceptor:preHandle
-------------->FirstInterceptor:postHandle
-------------->FirstInterceptor:afterCompletion
将 FirstInterceptor 中的 preHandle 方法的返回值改为 false,执行结果为:
-------------->FirstInterceptor:preHandle
仅执行了 preHandle,postHandle,afterCompletion 两个方法未执行。
5、总结
SpringMVC 中的拦截器有三个抽象方法:
preHandle:控制器方法执行之前执行 predHandle(),其 boolean 类型的返回值表示是否拦截或放行,返回 true 为放行,即调用控制器方法;返回 false 表示拦截,即不调用控制器方法。
postHandle:控制器方法执行之后执行 postHandle()
afterCompletion:处理完视图和模型数据,渲染视图完毕之后执行 afterCompletion()
二、SpringMVC 拦截器的几种配置方式
1、第一种配置方式
<mvc:interceptors>
<bean class="com.example.mvc.interceptor.FirstInterceptor"></bean>
</mvc:interceptors>
或者
<bean id="firstInterceptor" class="com.example.mvc.interceptor.FirstInterceptor"></bean>
<mvc:interceptors>
<ref bean="firstInterceptor"></ref>
</mvc:interceptors>
以上两种配置方式都是对 DispatcherServlet 所处理的所有的请求进行拦截。
2、第二种配置方式
<bean id="firstInterceptor" class="com.example.mvc.interceptor.FirstInterceptor"></bean>
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"></mvc:mapping>
<mvc:exclude-mapping path="/test/index"></mvc:exclude-mapping>
<ref bean="firstInterceptor"></ref>
</mvc:interceptor>
</mvc:interceptors>
以上配置方式可以通过 ref 或 bean 标签设置拦截器,通过 mvc:mapping 设置需要拦截的请求,通过 mvc:exclude-mapping 设置需要排除的请求,即不需要拦截的请求。
验证
FirstInteceptor.java
注意 preHandle 方法的返回值应当为 false
package com.example.mvc.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class FirstInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("-------------->FirstInterceptor:preHandle");
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("-------------->FirstInterceptor:postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("-------------->FirstInterceptor:afterCompletion");
}
}
创建两个Controller
(1)TestController
package com.example.mvc.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/test")
public class TestController {
@RequestMapping("/index")
public String index(){
return "index";
}
}
(2)InterceptorController
package com.example.mvc.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/interceptor")
public class InterceptorController {
@RequestMapping("/index")
public String index(){
return "index";
}
}
启动服务,分别访问 localhost:8080/springmvc/test/index
以及 localhost:8080/springmvc/interceptor/index
,会发现第一个路径可以正常访问,第二个路径则被拦截。
三、多个拦截器执行顺序
1、创建 SecondInterceptor.java
package com.example.mvc.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class SecondInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("-------------->SecondInterceptor:preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("-------------->SecondInterceptor:postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("-------------->SecondInterceptor:afterCompletion");
}
}
2、springMVC.xml 中拦截器的配置
<bean id="secondInterceptor" class="com.example.mvc.interceptor.SecondInterceptor"></bean>
<mvc:interceptors>
<bean class="com.example.mvc.interceptor.FirstInterceptor"></bean>
<ref bean="secondInterceptor"></ref>
</mvc:interceptors>
访问 localhost:8080/springmvc/test/index
,输出结果如下:
-------------->FirstInterceptor:preHandle
-------------->SecondInterceptor:preHandle
-------------->SecondInterceptor:postHandle
-------------->FirstInterceptor:postHandle
-------------->SecondInterceptor:afterCompletion
-------------->FirstInterceptor:afterCompletion
3、调整 springMVC.xml 文件中拦截器的配置顺序
<bean id="secondInterceptor" class="com.example.mvc.interceptor.SecondInterceptor"></bean>
<mvc:interceptors>
<ref bean="secondInterceptor"></ref>
<bean class="com.example.mvc.interceptor.FirstInterceptor"></bean>
</mvc:interceptors>
访问 localhost:8080/springmvc/test/index
,输出结果如下:
-------------->SecondInterceptor:preHandle
-------------->FirstInterceptor:preHandle
-------------->FirstInterceptor:postHandle
-------------->SecondInterceptor:postHandle
-------------->FirstInterceptor:afterCompletion
-------------->SecondInterceptor:afterCompletion
4、将 SecondInterceptor.java 中的 preHandler() 方法返回值改为 false,FirstInterceptor.java 中的 preHandle() 方法返回值改为 true。
springMVC.xml 文件中拦截器的配置如下:
<bean id="secondInterceptor" class="com.example.mvc.interceptor.SecondInterceptor"></bean>
<mvc:interceptors>
<bean class="com.example.mvc.interceptor.FirstInterceptor"></bean>
<ref bean="secondInterceptor"></ref>
</mvc:interceptors>
访问 localhost:8080/springmvc/test/index
,输出结果如下:
-------------->FirstInterceptor:preHandle
-------------->SecondInterceptor:preHandle
-------------->FirstInterceptor:afterCompletion
4、总结
- 若每个拦截器的 preHandle() 都返回 true,此时多个拦截器的执行顺序和拦截器在 SpringMVC 的配置文件的配置顺序有关,preHandle() 会按照配置的顺序执行,而 postHandle() 和 afterCompletion() 会按照配置的反序执行。
- 若某个拦截器的 preHandle() 返回了 false,preHandle() 返回 false 和它之前的拦截器的 preHandle() 都会执行,postHandle() 都不执行,返回 false 的拦截器之前的拦截器的 afterCompletion() 会执行。