1.拦截器的说明
拦截器的作用是对处理器进行拦截,增加处理器的功能。可以在处理器执行方法前、后和处理器完成后做一些逻辑处理。
2.定义拦截器
必须实现接口HandlerInterceptor。在方法preHandle、postHandle和afterCompletion加入所需的逻辑。
拦截器的执行流程如下:
- 执行preHandle方法,如果返回false,则流程结束,否则继续执行。可以进行参数验证、身份验证等。
- 执行处理器逻辑。
- 执行postHandle方法。可以填充公共的返回视图参数。
- 执行视图解析和视图渲染。
- 执行afterCompletion方法。可以进行统一的异常处理、日志处理。
package com.zyf.springMVC.mvcinterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.lang.Nullable;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
/**
* 自定义拦截器(需要实现HandlerInterceptor的默认方法)
*/
public class MvcInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("处理器执行前方法");
return true;
}
//返回ModelAndView之前执行,可以填充公共的返回视图参数
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable ModelAndView modelAndView) throws Exception {
System.out.println("处理器执行后方法");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable Exception ex) throws Exception {
System.out.println("处理器完成后方法");
}
}
3.注册拦截器
拦截器需要注册到InterceptorRegistry中才会生效。
在注册器中要说明该拦截器具体拦截什么请求路径。
package com.zyf.springMVC.mvcinterceptor;
import java.util.Arrays;
import java.util.List;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**拦截器注册,需要实现WebMvcConfigurer的addInterceptors方法*/
@Configuration
public class MvcInterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 注册拦截器
InterceptorRegistration ir = registry.addInterceptor(new MvcInterceptor());
// 注册拦截器的拦截请求路径
List<String> pathList = Arrays.asList("/mvcinterceptor/*");
ir.addPathPatterns(pathList);
}
}
4.控制器
package com.zyf.springMVC.mvcinterceptor;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
@Controller
@RequestMapping(path = "/mvcinterceptor")
public class MvcInterceptorController {
@RequestMapping(value = "/mic1")
public ModelAndView mic1(@RequestParam(value = "id") int userid,ModelAndView modelAndView) {
modelAndView.addObject("userid",userid);
modelAndView.setViewName("mvcinterceptor/mic1");
System.out.println("执行控制器方法...mic1");
return modelAndView;
}
}
测试:访问 http://localhost:8080/mvcinterceptor/mic1?id=1
日志:
处理器执行前方法
执行控制器方法...mic1
处理器执行后方法
处理器完成后方法
由此可以了解拦截器方法执行和控制器方法执行的顺序。
5.多个拦截器的执行顺序
注册多个拦截器(拦截器方法的执行顺序是采用的责任链模式),preHandle先注册先执行、postHandle和afterCompletion是先注册后执行。
增加一个拦截器:
public class MvcInterceptor2 implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("处理器执行前方法-2");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable ModelAndView modelAndView) throws Exception {
System.out.println("处理器执行后方法-2");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable Exception ex) throws Exception {
System.out.println("处理器完成后方法-2");
}
}
注册该拦截器,改造MvcInterceptorConfig如下:
@Configuration
public class MvcInterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 注册拦截器
InterceptorRegistration ir = registry.addInterceptor(new MvcInterceptor());
// 注册拦截器的拦截请求路径
List<String> pathList = Arrays.asList("/mvcinterceptor/*");
ir.addPathPatterns(pathList);
// 注册拦截器2
InterceptorRegistration ir2 =registry.addInterceptor(new MvcInterceptor2());
// 注册拦截器2的拦截请求路径
List<String> pathList2 = Arrays.asList("/mvcinterceptor/*");
ir2.addPathPatterns(pathList2);
}
}
测试日志:
处理器执行前方法
处理器执行前方法-2
执行控制器方法...mic1
处理器执行后方法-2
处理器执行后方法
处理器完成后方法-2
处理器完成后方法
github:https://github.com/zhangyangfei/SpringBootLearn.git中的springMVC工程。