我们可以在web.xml URL模式中使用正则表达式吗?

问题描述 投票:31回答:6

我正在编写一个过滤器来执行特定任务,但我无法为我的过滤器设置特定的url模式。我的过滤器映射如下:

 <web.xml>
  <filter>
     <filter-name>myFilter</filter-name>
     <filter-class>test.MyFilter</filter-class>
   </filter>

  <filter-mapping>
    <filter-name>myFilter</filter-name>
     <url-pattern>/org/test/*/keys/*</url-pattern>
   </filter-mapping>
 </web-app>

我的网址模式[ /org/test/ * /keys/ * ]没有像我预期的那样工作。

我在浏览器中调用网址:

http://localhost:8080/myapp/org/test/SuperAdminReport/keys/superAdminReport.jsp
http://localhost:8080/myapp/org/test/Adminreport/keys/adminReport.jsp
http://localhost:8080/myapp/org/test/OtherReport/keys/otherReport.jsp

因此,对于上面的URL,过滤器模式应该匹配。我怎样才能做到这一点?

java servlet-filters web.xml
6个回答
40
投票

不,你不能在那里使用正则表达式。根据Java Servlet Specification v2.4(section srv.11.1),url-path的解释如下:

  • 以“/”字符开头并以“/ *”后缀结尾的字符串用于路径映射。
  • 以“*。”前缀开头的字符串用作扩展名映射。
  • 仅包含'/'字符的字符串表示应用程序的“默认”servlet。在这种情况下,servlet路径是请求URI减去上下文路径,路径信息为null。
  • 所有其他字符串仅用于完全匹配。

不允许正则表达式。甚至没有复杂的外卡。


11
投票

正如其他人所指出的那样,只能使用基本的servlet过滤器功能来过滤正则表达式匹配。 servlet规范可能是以允许有效匹配url的方式编写的,并且因为servlet早于java中正则表达式的可用性(正则表达式在java 1.4中到达)。

正则表达式可能性能较差(不,我没有对它进行基准测试),但是如果你没有受到处理时间的强烈约束并希望交换性能以便于配置,你可以这样做:

在您的过滤器中:

private String subPathFilter = ".*";
private Pattern pattern;

  @Override
  public void init(FilterConfig filterConfig) throws ServletException {
    String subPathFilter = filterConfig.getInitParameter("subPathFilter");
    if (subPathFilter != null) {
      this.subPathFilter = subPathFilter;
    }
    pattern = Pattern.compile(this.subPathFilter);
  }

  public static String getFullURL(HttpServletRequest request) {
    // Implement this if you want to match query parameters, otherwise 
    // servletRequest.getRequestURI() or servletRequest.getRequestURL 
    // should be good enough. Also you may want to handle URL decoding here.
  }

  @Override
  public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    Matcher m = pattern.matcher(getFullURL((HttpServletRequest) servletRequest));
    if (m.matches()) {

      // filter stuff here.

    }
  }

然后在web.xml中...

  <filter>
    <filter-name>MyFiltersName</filter-name>
    <filter-class>com.konadsc.servlet.MyFilter</filter-class>
    <init-param>
      <param-name>subPathFilter</param-name>
      <param-value>/org/test/[^/]+/keys/.*</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>MyFiltersName</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

通过在doFilter()中反转if语句(或者为排除模式添加另一个init参数,这仍然可以方便地使模式排除匹配),这留给了读者的练习。)


5
投票

您的网址无法正常工作,因为它不是有效的网址格式。您可以参考以下回复

URL spec


3
投票

这不起作用,那里不能使用正则表达式。尝试将此URL用于您的应用程序:

http://localhost:8080/myapp/org/test/keys/SuperAdminReport/superAdminReport.jsp
http://localhost:8080/myapp/org/test/keys/Adminreport/adminReport.jsp
http://localhost:8080/myapp/org/test/keys/OtherReport/otherReport.jsp

这个配置为您的web.xml:

<filter-mapping>
    <filter-name>myFilter</filter-name>
    <url-pattern>/org/test/keys/*</url-pattern>
</filter-mapping>

0
投票

web.xml中进行servlet映射,只能在startend上应用通配符,如果你尝试在映射之间应用通配符,则不会选择映射。


0
投票

之前的回答是正确的,因为url-pattern只能以通配符开头或结尾,因此不能使用正则表达式的真正功能。

但是,我通过创建一个截取所有请求的简单默认过滤器来解决了以前项目中的这个问题,并且过滤器包含正则表达式以确定是否应该应用其他逻辑。我发现这种方法几乎没有性能下降。

下面是一个简单的示例,可以通过将正则表达式模式移动到过滤器属性来增强。

在web.xml中过滤配置:

<filter>
    <filter-name>SampleFilter</filter-name>
    <filter-class>org.test.SampleFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>SampleFilter</filter-name>
    <servlet-name>SampleServlet</servlet-name>
</filter-mapping>
<servlet-mapping>
    <servlet-name>SampleServlet</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>

可以使用任何正则表达式模式的基本过滤器实现(抱歉,使用Spring的OncePerRequestFilter父类):

public class SampleFilter extends OncePerRequestFilter {

    @Override
    final protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        if (applyLogic(request)) {
            //Execute desired logic;
        }

        filterChain.doFilter(request, response);
    }

    protected boolean applyLogic(HttpServletRequest request) {
        String path = StringUtils.removeStart(request.getRequestURI(), request.getContextPath());

        return PatternMatchUtils.simpleMatch(new String[] { "/login" }, path);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.