一、拦截器使用场景
1、权限验证
2、日志处理
3、监控
二、实现
1、实现HandlerInterceptor接口
2、继承实现HandlerInterceptor接口的类,默认HandlerInterceptorAdapter.
三、核心方法
1、preHandle:在controller方法调用之前执行
2、postHandle:在controller方法调用后,视图渲染之前执行
3、afterCompletion:在视图渲染之后执行,用于关闭资源
四、要点
1、拦截器链式执行
2、preHandle方法,先声明先执行,后声明后执行
3、postHandle方法,先声明后执行,与preHandle顺序相反。
4、preHandle返回为true时,继续往下执行,返回为false,则不继续往下执行
5、先执行所有拦截器的preHandle方法,然后再执行controller方法,然后postHandle方法,最后afterCompletion方法
五、在拦截器中想使用属性文件中配置值【通过@Value{"xxxx"}注入】,需要将自定义拦截器的初始化交由Spring IOC容器实现,否则自定义拦截器中无法获取到该值。
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; @Configuration public class WebMvcConfig extends WebMvcConfigurerAdapter {
//交由Spring IOC容器托管 @Bean AliyunOauthinterceptor aliyunOauthinterceptor() { return new AliyunOauthinterceptor(); } @Override public void addInterceptors(InterceptorRegistry registry) { // 多个拦截器组成一个拦截器链 // addPathPatterns 用于添加拦截规则 // excludePathPatterns 用户排除拦截 registry.addInterceptor(aliyunOauthinterceptor()).addPathPatterns("/home"); } }
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; /** * @author zxguan * @description 阿里云权限验证拦截器 * @create 2017-12-25 11:18 */ public class AliyunOauthinterceptor implements HandlerInterceptor { private Logger logger = LoggerFactory.getLogger(AliyunOauthinterceptor.class); @Value("${server.demain}") private String serVerDemain; /** * 该方法将在Controller处理之前进行调用,SpringMVC中的Interceptor拦截器是链式的,可以同时存在多个Interceptor,然后SpringMVC会根据声明的前后顺序一个接一个的执行, * 而且所有的Interceptor中的preHandle方法都会在Controller方法调用之前调用。 * * 当preHandle的返回值为false的时候整个请求就结束了, ture接着往下执行。 */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println(serVerDemain); } /** 在请求处理之后进行调用(Controller方法调用之后, 但是在视图被渲染之前)*/ @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } /** 在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作) */ @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { } public String getSerVerDemain() { return serVerDemain; } public void setSerVerDemain(String serVerDemain) { this.serVerDemain = serVerDemain; } }
七、拦截器中查询数据库,如果拦截器初始化是由Spring 来管理的,可以通过@Autowired注入;如果拦截器是手动new一个实例,就需要通过下边的方法获取到Service实例,然后再操作具体的方法
/** * 获取bean对象 * */ public static <T> T getMapper(Class<T> clazz, HttpServletRequest request) { BeanFactory factory = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext()); return factory.getBean(clazz); }