【问题标题】:Can we use regular expressions in web.xml URL patterns?我们可以在 web.xml URL 模式中使用正则表达式吗?
【发布时间】:2012-01-24 03:25:13
【问题描述】:

我正在编写一个过滤器来执行特定任务,但我无法为我的过滤器设置特定的 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/ * ] 没有像我预期的那样工作。

我正在从浏览器调用网址,例如:

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,过滤器模式应该匹配。我怎样才能做到这一点?

【问题讨论】:

  • 据我所知,您只能在 urlpattern 中使用特定文件夹的内容 (path/to/my/folder/*) 或特定扩展名 (*.do)。
  • 请参考this question接受的答案

标签: java servlet-filters web.xml


【解决方案1】:

您的网址无效,因为它不是有效的网址格式。可以参考下面的回复

URL spec

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      那行不通,那里不能使用正则表达式。尝试将此网址用于您的应用程序:

      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>
      

      【讨论】:

        【解决方案4】:

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

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

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

        【讨论】:

          【解决方案5】:

          前面的回答是正确的,因为 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);
              }
          }
          

          【讨论】:

            【解决方案6】:

            正如其他人所指出的,仅使用基本的 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.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 语句使模式排除匹配项(或为排除模式添加另一个初始化参数,这留给读者练习。)

            【讨论】:

              猜你喜欢
              • 2015-03-08
              • 2010-09-29
              • 2021-10-20
              • 2013-05-23
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-02-06
              相关资源
              最近更新 更多