【发布时间】:2015-07-18 16:04:56
【问题描述】:
我们有多个打包为 WAR 的 Java Web 应用程序,所有这些都打包在一个 EAR 中。我们的 RESTful 服务是使用 JAX-RS 和版本特定的 WAR 构建的。
我们希望为每个特定版本的 WAR 添加静态内容,但对静态内容和 RESTful 服务 API 调用都使用(WAR)的根上下文,以便以下所有 URL 都可以使用:
{hostname}/v1/swagger.yaml <-- Static Content describing the v1 API
{hostname}/v1/orders/{uid} <-- JAX-RS RESTful API (v1)
{hostname}/v2/swagger.yaml <-- Static Content describing the v2 API
{hostname}/v2/orders/{uid} <-- JAX-RS RESTful API (v2)
以下部署结构是我们目前拥有的,适用于 JAX-RS 服务,但不适用于静态内容。换句话说,这些 URL 有效:
{hostname}/v1/orders/{uid} <-- JAX-RS RESTful API (v1)
{hostname}/v2/orders/{uid} <-- JAX-RS RESTful API (v2)
但问题是这些 URL 无法访问:
{hostname}/v1/swagger.yaml <-- Static Content describing the v1 API
{hostname}/v2/swagger.yaml <-- Static Content describing the v2 API
问题:我们如何让这些静态 URL 发挥作用?
这是分解后的 EAR:
example.ear
META-INF
application.xml
v1.war
swagger.yaml
WEB-INF
web.xml
classes
ApplicationV1.class
OrdersResourceV1.class
v2.war
swagger.yaml
WEB-INF
web.xml
classes
ApplicationV2.class
OrdersResourceV2.class
这是 EAR application.xml:
<?xml version="1.0"?>
<application xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application_6.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="6">
<application-name>...</application-name>
<module>
<web>
<web-uri>v1.war</web-uri>
<context-root>/v1</context-root>
</web>
</module>
<module>
<web>
<web-uri>v2.war</web-uri>
<context-root>/v2</context-root>
</web>
</module>
<module>
<web>
<web-uri>another.war</web-uri>
<context-root>/</context-root>
</web>
</module>
</application>
这里是 v1 和 v2 web.xml:
<web-app version="3.0" 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_3_0.xsd">
</web-app>
这是ApplicationV1.java (JAX-RS) 的实现,注意 URL 映射:
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
@ApplicationPath("/")
public class ApplicationV1 extends Application {
private Set<Object> singletons = new HashSet<Object>();
public ApplicationV1() {
singletons.add(new OrdersResourceV1());
}
@Override
public Set<Object> getSingletons() {
return singletons;
}
}
这是OrdersResourceV1.java (JAX-RS) 实现,注意 URL 映射:
import javax.enterprise.context.RequestScoped;
import javax.ws.rs.*;
@RequestScoped
@Path("/orders")
public class OrdersResourceV1 {
@GET
@Path("/{uid}")
@Produces("application/json;charset=UTF-8")
public Response getOrder(@PathParam("uid") String orderUid) {
<ommited for brevity>
}
}
我知道如果我们将 ApplicationV*.java 的映射更改为 @ApplicationPath("/services"),静态内容将是可评估的,但 URL 将如下所示,但我们的目标是不包含任何无关的路径元素,例如这个。
{hostname}/v1/swagger.yaml <-- Static Content describing the v1 API
{hostname}/v1/services/orders/{uid} <-- JAX-RS RESTful API (v1)
{hostname}/v2/swagger.yaml <-- Static Content describing the v2 API
{hostname}/v2/services/orders/{uid} <-- JAX-RS RESTful API (v2)
所以我的问题是,我们如何在 WAR(/v1 和 /v2)的根上下文下获取 JAX-RS 和静态内容?是否有不同的方法来映射 URL?或者,如果 JAX-RS 没有 URL 处理程序,是否有允许静态回退的配置选项?
我希望这可以通过 JavaEE 通用方式解决,但如果不能,我们将在 Java8 上使用 Wildfly 8.1。
【问题讨论】:
-
问题是servlet容器有一个默认的servlet来处理静态内容。当您定义具有相同映射的 servlet 时,即
/*,这将隐藏静态内容 servlet。当调用 Resteasy servlet 时,如果找不到请求的静态内容,它不会回退到默认的 servlet。我知道 Jersey 有一个配置属性要设置,它自己处理静态内容,但我不知道 Resteasy。我checked, but you can check again -
您可以使用一个过滤器,该过滤器可以了解何时请求针对静态内容并自行响应;您将必须重现静态资源 servlet 的部分(或全部?)功能。如果您只想提供 swagger.yaml,那么您可以创建一个 JAX-RS 服务,通过从类路径加载例如文件并设置正确的标头来响应此 URL。
标签: java jakarta-ee jax-rs resteasy wildfly-8