【问题标题】:Servlet and path parameters like /xyz/{value}/test, how to map in web.xml?Servlet 和 /xyz/{value}/test 等路径参数,如何在 web.xml 中映射?
【发布时间】:2012-01-03 16:40:32
【问题描述】:

servlet 是否支持如下 url:

/xyz/{value}/test

其中值可以替换为文本或数字。

如何在 web.xml 中映射它?

【问题讨论】:

标签: servlets get web.xml path-parameter


【解决方案1】:

Servlet API 不支持在映射中间使用 URL 模式通配符 *。它只允许在映射的末尾使用通配符 *,如 /prefix/* 或在映射的开头,如 *.suffix

使用允许的标准 URL 模式语法,最好的办法是将其映射到 /xyz/* 并使用 HttpServletRequest#getPathInfo() 提取路径信息。

所以,给定一个<url-pattern>/xyz/*</url-pattern>,这是一个基本的启动示例,如何提取路径信息、空检查和数组索引越界检查省略:

String pathInfo = request.getPathInfo(); // /{value}/test
String[] pathParts = pathInfo.split("/");
String part1 = pathParts[1]; // {value}
String part2 = pathParts[2]; // test
// ...

如果您希望使用 Apache HTTPD 的mod_rewrite 尽可能地进行更精细的控制,那么您可以查看Tuckey's URL rewrite filterhomegrow your own URL rewrite filter

【讨论】:

  • 这真的是 方式 需要提取不是 GET 参数的 url 参数吗?这似乎很臃肿,难以维护,容易出现偏移错误,而且一般是 1995 年。
  • @Herbert:只需在 Servlet API 之上使用支持路径参数的框架,例如 JAX-RS 或 MVC。
  • 另一个选项是 getRequestURI(),在我的例子中 getPathInfo() 是空的。
  • @leventunver:它在过滤器中是空的,或者当请求中的某个地方使用了糟糕的请求包装器时,或者由于 servlet 容器中的错误。
  • 我修改了一个扩展 GenericFilterBean 的类。使用 ServletRequest 作为输入。
【解决方案2】:

正如其他人所指出的,servlet 规范不允许这样的模式;但是,如果适合您的用例,您可能会考虑 JAX-RS,它确实允许此类模式。

@Path("/xyz/{value}/test")
public class User { 

    public String doSomething(@PathParam("value") final String value) { ... }

}

或者:

@Path("/xyz/{value}")
public class User { 

    @Path("test")
    public String doTest(@PathParam("value") final String value) { ... }

}

(相关:https://stackoverflow.com/a/8303767/843093.)

【讨论】:

    【解决方案3】:

    它确实支持映射该 url;但不提供任何验证。

    在你的 web xml 中,你可以这样做......

    /xyz/*
    

    但这并不能保证结尾的test 存在并且它是最后一项。如果你正在寻找更复杂的东西,你应该试试 urlrewritefilter。

    http://code.google.com/p/urlrewritefilter/

    【讨论】:

      【解决方案4】:

      您不应该在 web.xml 中这样做,而是可以将每个请求指向您的过滤器 (Patternfilter) 并检查 URL

      package com.inventwheel.filter;
      
      import java.io.IOException;
      import java.util.regex.Matcher;
      import java.util.regex.Pattern;
      
      import javax.servlet.Filter;
      import javax.servlet.FilterChain;
      import javax.servlet.FilterConfig;
      import javax.servlet.ServletException;
      import javax.servlet.ServletRequest;
      import javax.servlet.ServletResponse;
      import javax.servlet.annotation.WebFilter;
      import javax.servlet.http.HttpServletRequest;
      
      /**
       * Servlet Filter implementation class PatternFilter
       */
      @WebFilter("/*")
      public class PatternFilter implements Filter {
      
          /**
           * Default constructor. 
           */
          public PatternFilter() {
              // TODO Auto-generated constructor stub
          }
      
          /**
           * @see Filter#destroy()
           */
          public void destroy() {
              // TODO Auto-generated method stub
          }
      
          /**
           * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
           */
          public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
                  String servletPath = ((HttpServletRequest)request).getServletPath();
                  String requestURI = ((HttpServletRequest)request).getRequestURI();
                  Pattern pattern = Pattern.compile(".*"+servletPath+"/(.*)");
                  Matcher matcher = pattern.matcher(requestURI);
                  if (matcher.matches())
                  {
                  String param = matcher.group(1);
                  // do stuff with param here..
                  }
      
              chain.doFilter(request, response);
          }
      
          /**
           * @see Filter#init(FilterConfig)
           */
          public void init(FilterConfig fConfig) throws ServletException {
              // TODO Auto-generated method stub
          }
      
      }
      

      【讨论】:

        【解决方案5】:

        如上所述,基本 servlet 不支持您在问题中指定的模式。 Spring MVC 确实支持模式。 Here 是指向Spring Reference Document 中相关部分的链接。

        【讨论】:

          【解决方案6】:

          没有 Servlet 不支持这样的模式,其他人提到的可能的方法是在 xyz 之后使用 /*,但这不会检查 {value}/test。最好选择 Spring 或 JAX-RS。但是,如果您打算坚持使用 Servlet,则可以使用一种更好的方式来编写它:

          @WebServlet(urlPatterns = {"/xyz/*"})

          【讨论】:

            【解决方案7】:

            2022 年的答案。

            1. Servlet 仍然不允许使用通配符,因此我们不能执行以下操作:
              /xyz/{value}/test

            2. Paul Tuckeys urlrewritefilter 仍为 4.0.3 版本,与新的 jakarta 命名空间 [1] 不兼容(版本 5 正在开发中)。

            我在 Tomcat 本身中找到了一个解决方案,它具有 RewriteValve 功能。
            有关分步手册,请参阅https://rmannibucau.metawerx.net/post/tomcat-rewrite-url。这是在 URL 中间允许使用通配符的便捷解决方案。

            [1]https://github.com/paultuckey/urlrewritefilter/issues/239

            【讨论】:

              猜你喜欢
              • 2018-01-24
              • 2015-03-01
              • 2016-07-05
              • 2013-01-20
              • 2013-09-24
              • 2012-04-17
              • 2012-07-23
              相关资源
              最近更新 更多