spring mvc 拦截器
过滤器和拦截器的区别
拦截器是基于AOP思想的
拦截器只会拦截访问的控制器方法,是方法级别的拦截
When
DispatcherServlet
receives the request, it dispatches the task of selecting an appropriate controller toHandlerMapping
. Then,HandlerMapping
selects the controller which is mapped to the incoming request URL and returns the (selected Handler) and Controller toDispatcherServlet
.
DispatcherServlet
dispatches the task of executing the business logic byController
toHandlerAdapter
.HandlerAdapter
calls the business logic process ofController
. When theHandlerAdapter
calls the controller,Interceptor
is invoked to intercept the request.Then,
Controller
executes the business logic and sets the processing result inModel
. Then, if there is anyInterceptor
to intercept the response, is invoked as a post process. ThenController
returns the logical name of view toHandlerAdapter
.
DispatcherServlet
dispatches the task of resolving theView
corresponding to the View name toViewResolver
.ViewResolver
returns theView
mapped to View name.
DispatcherServlet
dispatches the rendering process to returnedView
.
View
rendersModel
data and returns the response.
工作流如下
DispatcherServlet
收到请求,分发给负责HandlerMapping
的控制器DispatcherServlet
分发任务处理业务逻辑给HandlerAdapter
适配器,适配器调用Controller
的方法,当适配器调用方法前,拦截器介入,拦截- 如果拦截器不放行,处理器不执行请求,如果拦截器方向,后面的过程和正常的一样
自定义拦截器
All
HandlerMapping
implementations support handler interceptors that are useful when you want to apply specific functionality to certain requests
所有的处理器映射的实现类支持处理器拦截器,并在你想在特定的请求上完成一些特点的功能会很有用
Interceptors must implement
HandlerInterceptor
from theorg.springframework.web.servlet
package
所有的拦截器都必须继承,HandlerInterceptor
接口,且有三个方法可以继承
preHandle(..)
:在之际的处理器执行之前做postHandle(..)
:在处理器执行之后做afterCompletion(..)
:在请求执行完成之后做
The
preHandle(..)
method returns a boolean value. You can use this method to break or continue the processing of the execution chain. When this method returnstrue
, the handler execution chain continues. When it returns false, theDispatcherServlet
assumes the interceptor itself has taken care of requests (and, for example, rendered an appropriate view) and does not continue executing the other interceptors and the actual handler in the execution chain.
preHandle(..)
方法返回一个布尔值,我们可以用这个方法去拦截或者放行执行链。当这个方法返回值为true
,拦截器放行,当返回值为false
,DispatcherServlet
认为这个拦截器本身就已经做了处理,比如说跳到了某个特定的视图,然后就不去执行其他拦截器或者执行真正的处理器了
实现接口
拦截器最常用的业务场景就是判断用户有没有登录和有没有权限访问
public class LoginInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 获得请求路径的uri
String uri = request.getRequestURI();
// 进入登录页面,判断session中是否有key,有的话重定向到首页,否则进入登录界面
if(uri.endsWith("/login")||uri.contains("Login")||uri.contains("login")) {
return true;
}
// 如果没有session就代表没有登录
if(request.getSession() == null)
{
response.sendRedirect(request.getContextPath());
}
// 其他情况判断session中是否有key,有的话继续用户的操作
if(request.getSession().getAttribute("user") != null) {
return true;
}
// 最后的情况就是进入登录页面
response.sendRedirect(request.getContextPath());
return false;
}
}
配置拦截器
通过mvc:interceptors
<mvc:interceptors>
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"/>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/admin/**"/>
<bean class="org.springframework.web.servlet.theme.ThemeChangeInterceptor"/>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/secure/*"/>
<bean class="org.example.SecurityInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
通过RequestMappingHandlerMapping
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
<property name="interceptors">
<bean class="com.lucas.interceptor.LoginInterceptor"/>
</property>
<property name="order" value="-1"/>
</bean>
多个拦截器配置
参考博客: https://blog.csdn.net/itcats_cn/article/details/80371639
- preHandle按拦截器定义顺序调用
- postHandler按拦截器定义逆序调用
- afterCompletion按拦截器定义逆序调用
- postHandler在拦截器链内所有拦截器返成功调用
- afterCompletion只有preHandle返回true才调用