当前位置: 首页 > 面试题库 >

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

鄂坚
2023-03-14
问题内容

我希望能够以不同于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>

我已经在Guice的GuiceFilter中完成了此操作,其中在运行时配置了过滤器。


问题答案:

只需执行与容器已完成的相同的工作即可。即,按照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();
        }
    }

}

与那些小的帮助程序类(如果需要,可以将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);
    }

}

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

}

如有必要,您还可以将XML配置文件与所有可能的过滤器一起输入,以使最终配置更加容易。你可以使用反射来创建过滤器init()你的GodFilter

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



 类似资料:
  • TL;DR:将@webservlet(“/find-customers”)放在servlet(通过Tomcat 7部署)的开头并不是将servlet映射到host:port/webproject/find-customers中,即使servlet位于src文件夹中。

  • 问题内容: 我希望在不停止应用程序的情况下分析Java应用程序。我可以在应用程序运行时以某种方式添加Javaagent吗? 问题答案: 根据java.lang.instrument软件包的文档,应该是可能的。 VM启动后启动代理 一个实现可以提供一种机制,可以在VM启动之后的某个时间启动代理。有关如何启动的详细信息是特定于实现的,但通常应用程序已启动并且其主要方法已被调用。在虚拟机启动后实现支持启

  • 问题内容: 我有两个活动,我分别从这两个活动向Firestore添加数据。但是,每当我向Firestore添加第二个活动数据时,它就会覆盖第一个活动数据。我在以下两个活动中使用了以下代码: 如何停止覆盖?我想将两个“活动”数据保存在同一文件夹中。 问题答案: 我建议您再添加一个文档或集合,以便它可以为单个用户存储多个数据值。 您可以为两个活动创建文档参考: 或者,您可以为其创建一个子集合: 更多关

  • 问题内容: 有没有办法可以在不重新加载页面的情况下修改当前页面的URL? 如果可能,我想访问#哈希 之前 的部分。 我只需要更改域 后 的部分,所以就好像我没有违反跨域策略一样。 问题答案: 现在,可以在Chrome,Safari,Firefox 4+和Internet Explorer 10pp4 +中完成此操作! 例: 然后,您可以用来检测后退/前进按钮的导航:

  • 或者(甚至更好)在调用之前以某种方式截取序列化,例如: 我想我可以扩展并重写它的方法,但它被声明为,而且我找不到一种简单的方法来创建的新实例,而不为它提供所有类型元数据细节,这实际上是复制Jackson的一个很好的部分。所以我已经放弃了。 我的问题是-如何定制Jackson的序列化,为特定POJO向JSON输出添加额外的内容,而不引入太多的样板代码,并尽可能多地重用默认的Jackson行为。

  • 问题内容: 有没有办法可以在不重新加载页面的情况下修改当前页面的URL? 如果可能,我想访问#哈希 之前 的部分。 我只需要更改域 后 的部分,所以就好像我没有违反跨域策略一样。 问题答案: 现在,可以在Chrome,Safari,Firefox 4+和Internet Explorer 10pp4 +中完成此操作! 有关更多信息,请参见此问题的答案: 使用新URL更新地址栏而不散列或重新加载页面