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

36

我正在编写一个过滤器来完成特定的任务,但我无法将特定的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>

我的url-pattern [ /org/test/ * /keys/ * ] 没有按照我预期的工作。

我从浏览器中调用的URL如下:

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,过滤器模式应该匹配。我如何实现这一点?


3
据我所知,在urlpattern中,只能使用特定文件夹的内容(path/to/my/folder/*)或特定扩展名(*.do)。 - user684934
1
请参考这个问题中的接受答案。 - aishwarya
6个回答

51

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

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

不允许使用正则表达式。 即使是复杂的通配符也不行。


14

正如其他人指出的那样,只使用基本servlet过滤器功能无法使用正则表达式匹配进行过滤。Servlet规范的编写可能是为了允许有效匹配URL,并且因为servlet比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.example.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无法正常工作,因为它不符合有效的URL模式。您可以参考以下回复:

URL规范


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>

1
web.xml 中进行 Servlet 映射时,你只能在映射的 开头 或者 结尾 使用通配符,如果你在中间使用通配符,该映射将不会被选中。

1
之前的回答是正确的,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);
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接