Skip to content

拦截器interceptor

拦截器(interceptor) 同Filter过滤器一样,都是面向切面编程————AOP的具体实现,你可以使用interceptor来执行某些任务,例如在Controller处理请求之前编写日志,添加或者更新配置

在Spring中,当请求发送到Controller时,在被Controller处理之前,它必须经过若干个Interceptor,Spring interceptor是一个非常类似于Servlet Filter的概念

Interceptor作用

  1. 日志记录:记录请求信息的日志,以便于进行信息监控,信息统计、计算PV(Page View) 等;
  2. 权限检查:如登录检测,进入处理器检测是否登录
  3. 性能监控:通过拦截器在进入处理器之前记录开始的事件,在处理完后记录结束的事件,从而得到该请求的处理事件。(反向代理,如Apache阿帕奇也可以自动记录)
  4. 通用行为:读取Cookie得到用户信息并将用户对象放入请求,从而方便后去流程使用,还有如提取Locale、Theme信息等待,只要是多个处理器都需要的就可以使用拦截器实现

自定义interceptor

如果你需要自定义拦截器interceptor,需要实现org.springframework.web.servlet.HandlerInterceptor接口或继承org.springframework.web.servlet.handler.HandlerInterceptorAdapter

并且需要重写下面3个方法:

  1. preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) 方法在请求处理之前被调用,该方法在interceptor类中最先执行,用来进行些前置初始化的操作或者是对当前请求做预处理,也可以进行一些判断来决定求是否需要继续进行下去。该方法的返回值是布尔值Boolean,当它返回false时,标识请求结束,后续的interceptor的Controller都不会再执行;当它返回为true时会继续调用下一个interceptor的preHandle方法,如果已经是最后一个interceptor的时候就会调用当前请求的Controller方法。
  2. postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) 方法在当前请求处理完成后,也就是Controller方法调用之后执行,但是它会在DispatcherServlet进行视图返回渲染之前被调用,所以我们可以在这个方法中对Controller处理之后的ModelAndView对象进行操作
  3. 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";
    }
}