我们一个一个的的来!!!
一、什么是过滤器??
过滤器就是过滤的作用,在web开发中过滤一些我们指定的url。它能够在请求传送给 Servlet 之前,对 ServletRequest 和 ServletResponse 做检查和修改,起到了过滤的作用。那么它能帮我们过滤什么呢?那功能可就多了:
比如过拦截掉我们不需要的接口请求
修改请求(request)和响应(response)内容
完成CORS跨域请求等等。过滤器的工作流程去下图所示:
1.1 如何在springboot中实现过滤器(两个步骤)
第一步 自定义过滤器
由于spring boot中的过滤器属于servlet容器,所以自定义的类必须继承Filter接口。
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)//在这里进行过滤操作
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
System.out.println("MyFilter: "+ req.getRequestURI());
chain.doFilter(request, response);//这里是对请求放行,程序继续执行!
}
@Override
public void destroy() {
}
}
ps:注意这里需要将ServletRequest强转为HttpServletRequest,不然后面会出问题!!
第二步 注册过滤器(这里有三个方法)
方法一: 在配置类中实现一个 FilterRegistrationBean 对象
@Configuration
public class WebConfig {
@Bean
public FilterRegistrationBean<MyFilter> abcFilter() {
FilterRegistrationBean<MyFilter> filterRegBean = new FilterRegistrationBean<>();
filterRegBean.setFilter(new MyFilter());//设置过滤器 对应上面的过滤器
filterRegBean.addUrlPatterns("/*"); //在这里指定过滤地址
//如果出现多个过滤器,order可以设置过滤器执行顺序。 1>2>3 这里的LOWEST_PRECEDENCE是最低优先级
filterRegBean.setOrder(Ordered.LOWEST_PRECEDENCE);
return filterRegBean;
}
}
方法2:使用@Component 和@Order 注解注册
@Order(Ordered.LOWEST_PRECEDENCE -1)
@Component
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
System.out.println("MyFilter: "+ req.getRequestURI());
chain.doFilter(request, response);//这步使得请求能够继续传导下去,如果没有的话,请求就在此结束
}
@Override
public void destroy() {
}
}
这种方法的缺点是不能再指定 UrlPatterns,默认的 URL 模式就是/*
方法三: 使用@WebFilter 和@ServletComponentScan 注解,@WebFilter 注解是 Servlet3.0 中的注解,SpringBoot 能够支持该注解,通过@ServletComponentScan 注解,能够扫描并注册到 Servlet 容器中
@WebFilter(urlPatterns="/api/*")
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
System.out.println("MyFilter: "+ req.getRequestURI());
chain.doFilter(request, response);//这步使得请求能够继续传导下去,如果没有的话,请求就在此结束
}
@Override
public void destroy() {
}
}
还需要在springboot启动类中加入@ServletComponentScan注解
@ServletComponentScan
@SpringBootApplication
public class SpringbootlearnApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootlearnApplication.class, args);
}
}
@WebFilter 方式,可以支持 UrlPatterns 的设置,但是不支持 Order 的设置。
综上所述,第 1 种方法是最灵活的,也是最常用的一种。
二、拦截器
上面我们看了过滤的配置方法,下面我们来看一下拦截器的。网上常用的是实现HandlerInterceptor接口,这里我用的是另一种差不多的方法继承HandlerInterceptorAdapter。(建议用HandlerInterceptorAdapter,可以根据需求覆盖方法)
自定义DjmIntercepter类
public class DjmIntercepter extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle调用");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
System.out.println("postHandle调用");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
}
@Override
public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
}
}
ps:主要包括三个方法,preHandle是请求执行前执行的,postHandler是请求结束执行的,但只有preHandle方法返回true的时候才会执行,afterCompletion是视图渲染完成后才执行,同样需要preHandle返回true,该方法通常用于清理资源等工作。afterConcurrentHandlingStarted用的比较少 大家可以自行百度!! 然后需要配置WebConfigurer类,通过实现WebMvcConfigurer接口。
WebConfigurer类 注册自定义拦截器
@Configuration
public class WebConfigurer implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
//用于拦截静态资源
}
@Bean
public HttpMessageConverter<String> responseBodyConverter() {
return new StringHttpMessageConverter(Charset.forName("UTF-8"));
}
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(responseBodyConverter());
}
/**
* 这个方法用来注册拦截器,我们自己写好的拦截器需要通过这里添加注册才能生效
* @param registry 拦截器
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new DjmIntercepter()).addPathPatterns("/*");
super.addInterceptors(registry);
}
}
然后启动项目,在任意地址运行。结果如下:
MyFilter: /ddddd
preHandle调用
postHandle调用
preHandle调用
postHandle调用
通过以上的例子,想必大家也知道了过滤器与拦截器的一些区别。下面我给大家总结一下:
1、过滤器和拦截器触发时机不一样,过滤器是在请求进入容器后,但请求进入servlet之前进行预处理的。请求结束返回也是,是在servlet处理完后,返回给前端之前。
2、拦截器可以获取IOC容器中的各个bean,而过滤器就不行,因为拦截器是spring提供并管理的,spring的功能可以被拦截器使用,在拦截器里注入一个service,可以调用业务逻辑。而过滤器是JavaEE标准,只需依赖servlet api ,不需要依赖spring。
这里有一张图很好的展示了过滤器与拦截器的使用:
3、过滤器的实现基于回调函数。而拦截器(代理模式)的实现基于反射,代理分静态代理和动态代理,动态代理是拦截器的简单实现。
何时使用拦截器?何时使用过滤器?
如果是非spring项目,那么拦截器不能用,只能使用过滤器。
如果是处理controller前后,既可以使用拦截器也可以使用过滤器。
如果是处理dispaterServlet前后,只能使用过滤器。
以上就是spring boot中过滤器与拦截器的实现与区别!!!!