在同一根上下文下托管静态内容和 JAX-RS 服务 [英] Hosting Static Content and JAX-RS Services Under the Same Root Context

查看:28
本文介绍了在同一根上下文下托管静态内容和 JAX-RS 服务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有多个打包为 WAR 的 Java Web 应用程序,所有这些应用程序都打包在一个 EAR 中.我们的 RESTful 服务是使用 JAX-RS 和版本特定的 WAR 构建的.

We have multiple Java web apps packaged as WARs all packaged in an EAR. Our RESTful services are built using JAX-RS and in version specific WARs.

我们想为每个特定于版本的 WAR 添加静态内容,但对静态内容和 RESTful 服务 API 调用都使用(WAR 的)根上下文,以便以下所有 URL 都可以使用:

We'd like to add static content for each of these version specific WARs, but use the root context (of the WAR) for both the static content and the RESTful service API calls, such that all of the following URLs will work:

{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 有效:

The following deployment structure is what we currently have, which works for the JAX-RS services, but not the static content. In other words these URLs work:

{hostname}/v1/orders/{uid}  <-- JAX-RS RESTful API (v1)
{hostname}/v2/orders/{uid}  <-- JAX-RS RESTful API (v2)

但问题是这些 URL 无法访问:

But the problem is that these URLS are inaccessible:

{hostname}/v1/swagger.yaml  <-- Static Content describing the v1 API
{hostname}/v2/swagger.yaml  <-- Static Content describing the v2 API

问题:我们如何让这些静态 URL 发挥作用?

Question: How do we get these static URLs to work?

这是爆炸的 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:

Here's the 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 映射:

Here's the ApplicationV1.java (JAX-RS) implementation, notice the URL mapping:

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 映射:

Here's the OrdersResourceV1.java (JAX-RS) implementation, notice the URL mapping:

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 将如下所示,但我们的目标是不包含任何像这样的无关路径元素.

I do know that if we changed ApplicationV*.java's mapping to @ApplicationPath("/services"), that the static content will be assessable, but the URLs will then be as follows, but it's our goal to not include any extraneous path elements like this.

{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 处理程序,是否有允许静态回退的配置选项?

So my question is, how do we get the JAX-RS and static content under the root context for the WAR (/v1 and /v2)? Is there a different way to map the URLs? Or is there a configuration option that allows for a static fallback if JAX-RS doesn't have a handler for the URL?

我希望这可以通过 JavaEE 通用方式解决,但如果不能,我们将在 Java8 上使用 Wildfly 8.1.

I'm hoping that this can be solved a JavaEE generic fashion, but if not, we're using Wildfly 8.1 on Java8.

推荐答案

所以我找到了一个有效的解决方案(经过测试).如 Resteasy 文档 - RESTEasy 中所述一个 servlet 过滤器:

So I found a solution (tested) that works. As stated in the Resteasy Documentation - RESTEasy as a servlet Filter:

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

The downside of running Resteasy as a Servlet is that you cannot have static resources like .html and .jpeg files in the same path as your JAX-RS services. Resteasy allows you to run as a Filter instead. If a JAX-RS resource is not found under the URL requested, Resteasy will delegate back to the base servlet container to resolve URLs.

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>

这篇关于在同一根上下文下托管静态内容和 JAX-RS 服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆