SpringMVC 拦截器
SpringMVC 拦截器
一、拦截器简介
拦截器 Interceptor,顾名思义,是对我们当前的请求进行拦截的一种技术。说到拦截器,这里就不得不提一下过滤器 filter 的概念,这两种技术都可以拦截请求,那么她们到底有什么区别呢?
浏览器发送过来的所有请求首先被过滤器 filter 进行拦截,当请求未被过滤器拦截时,此时请求才会被前端控制器 DispatcherServlet 接收,并根据请求映射,找到具体的控制器(Controller)方法来处理请求。
而拦截器就是作用在控制器执行的前后,在拦截器中一般有三个抽象方法,分别在 “控制器方法执行前执行”、“控制器方法执行后执行” 和 “渲染视图之后执行”。下面会分别详细的介绍。
二、拦截器配置
2.1 拦截所有请求方式一
首先创建一个自定义的拦截器类 FirstInterceptor 并实现 HandlerInterceptor 接口,并重写其三个方法,代码如下:
public class FirstInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("FirstInterceptor --> preHandle ");
// 返回 false 表示拦截,返回 true 表示放行
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 ");
}
}
在 springMVC 的配置文件中配置拦截器,如下:
<mvc:interceptors>
<bean class="com.interceptor.FirstInterceptor"></bean>
</mvc:interceptors>
2.2 拦截所有请求方式二
给 FirstInterceptor 类添加注解,交由 IOC 容器进行管理,如下:
@Component
public class FirstInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("FirstInterceptor --> preHandle ");
// 返回 false 表示拦截,返回 true 表示放行
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 ");
}
}
在 springMVC 的配置文件中配置拦截器,如下:
<mvc:interceptors>
<ref bean="firstInterceptor"></ref>
</mvc:interceptors>
这两种拦截器的配置,将拦截所有的控制器方法,即只要是调用了控制器的方法,都会打印这三个方法的返回值,如下所示:
2.3 拦截指定路径请求方式
给 FirstInterceptor 类添加注解,交由 IOC 容器进行管理,如下:
@Component
public class FirstInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("FirstInterceptor --> preHandle ");
// 返回 false 表示拦截,返回 true 表示放行
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 ");
}
}
在 springMVC 的配置文件中配置拦截器,如下:
<mvc:interceptors>
<mvc:interceptor>
<!-- 设置需要拦截的路径,/* 表示只匹配上下文路径的一层目录,如果想要拦截所有的话就使用 /** -->
<mvc:mapping path="/**"/>
<!-- 排除指定的拦截路径,当访问 / 时不会被拦截器拦截-->
<mvc:exclude-mapping path="/"/>
<!-- 指定拦截器-->
<ref bean="firstInterceptor"></ref>
</mvc:interceptor>
</mvc:interceptors>
当访问 / 路径时不会被拦截,当访问其他的任何路径时,都会被拦截,如下图:
三、拦截器的三个抽象方法
3.1 preHandle
控制器(controller)方法执行之前执行 preHandle(),其 boolean 类型的返回值表示是否拦截或放行,返回 true 为放行,即调用控制器方法;返回 false 表示拦截,即不调用控制器方法。
3.2 postHandle
控制器方法执行之后执行 postHandle()
3.3 afterComplation
处理完视图和模型数据,渲染视图完毕之后执行 afterComplation()
四、多个拦截器执行顺序
4.1 配置多个拦截器
我们此时再创建一个拦截器 SecondInterceptor,代码如下所示:
@Component
public class SecondInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("SecondInterceptor --> preHandle ");
// 返回 false 表示拦截,返回 true 表示放行
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 ");
}
}
在 springMVC 的配置文件中配置这两个拦截器,如下:
<mvc:interceptors>
<ref bean="firstInterceptor"></ref>
<ref bean="secondInterceptor"></ref>
</mvc:interceptors>
那这两个拦截器的执行顺序该是什么样子的呢?如下图:
4.2 多个拦截器执行顺序
若每个拦截器的 preHandle() 都返回 true,此时多个拦截器的执行顺序和拦截器在 SpringMVC 的配置文件的配置顺序有关,preHandle() 会按照配置文件中的顺序执行,而 postHandle() 和 afterComplation() 会按照配置的反序执行。
若其中的一个拦截器的 preHandle() 返回 false,那么这个拦截器和它之前拦截器的 preHandle() 都会执行,postHandle() 都不执行,返回 false 的拦截器之前的拦截器的 afterComplation() 会执行。
4.3 案例展示
4.3.1 第一个拦截器返回 false
当 FirstInterceptor 的 preHandle() 返回 false,而 SecondInterceptor 的 preHandle() 返回 true 时,如下图:
@Component
public class FirstInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("FirstInterceptor --> preHandle ");
// 返回 false 表示拦截,返回 true 表示放行
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 ");
}
}
@Component
public class SecondInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("SecondInterceptor --> preHandle ");
// 返回 false 表示拦截,返回 true 表示放行
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 ");
}
}
在 springMVC 的配置文件中配置这两个拦截器,如下:
<mvc:interceptors>
<ref bean="firstInterceptor"></ref>
<ref bean="secondInterceptor"></ref>
</mvc:interceptors>
可以看到,只执行了 FirstInterceptor 的 preHandle() 方法,第二个拦截器的任何方法都没执行。
4.3.1 第二个拦截器返回 false
当 FirstInterceptor 的 preHandle() 返回 true,而 SecondInterceptor 的 preHandle() 返回 false 时,如下图:
@Component
public class FirstInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("FirstInterceptor --> preHandle ");
// 返回 false 表示拦截,返回 true 表示放行
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 ");
}
}
@Component
public class SecondInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("SecondInterceptor --> preHandle ");
// 返回 false 表示拦截,返回 true 表示放行
return false;
}
@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 ");
}
}
在 springMVC 的配置文件中配置这两个拦截器,如下:
<mvc:interceptors>
<ref bean="firstInterceptor"></ref>
<ref bean="secondInterceptor"></ref>
</mvc:interceptors>
可以看到,执行了 FirstInterceptor 和 SecondInterceptor 的 preHandle() 方法,还执行了 FirstInterceptor 的 afterComplation() ,其他的任何方法都没执行。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)