1. 拦截器概述
拦截器作用是在请求到达控制器之前或之后进行拦截,可以对请求和响应进行一些特定的处理。
1.1.应用场景
1)登录验证:使用拦截器可以判断用户是否已登录,如果未登录则拦截
2)权限校验:根据用户权限对部分网址进行访问控制
3)请求日志:记录请求信息,例如请求地址、请求参数、请求时间等
4)更改响应:可以对响应的内容进行修改,例如添加头信息、调整响应内容格式等
1.2.拦截器和过滤器的区别
1)过滤器更注重在请求和响应的流程中进行处理,可以修改请求和响应的内容,例如设置编码和字符集、请求头、状态码等
2)拦截器则更加侧重于对控制器进行前置或后置处理,在请求到达控制器之前或之后进行特定的操作,例如打印日志、权限验证等
1.3.Filter、Servlet、Interceptor、Controller的执行顺序
2. 拦截器的创建与基本配置
2.1.定义拦截器
实现org.springframework.web.servlet.HandlerInterceptor
接口,实现方法:
1)preHandle:处理器方法调用之前执行:只有该方法有返回true放行,false拦截
2)postHandle:处理器方法调用之后执行
3)afterCompletion:渲染完成后执行
2.2. 拦截器基本配置
<!--第一种方法-->
<mvc:interceptors>
<bean class="com.powernode.springmvc.interceptors.Interceptor1"/>
</mvc:interceptors>
<!--第二种方法,需要包扫描并把类纳入Bean管理-->
<mvc:interceptors>
<ref bean="interceptor1"/>
</mvc:interceptors>
2.3.部分源码
//DispatcherServlet部分源码
public class DispatcherServlet extends FrameworkServlet {
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 调用所有拦截器的 preHandle 方法
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 调用处理器方法
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
// 调用所有拦截器的 postHandle 方法
mappedHandler.applyPostHandle(processedRequest, response, mv);
// 处理视图
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
@Nullable Exception exception) throws Exception {
// 渲染页面
render(mv, request, response);
// 调用所有拦截器的 afterCompletion 方法
mappedHandler.triggerAfterCompletion(request, response, null);
}
}
public class DispatcherServlet extends FrameworkServlet {
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 调用所有拦截器的 preHandle 方法
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
// 如果 mappedHandler.applyPreHandle(processedRequest, response) 返回false,以下的return语句就会执行
return;
}
}
}
//HandlerExecutionChain部分源码
public class HandlerExecutionChain {
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
for (int i = 0; i < this.interceptorList.size(); i++) {
HandlerInterceptor interceptor = this.interceptorList.get(i);
if (!interceptor.preHandle(request, response, this.handler)) {
triggerAfterCompletion(request, response, null);
// 如果 interceptor.preHandle(request, response, this.handler) 返回 false,以下的 return false;就会执行。
return false;
}
this.interceptorIndex = i;
}
return true;
}
}
3.配置
<mvc:interceptors>
<mvc:interceptor>
<!--拦截所有路径-->
<mvc:mapping path="/**"/>
<!--除 /test 路径之外-->
<mvc:exclude-mapping path="/test"/>
<!--拦截器-->
<ref bean="interceptor1"/>
</mvc:interceptor>
</mvc:interceptors>