拦截器interceptor
拦截器(interceptor) 同Filter过滤器一样,都是面向切面编程————AOP的具体实现,你可以使用interceptor来执行某些任务,例如在Controller处理请求之前编写日志,添加或者更新配置
在Spring中,当请求发送到Controller时,在被Controller处理之前,它必须经过若干个Interceptor,Spring interceptor是一个非常类似于Servlet Filter的概念
Interceptor作用
- 日志记录:记录请求信息的日志,以便于进行信息监控,信息统计、计算PV(Page View) 等;
- 权限检查:如登录检测,进入处理器检测是否登录
- 性能监控:通过拦截器在进入处理器之前记录开始的事件,在处理完后记录结束的事件,从而得到该请求的处理事件。(反向代理,如Apache阿帕奇也可以自动记录)
- 通用行为:读取Cookie得到用户信息并将用户对象放入请求,从而方便后去流程使用,还有如提取Locale、Theme信息等待,只要是多个处理器都需要的就可以使用拦截器实现
自定义interceptor
如果你需要自定义拦截器interceptor,需要实现org.springframework.web.servlet.HandlerInterceptor接口或继承org.springframework.web.servlet.handler.HandlerInterceptorAdapter类
并且需要重写下面3个方法:
- preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) 方法在请求处理之前被调用,该方法在interceptor类中最先执行,用来进行些前置初始化的操作或者是对当前请求做预处理,也可以进行一些判断来决定求是否需要继续进行下去。该方法的返回值是布尔值Boolean,当它返回false时,标识请求结束,后续的interceptor的Controller都不会再执行;当它返回为true时会继续调用下一个interceptor的preHandle方法,如果已经是最后一个interceptor的时候就会调用当前请求的Controller方法。
- postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) 方法在当前请求处理完成后,也就是Controller方法调用之后执行,但是它会在DispatcherServlet进行视图返回渲染之前被调用,所以我们可以在这个方法中对Controller处理之后的ModelAndView对象进行操作
- afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) 方法需要在当前对应的interceptor类的postHandler方法返回值为true时才会执行,顾名思义,该方法将在整个请求结束之后,也就是在DispathcerServlet渲染了对应的视图之后执行,此方法主要用来进行资源清理
下面是一个简单案例
LogInterceptor:
java
public class LogInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
long startTime = System.currentTimeMillis();
System.out.println("\n-------- LogInterception.preHandle --- ");
System.out.println("Request URL: " + request.getRequestURL());
System.out.println("Start Time: " + System.currentTimeMillis());
request.setAttribute("startTime", startTime);
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("\n-------- LogInterception.postHandle --- ");
System.out.println("Request URL: " + request.getRequestURL());
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("\n-------- LogInterception.afterCompletion --- ");
long startTime = (Long) request.getAttribute("startTime");
long endTime = System.currentTimeMillis();
System.out.println("Request URL: " + request.getRequestURL());
System.out.println("End Time: " + endTime);
System.out.println("Time Taken: " + (endTime - startTime));
}
}public class LogInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
long startTime = System.currentTimeMillis();
System.out.println("\n-------- LogInterception.preHandle --- ");
System.out.println("Request URL: " + request.getRequestURL());
System.out.println("Start Time: " + System.currentTimeMillis());
request.setAttribute("startTime", startTime);
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("\n-------- LogInterception.postHandle --- ");
System.out.println("Request URL: " + request.getRequestURL());
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("\n-------- LogInterception.afterCompletion --- ");
long startTime = (Long) request.getAttribute("startTime");
long endTime = System.currentTimeMillis();
System.out.println("Request URL: " + request.getRequestURL());
System.out.println("End Time: " + endTime);
System.out.println("Time Taken: " + (endTime - startTime));
}
}OldLoginInterceptor:
java
public class OldLoginInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("\n-------- OldLoginInterceptor.preHandle --- ");
System.out.println("Request URL: " + request.getRequestURL());
System.out.println("Sorry! This URL is no longer used, Redirect to /admin/login");
response.sendRedirect(request.getContextPath()+ "/admin/login");
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("\n-------- OldLoginInterceptor.postHandle --- ");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("\n-------- OldLoginInterceptor.afterCompletion --- ");
}
}public class OldLoginInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("\n-------- OldLoginInterceptor.preHandle --- ");
System.out.println("Request URL: " + request.getRequestURL());
System.out.println("Sorry! This URL is no longer used, Redirect to /admin/login");
response.sendRedirect(request.getContextPath()+ "/admin/login");
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("\n-------- OldLoginInterceptor.postHandle --- ");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("\n-------- OldLoginInterceptor.afterCompletion --- ");
}
}配置拦截器:
java
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LogInterceptor());
registry.addInterceptor(new OldLoginInterceptor()).addPathPatterns("/admin/oldLogin");
registry.addInterceptor(new AdminInterceptor()).addPathPatterns("/admin/*").excludePathPatterns("/admin/oldLogin");
}
}@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LogInterceptor());
registry.addInterceptor(new OldLoginInterceptor()).addPathPatterns("/admin/oldLogin");
registry.addInterceptor(new AdminInterceptor()).addPathPatterns("/admin/*").excludePathPatterns("/admin/oldLogin");
}
}LogInterceptor拦截器用于拦截所有请求;
OldLoginInterceptor用来拦截链接 "/admin/oldLogin",它将重定向到新的 "/admin/login";
AdminInterceptor用来拦截器"/admin/*",并且排除 "/admin/oldLogin"
自定义Controller验证拦截器:
java
@Controller
public class LoginController {
@RequestMapping("/index")
public String index(Model model){
return "index";
}
@RequestMapping(value = "/admin/login")
public String login(Model model){
return "login";
}
}@Controller
public class LoginController {
@RequestMapping("/index")
public String index(Model model){
return "index";
}
@RequestMapping(value = "/admin/login")
public String login(Model model){
return "login";
}
}