区别
拦截器Interceptor和过滤器Filter的区别在于:
1、拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,就可以调用业务逻辑。
2、Filter的使用要依赖于Tomcat等容器,导致它只能在web程序中使用;Interceptor依赖Spring,可以使用在非web程序。
3、
访问流程:Tomcat——Filter——Servlet——Interceptor——Controller——Service——Mapper
拦截器Interceptor(两步)
基本使用
1、定义一个拦截器,实现HandlerInterceptor接口,实现HandlerInterceptor接口的三个方法:
preHandle()
:这个方法将在请求处理之前进行调用。注意:如果该方法的返回值为false ,将视为当前请求结束,不仅自身的拦截器会失效,还会导致其他的拦截器也不再执行。
postHandle()
:只有在 preHandle() 方法返回值为true 时才会执行。会在Controller 中的方法调用之后,DispatcherServlet 返回渲染视图之前被调用。 有意思的是:postHandle() 方法被调用的顺序跟 preHandle() 是相反的,先声明的拦截器 preHandle() 方法先执行,而postHandle()方法反而会后执行。
afterCompletion()
:只有在 preHandle() 方法返回值为true 时才会执行。在整个请求结束之后, DispatcherServlet 渲染了对应的视图之后执行。
@Component
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("Interceptor 前置");
if(true){
return true;
}else{//验证不通过使用PrintWriter返回
PrintWriter writer = null;
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
try {
writer = response.getWriter();
Map<String, Object> result = new HashMap<>();
result.put("data", null);
writer.print(result);
} catch (IOException e){
LoggerUtil.logError(ECInterceptor.class, "拦截器输出流异常"+e);
} finally {
//一定要关闭
if(writer != null){
writer.close();
}
}
}
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("Interceptor 处理中");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("Interceptor 后置");
}
}
2、创建一个配置类,将自定义好的拦截器处理类进行注册,并通过addPathPatterns、excludePathPatterns等属性设置需要拦截或需要排除的 URL。
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**");
registry.addInterceptor(new MyInterceptor1()).addPathPatterns("/**");
}
}
进阶使用
分析public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
的参数列表:
request:当前HTTP请求
response:当前HTTP相应
handler:SpringMVC处理器映射器将请求交给匹配的Handler处理,这个handler参数就是描述的处理请求的Handler。
这个handler对应的是本次Http访问的Controller的对应方法
//先转为HandlerMethod之后,调用getMethod()获取具体处理请求的方法
HandlerMethod handlerMethod = (HandlerMethod)handler;
Method method = handlerMethod.getMethod();//获取到XXController类对应url的方法
**总结:**可以使用这种形式,对某些接口加上注解完成某些限制或增强。
过滤器Filter
基本使用
使用步骤:
1、实现Filter
接口
2、实现init()、doFilter()、destroy()方法。其中doFilter()方法是干活的。
两种方式
1、案例033:注解方式
2、案例034:配置文件类
注:路径例如 /user/* 不能/user/**
示例:
注解方式:
@Component
@Order(1)
@WebFilter(urlPatterns = "/*")
public class MyFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("MyFilter");
// 要继续处理请求,必须添加 filterChain.doFilter()
filterChain.doFilter(servletRequest,servletResponse);
}
}
配置类方式:
定义MyFilter类实现Filter接口,重写三个方法之后:
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean registerMyFilter(){
FilterRegistrationBean<MyFilter> bean = new FilterRegistrationBean<>();
bean.setOrder(1);
bean.setFilter(new MyFilter());
// 匹配"/hello/"下面的所有url
bean.addUrlPatterns("/hello/*");
return bean;
}
@Bean
public FilterRegistrationBean registerMyAnotherFilter(){
FilterRegistrationBean<MyAnotherFilter> bean = new FilterRegistrationBean<>();
bean.setOrder(2);
bean.setFilter(new MyAnotherFilter());
// 匹配所有url
bean.addUrlPatterns("/*");
return bean;
}
}