项目场景:
filter进行登录校验过滤
1.实现filter的方法
2.filter的注意事项
实现过滤器的方式
- 方式一
// 实现Filter接口
@Component // 通过Component注解让Spring容器自动为我们创建实例
public class MyFilter implements Filter {
// 销毁过滤器时调用的方法(默认不用实现)
@Override
public void destroy() {
Filter.super.destroy();
}
// 初始化方法(默认不用实现该方法)
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// 请求接口前操作
// 调用接口方法前需要执行的代码
filterChain.doFilter(servletRequest,servletResponse); // 放行到下一个过滤器
// 请求接口后操作
// 调用接口方法后需要执行的代码
}
}
若不用@Component注解注入,则需要如下配置类或者在web.xml中填写配置文件。
⑴配置类
@Configuration
public class MyFilterRegistration {
@Bean
public FilterRegistrationBean<MyFilter> registrationBean(){
// 创建FilterRegistrationBean,通过它配置过滤器
FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new MyFilter()); // 设置过滤器
registrationBean.addUrlPatterns("/device/*"); // 设置过滤器生效范围
registrationBean.setName("myFilter"); // 过滤器名称
registrationBean.setOrder(1); // 设置优先级
return registrationBean;
}
}
⑵web.xml配置文件追加配置
<filter>
<filter-name>MyFilter</filter-name>
<filter-class>com.demo.filter.MyFilter</filter-class>
<async-supported>true</async-supported>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>MyFilter</filter-name>
<url-pattern>/login/check</url-pattern>
</filter-mapping>
⑶@WebFilter注解,性质和web.xml配置文件类似。
@WebFilter(urlPatterns = "/login/check",initParams = {@WebInitParam(name = "MyFilter",value = "GET,POST")})
public class MyFilter implements Filter {
// 销毁过滤器时调用的方法(默认不用实现)
@Override
public void destroy() {
Filter.super.destroy();
}
// 初始化方法(默认不用实现该方法)
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// 请求接口前操作
// 调用接口方法前需要执行的代码
filterChain.doFilter(servletRequest,servletResponse); // 放行到下一个过滤器
// 请求接口后操作
// 调用接口方法后需要执行的代码
}
}
分析:
自定义过滤器通过实现接口Filter达到功能效果;
1.使用注解@Component的话,MyFilter通过@Component注解进行注入容器,过滤的接口默认是所有的接口路径。
2.使用配置类,配置过滤器通过@Bean的方式,可以自己设置3.或者web.xml配置@WebFilter注解
过滤器的注意事项:
一、自定义的MyFilter里面注入其他bean对象,注入为null的现象。
1.通过hutool的Application工具,在使用的时候获取对应的bean对象
2.继承OncePerRequestFilter或者GenericFilterBean,之后配置项更改为走DelegatingFilterProxy代理
DelegatingFilterProxy
这是一个filter的代理类,什么意思呢? 我们知道:当我们实现Filter接口并配置到web.xml中这个filter就会生效,但是在这个filter中我们是无法使用自动注入功能的,因为这个filter并没有被spring管理,那么如果我们想实现一个自定义的filter并且可以进行自动注入spring管理的bean那该多好,spring给我们提供了DelegatingFilterProxy类,注意这是一个过滤器,实现了Filter接口,怎么使用呢?
<filter-name>gateWayUserInfoFilter</filter-name>名字要与自定义的过滤器名字对应。
<filter>
<filter-name>gateWayUserInfoFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>targetFilterLifecycle</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>gateWayUserInfoFilter</filter-name>
<url-pattern>/admin/checkLogin</url-pattern>
</filter-mapping>
二、filter的跨域问题
has been blocked by CORS policy: Response to preflight request doesn‘t pass access control check
解决办法:服务端对preflight请求和fetch请求做不同处理,两个请求不能走同一套逻辑,因为preflight请求不会携带request参数过去,只有fetch请求才会携带request。即在CorsFilter中增加代码:
HttpServletRequest request = (HttpServletRequest)req;
if ("OPTIONS".equals(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
return;
}