Java 如何在不修改web.xml的情况下向servlet添加过滤器

Java 如何在不修改web.xml的情况下向servlet添加过滤器,java,servlets,servlet-filters,web.xml,Java,Servlets,Servlet Filters,Web.xml,我希望能够以与web.xml不同的方式修改/配置过滤器。这里是2个过滤器的静态配置。我希望能够静态配置一个过滤器,并允许该过滤器加载其他过滤器。我只是想知道是否有人知道lib已经有了这个 使用ServletAPI2.5 ... 我的过滤器1 com.me.MyFilter1 我的过滤器1 /* ... MyFilter2 com.me.MyFilter2 MyFilter2 /* ... 我已经在Guice和GuiceFilter中看到了这一点,其中过滤器在运行时配置。Servlet 3.0

我希望能够以与web.xml不同的方式修改/配置过滤器。这里是2个过滤器的静态配置。我希望能够静态配置一个过滤器,并允许该过滤器加载其他过滤器。我只是想知道是否有人知道lib已经有了这个

使用ServletAPI2.5


...
我的过滤器1
com.me.MyFilter1
我的过滤器1
/*
...
MyFilter2
com.me.MyFilter2
MyFilter2
/*
...

我已经在Guice和GuiceFilter中看到了这一点,其中过滤器在运行时配置。

Servlet 3.0具有定义过滤器的
@WebFilter
注释。不再需要在web.xml中声明它


但不支持从筛选器加载筛选器。您可以自己实现它:它“只是”责任链模式,但您为什么要这么做?

它可以通过简单的步骤实现,即使对于3.0之前的Servlet规范:

  • 添加包含类(链)的静态有序集合的筛选器
  • 映射过滤器以拦截每个流量
  • 在链中操纵助手类的顺序和存在性(这些类在截获流量时将由过滤器私下调用)

  • Ref:Xstream对序列化程序使用相同的模式,但与Servlet/Filter不同。:)

    只需完成容器已经完成的相同工作即可。也就是说,重新设计servlet过滤器所使用的设计模式

    public class GodFilter implements Filter {
    
        private Map<Pattern, Filter> filters = new LinkedHashMap<Pattern, Filter>();
    
        @Override
        public void init(FilterConfig config) throws ServletException {
            Filter1 filter1 = new Filter1();
            filter1.init(config);
            filters.put(new Pattern("/foo/*"), filter1);
    
            Filter2 filter2 = new Filter2();
            filter2.init(config);
            filters.put(new Pattern("*.bar"), filter2);
    
            // ...
        }
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
            HttpServletRequest hsr = (HttpServletRequest) request;
            String path = hsr.getRequestURI().substring(hsr.getContextPath().length());
            GodFilterChain godChain = new GodFilterChain(chain);
    
            for (Entry<Pattern, Filter> entry : filters.entrySet()) {
                if (entry.getKey().matches(path)) {
                    godChain.addFilter(entry.getValue());
                }
            }
    
            godChain.doFilter(request, response);
        }
    
        @Override
        public void destroy() {
            for (Filter filter : filters.values()) {
                filter.destroy();
            }
        }
    
    }
    

    公共类GodFilterChain实现FilterChain{
    专用过滤链;
    私有列表筛选器=新的ArrayList();
    私有迭代器;
    公共过滤链(过滤链链){
    这个链子=链子;
    }
    @凌驾
    public void doFilter(ServletRequest请求,ServletResponse响应)抛出IOException,ServletException{
    if(迭代器==null){
    迭代器=过滤器。迭代器();
    }
    if(iterator.hasNext()){
    iterator.next().doFilter(请求、响应、this);
    }否则{
    链式过滤器(请求、响应);
    }
    }
    公共无效添加筛选器(筛选器筛选器){
    if(迭代器!=null){
    抛出新的非法状态异常();
    }
    过滤器。添加(过滤器);
    }
    }
    
    如有必要,您还可以向XML配置文件提供所有可能的过滤器,以便最终实现更简单的配置。您可以使用反射在
    GodFilter
    init()
    中创建过滤器


    哦,没关系,这就是
    web.xml
    和容器已经在做的事情…

    它将依赖于servlet容器,所以您应该告诉我们您正在使用的是哪一个,它必须依赖吗?GuiceFilter是否依赖于容器?Guice使用自己的映射机制,其行为类似于
    web.xml
    映射——对于web容器,所有请求都以
    GuiceFilter
    结束。如果你想要Guice,就用它吧:)删除我的答案,比我快30秒>:|@JB Nizet:TJR没有要求servlet 3.0版本,他是专门针对servlet 2的。5@JB,我在问题中添加了我使用的2.5。这3.0功能确实让我很高兴。我们在寻找什么呢?
    @WebFilter(filterName=“customFilter”,urlPatterns={”/*})公共类customFilter实现了Filter….
    它不应该只使用第一个过滤器而不在所有添加的过滤器上循环吗?@mralwaser:嗯,不。也许你不知道怎么做“责任链”设计模式有效?过滤器实现中的
    Chain.doFilter()
    调用将再次调用
    GodFilterChain#doFilter()
    (因为它是作为
    this
    作为
    FilterChain
    参数传递的)然后迭代器将前进到下一个元素,等等。啊,我完全错过了后面的迭代器。next()调用将在更深的“链级别”中完成“。谢谢您指出这一点。@user99560:这样就不必每次都执行相同的代码。每次的结果都是一样的,所以从逻辑上讲,只计算一次并获取它以供重用会更有效。这是令人印象深刻的和干净的+1.
    public class Pattern {
    
        private int position;
        private String url;
    
        public Pattern(String url) {
            this.position = url.startsWith("*") ? 1
                          : url.endsWith("*") ? -1
                          : 0;
            this.url = url.replaceAll("/?\\*", "");
        }
    
        public boolean matches(String path) {
            return (position == -1) ? path.startsWith(url)
                 : (position == 1) ? path.endsWith(url)
                 : path.equals(url);
        }
    
    }
    
    public class GodFilterChain implements FilterChain {
    
        private FilterChain chain;
        private List<Filter> filters = new ArrayList<Filter>();
        private Iterator<Filter> iterator;
    
        public GodFilterChain(FilterChain chain) {
            this.chain = chain;
        }
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
            if (iterator == null) {
                iterator = filters.iterator();
            }
    
            if (iterator.hasNext()) {
                iterator.next().doFilter(request, response, this);
            } else {
                chain.doFilter(request, response);
            }
        }
    
        public void addFilter(Filter filter) {
            if (iterator != null) {
                throw new IllegalStateException();
            }
    
            filters.add(filter);
        }
    
    }