
本文已收录在Github,关注我,紧跟本系列专栏文章,咱们下篇再续!

public interface HandlerInterceptor {
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return true;
}
default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable ModelAndView modelAndView) throws Exception {
}
default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable Exception ex) throws Exception {
}
}类似Servlet的过滤器Filter,对处理器进行预处理、后处理。HandlerInterceptor接口方法:
@SuppressWarnings("serial")
public class DispatcherServlet extends FrameworkServlet {
protected void doDispatch() {
...
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
}
}最终会调用HandlerInterceptor#preHandle:
public class HandlerExecutionChain {
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = 0; i < interceptors.length; i++) {
HandlerInterceptor interceptor = interceptors[i];
if (!interceptor.preHandle(request, response, this.handler)) {
...
}调用所有的HandlerInterceptor拦截器并调用其preHandle方法。
执行controller处理逻辑前执行,返回值为boolean,返回值为true时接着执行postHandle和afterCompletion,若返回false则中断执行。
拦截处理程序的执行。 HandlerMapping确定的适当处理器对象后调用,但在HandlerAdapter调用处理器之前。
DispatcherServlet是在执行链中处理的handler,其中包括了任意数量的拦截器,处理器本身在链的末尾,即最后才处理 handler。 利用该方法,每个拦截器可以决定中止执行链,特别发送一个HTTP错误或写入客户端响应。
异步请求处理参见AsyncHandlerInterceptor 。
true如果执行链应与下一个拦截器或处理程序本身进行。 否则,DispatcherServlet认为,这种拦截器已经处理了响应本身。
在业务处理器处理请求前被调用,只有当该方法返回true,才会继续调用下个Interceptor的preHandle(),若已是最后一个Interceptor,就调用当前请求的Controller
applyPostHandle,获取所有的拦截器并调用其postHandle方法:
/**
* Apply postHandle methods of registered interceptors.
*/
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv)
throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = interceptors.length - 1; i >= 0; i--) {
HandlerInterceptor interceptor = interceptors[i];
interceptor.postHandle(request, response, this.handler, mv);
}
}
}执行controller的处理后,即业务处理器处理请求执行完成后,并在ModelAndView处理生成视图之前执行。
请求处理后,DispatcherServlet进行视图返回渲染之前进行调用,可在该方法中对Controller处理之后的ModelAndView对象进行操作(如加入公用信息,以便页面显示)。
DispatchServlet执行完ModelAndView后执行,即完成之后回调,呈现视图后。 将在处理程序执行的任何结果调用,从而允许适当的资源清理。
需当前对应的Interceptor的preHandle方法的返回值为true时才会执行。该方法将在整个请求结束之后,即DispatcherServlet渲染了对应的视图之后执行,用于资源清理。
<bean
class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
<property name="interceptors">
<list>
<ref bean="handlerInterceptor1"/>
<ref bean="handlerInterceptor2"/>
</list>
</property>
</bean>
<bean id="handlerInterceptor1"class="springmvc.intercapter.HandlerInterceptor1"/>
<bean id="handlerInterceptor2"class="springmvc.intercapter.HandlerInterceptor2"/> <!--拦截器 -->
<mvc:interceptors>
<!--多个拦截器,顺序执行 -->
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.sss.filter.HandlerInterceptor1"></bean>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.sss.filter.HandlerInterceptor2"></bean>
</mvc:interceptor>
</mvc:interceptors> 用户访问其他页面时,从Seesion中获取到用户,未登录则重定向到登录页面。
Public class LoginInterceptor implements HandlerInterceptor {
@Override
Public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 若是登录页面则放行
if(request.getRequestURI().indexOf("login.action")>=0){
return true;
}
HttpSession session = request.getSession();
//如果用户已登录也放行
if(session.getAttribute("user")!=null){
return true;
}
//用户没有登录挑战到登录页面
request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
return false;
}