一、拦截器概念
Spring MVC 的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。底层采用的是aop的思想。
二、 HandlerInterceptor 接口
我们要想自定义拦截器必须实现 HandlerInterceptor 接口。
首先看下 HandlerInterceptor 接口内定义的3个方法
HandlerInterceptor.java
public interface HandlerInterceptor {
/*
在控制器方法执行前执行。
按拦截器定义顺序调用。只要配置了都会调用。
拦截所有的请求,判断是否可以进行下一步执行。
*/
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return true;
}
/*
按拦截器定义逆序调用
preHandle放行操作(即preHandle返回true),可以执行,否则不执行。
在业务处理器处理完请求后,但是控制器方法返回值之前执行,可以对返回的数据验证。
*/
default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable ModelAndView modelAndView) throws Exception {
}
/*
按拦截器定义逆序调用
preHandle必须放行(即preHandle返回true), 执行完postHandle之后执行,否则不执行。
在 DispatcherServlet 完全处理完请求后被调用,可以在该方法中进行一些资源清理的操作。
*/
default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable Exception ex) throws Exception {
}
}
举例:说明HandlerInterceptor 接口内方法的执行顺序
pom.xml中,添加依赖jar包spring-context、spring-webmvc、servlet-api、jsp-api
spring-mvc.xml
<!--扫描包,创建类对象-->
<context:component-scan base-package="com.testfan.controller"></context:component-scan>
<!--视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/pages/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<!--注解驱动-->
<mvc:annotation-driven></mvc:annotation-driven>
<!--引入拦截器:配置拦截器链-->
<mvc:interceptors>
<!--配置单个拦截器对象-->
<mvc:interceptor>
<!--拦截所有的请求-->
<mvc:mapping path="/**"/> <!-- 用于指定拦截的 url -->
<!--指定拦截器类-->
<bean class="com.testfan.interceptor.MyInterceptor1"></bean>
</mvc:interceptor>
<!--配置单个拦截器对象-->
<mvc:interceptor>
<!--拦截所有的请求-->
<mvc:mapping path="/**"/>
<!--指定拦截器类-->
<bean class="com.testfan.interceptor.MyInterceptor2"></bean>
</mvc:interceptor>
</mvc:interceptors>
<!--静态资源放行-->
<!--<mvc:resources mapping="/js/*" location="/js/"></mvc:resources>-->
<!--静态资源全部放行-->
<mvc:default-servlet-handler></mvc:default-servlet-handler>
MyInterceptor1.java
//创建自己的拦截器类,需要实现接口HandlerInterceptor
public class MyInterceptor1 implements HandlerInterceptor{
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("拦截器1:preHandle执行了");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("拦截器1:postHandle执行了");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("拦截器1:afterCompletion执行了");
}
}
MyInterceptor2.java
public class MyInterceptor2 implements HandlerInterceptor{
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("拦截器2:preHandle执行了");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("拦截器2:postHandle执行了");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("拦截器2:afterCompletion执行了");
}
}
TestController.java
@Controller
@RequestMapping("/user")
public class TestController {
@RequestMapping("/hello")
public String print(){
System.out.println("hello啊");
return "show";
}
}
在浏览器中,调用/user/hello接口
三、应用举例
需求:登录验证
- 判断是否是登录请求,如果登录请求,直接放行
- 如果不是登录请求,
- 如果session有登录信息,放行;
- 如果session没有登录信息,拦截,跳转到登录页面
spring-mvc.xml
<!--拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.testfan.interceptor.LoginInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
LoginInterceptor .java
public class LoginInterceptor implements HandlerInterceptor{
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String requestURI = request.getRequestURI();
if(requestURI.contains("login")){//登录请求直接放行
return true;
}
//从session中获取登录信息
Object username = request.getSession().getAttribute("username");
if(username != null){
return true;//session中有登录信息,放行
}else{
response.sendRedirect("/login.jsp");//session没有登录信息,跳转到登录页面
return false;
}
}
}