SpringMVC源码(八)HandlerInterceptor拦截器

SpringMVC在执行过程中,DispatcherServlet会根据路径查找对应的HandlerMapping处理器映射器.

此时HandlerMapping处理器映射器会返回一个执行链,包括了handler处理器对象和HandlerInterceptor(拦截器)集合.

而这个HandlerInterceptor拦截器集合主要是对返回的handler进行了一系列的加强处理.大致可分为预处理.后处理和完成后处理.

其常见的应用场景:

1.权限检查:如登陆拦截,可以在预处理里面检查用户是否登陆,没有则response返回登陆页面.

2.性能检测:可以在拦截器预处理和后处理加上时间,相减得出系统执行过程时间.

3.日志记录:记录请求信息日志,以便进行信息监控,信息统计等.

4.通用行为:读取cookie将用户对象放入请求等.

本质也是 AOP(面向切面编程),也就是说符合横切关注点的所有功能都可以放入拦截器实现

拦截器执行顺序:


异常中断的流程:


SpringMVC接口:

package org.springframework.web.servlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.method.HandlerMethod;
public interface HandlerInterceptor {

	boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
	    throws Exception;
	void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
			throws Exception;
	void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception;
}

boolean preHandle :预处理方法,返回boolean类型,当返回值为true时,才会执行后续handler,返回值为false时,则中断流程,不在调用其他handler,用response来来响应页面.一般我们用来拦截用户是否登陆,登陆返回true继续执行,没有登陆返回false,response到登陆页面.

postHandle :后处理方法,在此方法中便可以看到handler执行后的ModelAndView(在视图渲染之前),便可以对ModelAndView在视图渲染前对模型数据进行处理或者对视图进行处理.

afterCompletion:在整个请求处理完毕之后调用该方法(视图渲染之后).上面提到的性能检测,便可以在这里记录请求的结束时间,来进行系统的性能检测.同时还可以进行一些资源的清理.

自定义拦截器:

public class MyInterceptor1 implements HandlerInterceptor {

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		System.out.println("**********我是拦截器1的前置处理方法。");
		// 这里返回true,代表放行,如果是false,流程中断,不再执行后续的Controller中的方法了
		return true;
	}
	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		System.out.println("**********我是拦截器1的后处理方法。我看到了View:" + modelAndView.getViewName());
	}
	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		System.out.println("**********我是拦截器1的完成后处理方法。");
	}
}

public class MyInterceptor2 implements HandlerInterceptor {
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		System.out.println("------------------我是拦截器2的前置处理方法。");
		// 这里返回true,代表放行,如果是false,流程中断,不再执行后续的Controller中的方法了
		return true;
	}
	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		System.out.println("------------------我是拦截器2的后处理方法。我看到了View:" + modelAndView.getViewName());
	}
	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		System.out.println("------------------我是拦截器2的完成后处理方法。");
	}
}

xml中的配置:

<mvc:interceptors>
		<!-- 方式1:直接在这里配置<bean> 对所有的Controller都拦截 -->
		<bean class="cn.springmvc.handlerInterceptor.MyInterceptor1"/>
		<!-- 方式2:通过mvc:interceptor来配置,同时可以指定要拦截的路径: -->
		<mvc:interceptor>
		<!-- 指定要拦截的路径,这里可以写固定路径,也可以使用Ant风格通配符,/**代表就是任意层数任意路径了 -->
			<mvc:mapping path="/**"/>
			<bean class="cn.springmvc.handlerInterceptor.MyInterceptor2"/>
		</mvc:interceptor>
	</mvc:interceptors>

同时SpringMVC还提供了一个AsyncHandlerInterceptor拦截器接口, 在继承了HandlerInterceptor同时增加了一个afterConcurrentHandlingStarted方法:

public interface AsyncHandlerInterceptor extends HandlerInterceptor {

	void afterConcurrentHandlingStarted(
			HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception;

}

afterConcurrentHandlingStarted该方法是用来处理异步请求。当Controller中有异步请求方法的时候会触发该方法。异步请求先支持preHandle、然后执行afterConcurrentHandlingStarted。异步线程完成之后执行preHandle、postHandle、afterCompletion。

SpringMVC提供了抽象类HandlerInterceptorAdapter来实现AsyncHandlerInterceptor接口,一般所使用的拦截器都会继承这个类,并重写里面的方法.

public abstract class HandlerInterceptorAdapter implements AsyncHandlerInterceptor {
	
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
		throws Exception {
		return true;
	}

	@Override
	public void postHandle(
			HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
			throws Exception {
	}

	@Override
	public void afterCompletion(
			HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
	}

	@Override
	public void afterConcurrentHandlingStarted(
			HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
	}
}





猜你喜欢

转载自blog.csdn.net/superpojo/article/details/74178415