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

2022-09-01 06:37:31

我正在编写一个过滤器来执行特定任务,但我无法为我的过滤器设置特定的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,过滤模式应该匹配。我怎样才能做到这一点?


答案 1

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

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

不允许使用正则表达式。甚至没有复杂的通配符。


答案 2

正如其他人所指出的,没有办法仅使用基本的 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.

    }
  }

然后在网络中.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>

有时,通过反转 if 语句来使模式排除匹配项也很方便(或者为排除模式添加另一个 init 参数,这留给读者作为练习。doFilter()


推荐