文章整理来源:Spring编程常见错误50例_spring_spring编程_bean_AOP_SpringCloud_SpringWeb_测试_事务_Data-极客时间
案例31:标注了 @WebFilter 过滤器无法简单注入
为了统计接口耗时实现一个过滤器 ,并启动程序类加上扫描注解 @ServletComponentScan让其生效。
@WebFilter
@Slf4j
public class TimeCostFilter implements Filter {
public TimeCostFilter(){
System.out.println("construct");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
log.info("开始计算接口耗时");
long start = System.currentTimeMillis();
chain.doFilter(request, response);
long end = System.currentTimeMillis();
long time = end - start;
System.out.println("执行时间(ms):" + time);
}
}
但如果在其他地方,将此 TimeCostFilter 类进行注入,会引发 TimeCostFilter could not be found 错误
解析:过滤器被 @WebFilter 修饰后,TimeCostFilter 只会被包装为 FilterRegistrationBean,而 TimeCostFilter 自身,只会作为一个 InnerBean 被实例化,这意味着 TimeCostFilter 实例并不会作为 Bean 注册到 Spring 容器
解决:当使用 @WebFilter 修饰过滤器时,TimeCostFilter 类型的 Bean 并没有注册到 Spring 容器中,真正注册的是 FilterRegistrationBean,注入的名称是包含包名的长名称,即 com.spring.puzzle.filter.TimeCostFilter(不能用 TimeCostFilter),以便于存在多个过滤器时进行精确匹配
@Controller
@Slf4j
public class StudentController {
@Autowired
@Qualifier("com.spring.puzzle.filter.TimeCostFilter")
FilterRegistrationBean timeCostFilter;
}
案例 32:Filter 中多次执行 doFilter()
定义过滤器 实现了 Filter 接口 并且 标记 @Component ,但在过滤器中执行了两次 doFilter() 方法,对应的 业务逻辑也会被执行两次
@Component
public class DemoFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
try {
//模拟异常
System.out.println("Filter 处理中时发生异常");
throw new RuntimeException();
} catch (Exception e) {
chain.doFilter(request, response);
}
chain.doFilter(request, response);
}
}
解决:不管怎么调用,不能多次调用 FilterChain#doFilter()。