SpringMVC拦截器
拦截器
无拦截器-------------------------->controller------------------------------------>
有拦截器---->preHandle--|---true---controller--postHandle---afterCompletion--|------>
|---false--------------------------------------------|
拦截器(Interceptor)是一种动态拦截方法调用的机制,在SpringMVC中动态拦截控制器方法的执行;可以在指定的方法调用前后执行预先设定的代码,或者权限控制阻止原始方法的执行,总的来说拦截器就是用来做增强。
拦截器和过滤器之间的区别
归属不同:Filter属于Servlet技术,Interceptor属于SpringMVC技术
拦截内容不同:Filter对所有访问进行增强,Interceptor仅针对SpringMVC的访问进行增强
过滤器1--过滤器2--mvc核心--拦截器1--拦截器2--处理器--拦截器2--拦截器1--过滤器2--过滤器1-->
拦截器开发
ProjectInterceptor:重写HandlerInterceptor接口中的三个方法。
preHandler方法返回true代表放行,继续执行原始Controller类中要请求的方法;返回false代表拦截,终止原始操作
package com.lmcode.interceptor;
@Component
public class ProjectInterceptor implements HandlerInterceptor {
//原始方法调用前执行的内容
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle...");
return true;
/*返回false可以终止原始操作*/
}
//原始方法调用后执行的内容
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle...");
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
//原始方法调用完成后执行的内容
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion...");
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}
添加拦截器:SpringMVCSupport
package com.lmcode.config;
@Configuration
public class SpringMVCSupport extends WebMvcConfigurationSupport {
@Autowired
private ProjectInterceptor projectInterceptor;
// 放行静态资源
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
registry.addResourceHandler("/css/**").addResourceLocations("/css/");
registry.addResourceHandler("/js/**").addResourceLocations("/js/");
registry.addResourceHandler("/plugins/**").addResourceLocations("/plugins/");
}
// 添加拦截器
@Override
protected void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(projectInterceptor).addPathPatterns("/books","/books/*");
}
}
SpringMvcConfig:添加SpringMvcSupport包扫描
package com.lmcode.config;
@Configuration
@ComponentScan({
"com.lmcode.controller",
"com.lmcode.advice",
"com.lmcode.config",
"com.lmcode.interceptor"})
@EnableWebMvc
public class SpringMvcConfig {
}
添加拦截器方法二【侵入性强,和spring强绑定】
使用SpringMvcConfig实现WebMvcConfigurer方法,可以放行静态资源或添加拦截器
package com.lmcode.config;
@Configuration
@ComponentScan({"com.itheima.controller"})
@EnableWebMvc
//实现WebMvcConfigurer接口可以简化开发,但具有一定的侵入性
public class SpringMvcConfig implements WebMvcConfigurer {
@Autowired
private ProjectInterceptor projectInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
//配置多拦截器
registry.addInterceptor(projectInterceptor).addPathPatterns("/books","/books/*");
}
}
拦截器方法
- request:请求对象
- response:响应对象
- handler:被调用的处理器对象,本质上是一个方法对象,对反射中的Method对象进行了再包装
- modelAndView:页面跳转相关数据
- ex:如果处理器执行过程中出现异常对象,可以针对异常情况进行单独处理
现在大多是异步开发,而且有全局异常处理器,所以ModelAndView和ex使用率不高;最常用的是preHandle,在这个方法中可以通过返回值来决定是否要进行放行:把业务逻辑放在该方法中,如果满足业务则返回true放行,不满足则返回false拦截。
前置处理方法:preHandle
@Override
public boolean preHandle(HttpServletRequest request,HttpServletResponse response,Object handler) throws Exception {
System.out.println("preHandle");
return true;
}
使用request对象或response对象可以获取请求数据中的内容,如获取请求头的
Content-Type
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String contentType = request.getHeader("Content-Type");
System.out.println("preHandle..."+contentType);
return true;
}
使用handler参数,可以获取当前方法的相关信息
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println(handler); // com.lmcode.controller.BookController#save(Book)
System.out.println(handler.getClass()); // class org.springframework.web.method.HandlerMethod
HandlerMethod hm = (HandlerMethod)handler;
String methodName = hm.getMethod().getName(); // 获取方法的名称
return true;
}
后置处理方法:postHandle
@Override
public void postHandle(HttpServletRequest request,HttpServletResponse response,Object handler,ModelAndView modelAndView) throws Exception {
System.out.println("postHandle");
}
完成处理方法:afterCompletion
@Override
public void afterCompletion(HttpServletRequest request,HttpServletResponse response,Object handler,Exception ex) throws Exception {
// 通过ex可以拿到原始的程序执行过程中出现的异常
System.out.println("afterCompletion");
}
拦截器链
配置多个拦截器形成拦截器链
preHandle与配置顺序相同,必定运行;postHandle与配置顺序相反,可能不运行;afterCompletion与配置顺序相反,可能不运行。
两个拦截器时,当拦截器1返回false时,流程终止,拦截器2的pre也不执行了
三个拦截器时,当1,2正常运行,但是3返回false,最后只会运行1,2的after
package com.lmcode.interceptor;
@Component
public class ProjectInterceptor implements HandlerInterceptor {
//原始方法调用前执行的内容
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle1...");
return false;
/*返回false可以终止原始操作*/
}
//原始方法调用后执行的内容
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle1...");
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
//原始方法调用完成后执行的内容
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion1...");
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}
package com.lmcode.interceptor;
@Component
public class ProjectInterceptor2 implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle2...");
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle2...");
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion2...");
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}
按照配置拦截器的先后进行拦截
pre1--->pre2--代码--->post2--->post1--->after2--->after1
package com.lmcode.config;
@Configuration
public class SpringMVCSupport extends WebMvcConfigurationSupport {
@Autowired
private ProjectInterceptor projectInterceptor;
private ProjectInterceptor2 projectInterceptor2;
// 添加拦截器
@Override
protected void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(projectInterceptor).addPathPatterns("/books","/books/*");
registry.addInterceptor(projectInterceptor2).addPathPatterns("/books","/books/*");
}
}