拦截器和过滤器

  • 拦截器是基于aop,对控制器方法进行切面处理。
  • 过滤器是基于servlet,在请求到达方法前进行过滤,控制范围比拦截器更大,但是没拦截器精确。但是过滤器能干的拦截器都能干,而且拦截器更容易控制配置

    • 因为过滤器基于servlet,只能用于web程序
    • 过滤器是在请求进入容器后,但请求进入servlet之前进行预处理的。请求结束返回也是,是在servlet处理完后,返回给前端之前

      实现拦截器

      拦截器功能类

  • springmvc提供了一个接口HandlerInterceptor,有三个可重写方法:

    • boolean preHandle() 在请求处理方法执行之前执行
      • 为false时就不会再进入控制器里,直接从控制器结束执行
      • 有多个前置拦截器时,依次执行所有拦截,有一个false剩下的就不再执行
    • void postHandle() 在请求处理方法执行之后执行
      • 常常使用model,并往里面添加些通用数据,避免每个控制器都添加
    • void afterCompletion() 在dispatcherServlet处理后执行,做清理工作.
  • 然后在springmvc的配置文件中配置拦截器,配置路径下的所有控制器方法都会被拦截器处理
  • AsyncHandlerInterceptor 继承自HandlerInterceptor,提供了一个afterCompletion,它会在异步线程开始执行前执行,即执行时间晚于pre早于post,一般是用于清空当前线程的资源,如清空ThreadLocal ```java import com.example.demo.util.GLQ; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Slf4j public class GLQ implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

    1. log.error("preHandle {}...", request.getRequestURI());
    2. if (request.getParameter("logined") == false) { //未登录
    3. response.sendRedirect("login.html");
    4. return false;
    5. }
    6. return true;

    }

    @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

     logger.info("postHandle {}.", request.getRequestURI());
      if (modelAndView != null) {
          modelAndView.addObject("__time__", LocalDateTime.now());
      }
    

    }

    @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

      if(ex !=null){  //没有出现错误时异常为空
      log.error("afterCompletion {}: exception = {}", request.getRequestURI(), ex);
      }
    

    }

<a name="relPx"></a>
## 拦截器配置类

- 重写`添加过滤器`方法,参数为`过滤器注册中心`。注册中心执行添加过滤器,再执行添加路径,再执行添加放行路路径
```java
@Configuration
public class WebMvcConfigurer2 implements WebMvcConfigurer {
@Override
    public void addInterceptors(InterceptorRegistry registry) {
        GLQ glq = new GLQ();
        String[] path = {"/**"};
        String[] excludePath = {"/login"};   //除了登录页面能直接进,其他都要进行审核
        registry.addInterceptor(glq).addPathPatterns(path).
                excludePathPatterns(excludePath);
    }
}
//-------------------------------------------------
//还有一种更加优雅的方式 ,自动注册所有的拦截器。
@Configuration
public class WebMvcConfigurer22 {
    @Bean
    WebMvcConfigurer createWebMvcConfigurer(@Autowired HandlerInterceptor[] interceptors) {
        return new WebMvcConfigurer() {
            @Override
            public void addInterceptors(InterceptorRegistry registry) {
                String[] path = {"/**"};
                String[] excludePath = {"/login"};
                for (HandlerInterceptor interceptor : interceptors) { registry.addInterceptor(interceptor).addPathPatterns(path).excludePathPatterns(excludePath);
                }
            }
        };
    }
}
//-------------------------------------------------
@Override        //配置静态资源的访问路径
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
    }

控制器控制是否登录例子

  • 不清楚””和”/“的区别

    @GetMapping(value = {"", "/"})
      public ModelAndView index(HttpServletRequest request) {
          ModelAndView mv = new ModelAndView();
    
          User user = (User) request.getSession().getAttribute("user");
          if (ObjectUtil.isNull(user)) {
              mv.setViewName("redirect:/user/login");
          } else {
              mv.setViewName("page/index");
              mv.addObject(user);
          }
    
          return mv;
      }
    
    @Controller
    @RequestMapping("/user")
    @Slf4j
    public class UserController {
      @PostMapping("/login")
      public ModelAndView login(User user, HttpServletRequest request) {
          ModelAndView mv = new ModelAndView();
    
          mv.addObject(user);
          mv.setViewName("redirect:/");
    
          request.getSession().setAttribute("user", user);
          return mv;
      }
    
      @GetMapping("/login")
      public ModelAndView login() {
          return new ModelAndView("page/login");
      }
    }