什么是过滤器?
Filter 也称之为过滤器,它是Servlet技术中最实用的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如JSP,Servlet,静态图片文件或静态HTML文件进行拦截,从而实现一些特殊功能。例如实现 URL级别的权限控制 、 过滤敏感词汇 、 压缩响应信息 等一些高级功能。
Filter的执行原理
当客户端发出Web资源的请求时,Web服务器根据应用程序配置文件设置的过滤规则进行检查,若客户请求满足过滤规则,则对客户请求/响应进行拦截,对请求头和请求数据进行检查或改动,并依次通过过滤器链,最后把请求/响应交给请求的Web资源处理。请求信息在过滤器链中可以被修改,也可以根据条件让请求不发往资源处理器,并直接向客户机发回一个响应。当资源处理器完成了对资源的处理后,响应信息将逐级逆向返回。同样在这个过程中,用户可以修改响应信息,从而完成一定的任务。
服务器会按照过滤器定义的先后循序组装成一条链 ,然后一次执行其中的 doFilter()
方法。这一点 Filter 和 Servlet 是不一样的,执行的顺序不同:
- 执行第一个过滤器的
chain.doFilter()
之前的代码
- 第二个过滤器的
chain.doFilter()
之前的代码,
- 请求的资源,第二个过滤器的
chain.doFilter()
之后的代码
- 第一个过滤器的
chain.doFilter()
之后的代码
- 最后返回响应
如何自定义一个Filter?
只需要实现 javax.servlet.Filter
这个接口,重写其中的方法。实例如下:
1 2 3 4 5 6 7 8
| @Component public class CrosFilter implements Filter { @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { filterChain.doFilter(servletRequest, servletResponse); } }
|
Spring Boot如何配置Filter?
配置类中使用@Bean注入【推荐使用】
只需要将 FilterRegistrationBean 这个实例注入到IOC容器中即可,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| @Configuration public class FilterConfig {
@Autowired CrosFilter crosFilter;
@Bean FilterRegistrationBean<CrosFilter> crosFilter() { FilterRegistrationBean<CrosFilter> registrationBean = new FilterRegistrationBean<CrosFilter>(); registrationBean.setFilter(crosFilter); registrationBean.addUrlPatterns("/*"); registrationBean.setName("crosFilter"); registrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE); return registrationBean; }
}
|
使用@WebFilter
@WebFilter
是Servlet3.0的一个注解,用于标注一个Filter,Spring Boot也是支持这种方式,只需要在自定义的Filter上标注该注解即可,如下:
1 2 3 4 5 6 7 8
| @WebFilter(filterName = "crosFilter2", urlPatterns = {"/*"}) public class CrosFilter2 implements Filter { @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { filterChain.doFilter(servletRequest, servletResponse); } }
|
要想 @WebFilter
注解生效,需要在配置类上标注另外一个注解 @ServletComponentScan
用于扫描使其生效 ,如下:
1 2 3
| @SpringBootApplication @ServletComponentScan(value = {"com.monochrome.filter"}) public class SpringbootApplication {}
|
举个栗子
对于前后端分离的项目来说跨域是一个难题,什么是跨域问题?如何造成的? 对于跨域问题有多中解决方案,比如JSONP,网关支持等等。如何使用过滤器来解决跨域问题?
其实原理很简单,只需要在请求头中添加相应支持跨域的内容即可,如下代码仅仅是简单的演示下,针对细致的内容还需自己完善,比如白名单等等。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @Component public class CrosFilter implements Filter { @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletResponse response = (HttpServletResponse) servletRequest; response.setHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Access-Control-Allow-Credentials", "true"); response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE"); response.setHeader("Access-Control-Max-Age", "3600"); response.setHeader("Access-Control-Allow-Headers", " Origin, X-Requested-With, Content-Type,Accept"); filterChain.doFilter(servletRequest, servletResponse); } }
|