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

TJR*_*TJR 29 java web.xml servlets servlet-filters

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

使用Servlet API 2.5

<web-app>
  ...
  <filter>
    <filter-name>MyFilter1</filter-name>
    <filter-class>com.me.MyFilter1</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>MyFilter1</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  ...
  <filter>
    <filter-name>MyFilter2</filter-name>
    <filter-class>com.me.MyFilter2</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>MyFilter2</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  ...
</web-app>
Run Code Online (Sandbox Code Playgroud)

我已经在使用GuiceFilter的Guice中看到了这一点,其中过滤器是在运行时配置的.

Bal*_*usC 38

只是做容器已经做的相同的工作.即重新发明责任链设计模式的轮子,因为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();
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

使用那些小助手类(如果需要,可以使用private static上面的嵌套类GodFilter):

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);
    }

}
Run Code Online (Sandbox Code Playgroud)

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);
    }

}
Run Code Online (Sandbox Code Playgroud)

如有必要,您还可以使用所有可能的过滤器提供XML配置文件,以便最终更轻松地进行配置.你可以使用反射来创建过滤器init()你的GodFilter.

哦,没关系,这就是web.xml容器已经在做什么......


JB *_*zet 15

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

但是不支持从过滤器加载过滤器.你可以自己实现它:它只是"责任链模式",但为什么你呢?

  • 删除了我的答案,30秒后击败我> :. (2认同)
  • @JB Nizet:TJR并没有要求版本的servlet 3.0,他特别关注servlet 2.5 (2认同)