Servlet和路径参数,例如/xyz/{value}/test,如何在web.xml中映射?

40

Servlet支持以下URL吗:

/xyz/{value}/test

value可以被替换为文本或数字。

如何在web.xml中进行映射?


有关于:https://dev59.com/X2sy5IYBdhLWcg3w4x_c(可能的重复)。 - shelley
7个回答

53
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的URL重写过滤器或者自己开发URL重写过滤器


2
这真的是提取不是GET参数的URL参数的方法吗?这看起来相当臃肿、难以维护,易受偏移错误和1995年的影响。 - Herbert
3
@Herbert:只需在Servlet API之上使用一个支持路径参数的框架,例如JAX-RS或MVC。 - BalusC
另一个选项是getRequestURI(),在我的情况下getPathInfo()为空。 - leventunver
@leventunver:当过滤器为空时,或者在请求的某个地方使用了糟糕的实现请求包装器,或者由于Servlet容器中的错误而导致它为空。 - BalusC
我修改了一个扩展GenericFilterBean的类。使用ServletRequest作为输入。 - leventunver
@leventunver:嗯,过滤器显然不是一个servlet。 - BalusC

10

就像其他人所说的那样,servlet规范不允许使用这样的模式;但是,如果这符合您的用例,您可以考虑使用JAX-RS,因为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://dev59.com/X2sy5IYBdhLWcg3w4x_c#8303767相关)。


3
它支持映射该URL,但不提供任何验证。
在您的Web xml中,您可以这样做....
/xyz/*

但这并不能保证末尾的test是否存在,以及它是否是最后一个项目。如果您正在寻找更复杂的内容,则应该尝试使用urlrewritefilter。 http://code.google.com/p/urlrewritefilter/

1

Servlet不支持那样的模式,其他人提到的可能的方法是在xyz后面使用/*,但这并不检查{value}/test。最好使用Spring或JAX-RS。但是,如果您计划坚持使用Servlet,则更好的编写方式是:

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


1

你不应该在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
    }

}

0

来自2022年的答案。

  1. Servlets仍然不允许通配符,因此我们无法做到以下操作:
    /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


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

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