如何在web.xml中处理多个精确匹配的REST服务映射?
如何在Jersey 2.42中实现多个精确URL匹配的REST服务
需要创建包含多个精确匹配的REST服务,使用Jersey 2.42,且不能使用/*模式(因为有其他过滤器需要处理对应请求)。当前配置下请求无法正常工作:web.xml中给Jersey Servlet映射了/foo和/bar两个精确路径,但对应的资源类使用@Path("/foo")和@Path("/bar")时,请求会返回404。
问题原因
当Servlet的url-pattern是精确匹配(比如/foo)时,Jersey会将请求的路径去掉Servlet映射的前缀部分,用剩余的路径去匹配资源类的@Path注解。比如请求/foo时,Jersey内部处理的路径是空字符串,而资源类的@Path("/foo")无法匹配空路径,导致404。
解决方案一:调整资源类的@Path为根路径
保持web.xml的Servlet映射不变,将每个资源类的@Path改为"/",因为Jersey处理的是去掉Servlet前缀后的路径:
原web.xml(无需修改)
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <servlet> <servlet-name>main-servlet</servlet-name> <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> <init-param> <param-name>jersey.config.server.provider.packages</param-name> <param-value>com.test</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>main-servlet</servlet-name> <url-pattern>/foo</url-pattern> <url-pattern>/bar</url-pattern> </servlet-mapping> </web-app>
修改后的FooResource
@Path("/") public class FooResource { @GET public String foo() { return "Foo"; } }
修改后的BarResource
@Path("/") public class BarResource { @GET public String bar() { return "Bar"; } }
此时请求/foo时,Jersey用空路径匹配FooResource的@Path("/");请求/bar时匹配BarResource的@Path("/"),Servlet映射已完成请求分流,两者互不干扰。
解决方案二:为每个精确匹配创建独立Servlet
如果希望资源类保留原有的@Path,可以为每个精确路径创建单独的Jersey Servlet,每个Servlet只映射一个精确路径:
修改后的web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <!-- 处理/foo的Servlet --> <servlet> <servlet-name>foo-servlet</servlet-name> <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> <init-param> <param-name>jersey.config.server.provider.classnames</param-name> <param-value>com.test.FooResource</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>foo-servlet</servlet-name> <url-pattern>/foo</url-pattern> </servlet-mapping> <!-- 处理/bar的Servlet --> <servlet> <servlet-name>bar-servlet</servlet-name> <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> <init-param> <param-name>jersey.config.server.provider.classnames</param-name> <param-value>com.test.BarResource</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>bar-servlet</servlet-name> <url-pattern>/bar</url-pattern> </servlet-mapping> </web-app>
资源类保持不变
@Path("/foo") public class FooResource { @GET public String foo() { return "Foo"; } }
@Path("/bar") public class BarResource { @GET public String bar() { return "Bar"; } }
这种方式每个Servlet独立负责一个路径,避免匹配冲突,但会增加Servlet数量,适合路径数量较少的场景。
内容的提问来源于stack exchange,提问作者Please
相关产品推荐
相关产品推荐

