拦截器和过滤器
- 拦截器是基于aop,对控制器方法进行切面处理。
过滤器是基于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 {log.error("preHandle {}...", request.getRequestURI());
if (request.getParameter("logined") == false) { //未登录
response.sendRedirect("login.html");
return false;
}
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"); } }