Java之SpringMVC拦截器
SpringMVC拦截器
SpirngMVC的拦截器类似于Servlet中的Filter,是AOP思想的具体应用
SpirngMVC拦截器是SpringMVC自己的,只有使用了SpringMVC才可以用
拦截器只会拦截访问控制器的方法,并不会拦截jsp/html/css/js
Spring的Interceptor(拦截器)与Servlet的Filter有相似之处,都能实现权限检查、日志记录等。不同的是:
Filter | Interceptor | Summary |
---|---|---|
Filter 接口定义在 javax.servlet 包中 | 接口 HandlerInterceptor 定义在org.springframework.web.servlet 包中 | |
Filter 定义在 web.xml 中 | ||
Filter在只在 Servlet 前后起作用。Filters 通常将 请求和响应(request/response) 当做黑盒子,Filter 通常不考虑servlet 的实现。 | 拦截器能够深入到方法前后、异常抛出前后等,因此拦截器的使用具有更大的弹性。允许用户介入(hook into)请求的生命周期,在请求过程中获取信息,Interceptor 通常和请求更加耦合。 | 在Spring构架的程序中,要优先使用拦截器。几乎所有 Filter 能够做的事情, interceptor 都能够轻松的实现1 |
Filter 是 Servlet 规范规定的。 | 而拦截器既可以用于Web程序,也可以用于Application、Swing程序中。 | 使用范围不同 |
Filter 是在 Servlet 规范中定义的,是 Servlet 容器支持的。 | 而拦截器是在 Spring容器内的,是Spring框架支持的。 | 规范不同 |
Filter 不能够使用 Spring 容器资源 | 拦截器是一个Spring的组件,归Spring管理,配置在Spring文件中,因此能使用Spring里的任何资源、对象,例如 Service对象、数据源、事务管理等,通过IoC注入到拦截器即可 | Spring 中使用 interceptor 更容易 |
Filter 是被 Server(like Tomcat) 调用 | Interceptor 是被 Spring 调用 | 因此 Filter 总是优先于 Interceptor 执行 |
interceptor 的执行顺序大致为:
- 请求到达 DispatcherServlet
- DispatcherServlet 发送至 Interceptor ,执行 preHandle
- 请求达到 Controller
- 请求结束后,postHandle 执行
Spring 中主要通过 HandlerInterceptor 接口来实现请求的拦截,实现 HandlerInterceptor 接口需要实现下面三个方法:
- preHandle() – 在handler执行之前,返回 boolean 值,true 表示继续执行,false 为停止执行并返回。
- postHandle() – 在handler执行之后, 可以在返回之前对返回的结果进行修改
- afterCompletion() – 在请求完全结束后调用,可以用来统计请求耗时等等
而preHandle方法大致会在DispatchServlet#doDispatch方法中进行调用。在DispatchServlet#doDispatch中调用applyPreHandler()方法对所有的拦截器进行遍历,如果发现拦截器的preHandle()方法返回false的话,则直接执行triggerAfterCompletion()方法,并返回false,运行停止,如果获取的布尔类型为true,则将对interceptorIndex进行赋值为1。所以拦截器中preHandle的返回值为false,是会在doDispatch方法中抛出异常的。
拦截器配置
springmvc-servlet.xml
<!-- 拦截器配置-->
<mvc:interceptors>
<mvc:interceptor>
<!-- 一个/代表当前路径下的这一个请求,/**代表当前路径及子路径下的所有请求-->
<mvc:mapping path="/**"/>
<bean class="com.zh1z3ven.controller.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
要实现拦截器需要继HandlerInterceptor接口
public class MyInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return false;
}
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
这里实现了HandlerInterceptor接口的3个方法
1、preHandle方法,处理请求前执行
return true,在这里放行,执行下一个拦截器
return false,不执行下一个拦截器
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return false;
}
2、postHandle方法,处理请求后执行
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
3、afterCompletion方法,请求过后进行的操作
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
2\3主要用来写拦截日志
小结:
其实拦截器没多少东西,后续会在审计中的权限绕过深入分析一下