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

时间:2011-12-20 04:26:55

标签: java servlet-filters web.xml

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

6 个答案:

答案 0 :(得分:40)

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

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

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

答案 1 :(得分: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参数以排除模式,这留下作为读者的练习),有时也可以方便地使模式排除匹配。

答案 2 :(得分:5)

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

URL spec

答案 3 :(得分: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 :(得分:0)

用于servlet映射的web.xml中的

,只能在startend处应用通配符,如果您尝试在映射之间应用通配符,则不会选择映射。 / p>

答案 5 :(得分: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);
    }
}