为什么多个类实现filter接口后会依次调用实现类里的doFilter方法?

普通的springboot项目,写了两个过滤器,访问接口后两个输出语句都能打印,filter是如何设计实现的?

@Component
public class XssFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        
        //输出
        System.out.println(this.getClass().getSimpleName());
        
        ServletRequest requestWrapper = null;
        if (request instanceof HttpServletRequest) {
            requestWrapper = new XssHttpServletRequestWrapper((HttpServletRequest) request);
        }
        if (requestWrapper == null) {

            chain.doFilter(request, response);
        } else {
            chain.doFilter(requestWrapper, response);
        }
    }
}
@Component
public class TestFilter implements Filter {


    @Override
    public void doFilter(ServletRequest request, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        
        //输出
        System.out.println(this.getClass().getSimpleName());
        
        
        ServletRequest requestWrapper = null;
        if (request instanceof HttpServletRequest) {
            requestWrapper = new XssHttpServletRequestWrapper((HttpServletRequest) request);
        }
        if (requestWrapper == null) {

            filterChain.doFilter(request, servletResponse);
        } else {
            filterChain.doFilter(requestWrapper, servletResponse);
        }
    }
}

image.png

我自己写了公共的接口,然后用两个类来实现,最后启动项目的时候找到了两个就报错了,如何实现filter中的功能的?是不是springboot扫描到实现了filter接口的类然后再调用对应的方法?

public interface CommonInterface {

    void test();

}
@Component
public class TestOne implements CommonInterface{
    @Override
    public void test() {
        System.out.println(this.getClass().getSimpleName());
    }
}
@Component
public class TestTwo implements CommonInterface{
    @Override
    public void test() {
        System.out.println(this.getClass().getSimpleName());
    }
}
@Component
public class StartTest implements CommandLineRunner {

    @Resource
    private CommonInterface commonInterface;

    @Override
    public void run(String... args) throws Exception {

        commonInterface.test();
        
    }
}

image.png

阅读 2.1k
2 个回答

首先你的代码的问题在于使用@Resource注解注入一个bean却没有指定它的名称 所以它根据属性来查找bean找到了这两个同样为CommonInterface类型的bean,Spring不知道要注入哪一个所以报错了,
可以参照楼上使用@Qualifier的方式来指定是哪一个bean要注入。
但是你的题目似乎是想说想要实现类似filter这样的过滤器链顺序来执行你的两个类里的方法
请使用设计模式里的过滤器模式(也叫标准模式)来实现你的需求:
过滤器模式的示范
至于你说Spring里面是怎么实现filter里面的功能的,这涉及到源码,可以看一下下面的这篇文章:
filter的执行顺序解密

@Component
public class StartTest implements CommandLineRunner {

    @Resource
    @Qualifier("testOne")
    private CommonInterface commonInterface;

    @Override
    public void run(String... args) throws Exception {
        commonInterface.test();
    }
}
@Component
@Primary
public class TestOne implements CommonInterface{
    @Override
    public void test() {
        System.out.println(this.getClass().getSimpleName());
    }
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题