在同一根上下文中托管静态内容和JAX-RS服务

时间:2015-05-07 21:27:41

标签: java java-ee jax-rs resteasy wildfly-8

我们将多个打包为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

问题:我们如何让这些静态网址生效?

这是爆炸的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&amp; 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"),那么静态内容将是可评估的,但网址将如下所示,但我们的目标是不包含任何内容像这样无关的路径元素。

{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。

2 个答案:

答案 0 :(得分:2)

所以我找到了一个有效的解决方案(已测试)。如Resteasy Documentation - RESTEasy as a servlet Filter中所述:

  

将Resteasy作为Servlet运行的缺点是,您不能将.html和.jpeg文件等静态资源放在与JAX-RS服务相同的路径中。 Resteasy允许您作为过滤器运行。如果在请求的URL下找不到JAX-RS资源,Resteasy将委托回基本servlet容器来解析URL。

web.xml示例

<web-app>
    <filter>
        <filter-name>Resteasy</filter-name>
        <filter-class>
            org.jboss.resteasy.plugins.server.servlet.FilterDispatcher
        </filter-class>
        <init-param>
            <param-name>javax.ws.rs.Application</param-name>
            <param-value>com.restfully.shop.services.ShoppingApplication</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>Resteasy</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

答案 1 :(得分:0)

我找到了另一个解决方案(感谢https://stackoverflow.com/a/3582215/589525)。这适用于JBoss 6上的RestEasy。只需将默认servlet添加到映射中

<!--existing mapping: -->
<servlet-mapping>
  <servlet-name>Resteasy</servlet-name>
  <url-pattern>/rest/*</url-pattern>
</servlet-mapping>

<servlet-mapping>
  <servlet-name>default</servlet-name>
  <url-pattern>*</url-pattern>
</servlet-mapping>