Tomcat 是否支持开箱即用的 JAX-RS(是否支持 JAX-RS)?

Does Tomcat support JAX-RS out of the box (is it JAX-RS aware)?

从教科书“RESTful Java with JAX-RS”我们可以读到:

If our application server is JAX-RS-aware or, in other words, is tightly integrated with JAX-RS declare our ShoppingApplication class as a servlet:

<?xml version="1.0"?>
<web-app>
  <servlet>
    <servlet-name>Rest</servlet-name>
    <servlet-class>
      com.restfully.shop.services.ShoppingApplication
    </servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>Rest</servlet-name>
    <url-pattern>/*</url-pattern>
  </servlet-mapping>
</web-app> 

If our application server is not JAX-RS-aware, you will have to specify the JAX-RS provider's servlet that handles JAX-RS invocations. The Application class should be specified as an init-param of the servlet:

现在我的问题是:Tomcat 是一个支持 JAX-RS 的 Servlet 容器吗?您如何区分 JAX-RS 感知的 servlet 容器和不感知 JAX-RS 的 servlet 容器?为什么在第一种情况下可以使用扩展 javax.ws.rs.core.Application 作为 Servlet 的自定义 class?

"Is Tomcat a JAX-RS aware Servlet container?"

没有

"How do you distinguish a servlet container JAX-RS aware from one wich is not JAX-RS aware?"

事实上这只是一个 Servlet 容器,应该告诉您它不是“JAX-RS 感知”。 JAX-RS 是 Java EE 规范的一部分。 Servlet 容器正如其名称所暗示的那样支持; Servlet 的容器。他们可能支持 JSP 等其他小功能,但不会支持整个 EE 规范。这不是他们设计的一部分。如果你想在 Servlet 容器中使用 JAX-RS,你需要添加一个实现,比如 Jersey or Resteasy

当您说到 Servlet 容器时,您会想到像 Jetty、Tomcat、Undertow、Grizzly 这样的服务器。如果您想要完整的 Java EE 支持,那么您需要获得支持整个规范的实际 Java EE 应用程序服务器,例如 JBoss/Wildfly、Glassfish、TomEE、WebSphere、WebLogic。

"Why in the first case it's possible to use your custom class wich extends javax.ws.rs.core.Application as a Servlet?"

我无法使用 Glassfish 4.0 或 Wildfly 8.1 生成工作示例,JAX-RS specification 中也没有指定。在 Glassfish 中,我会得到一个关于 ShoppingApplication 不是 Servlet 的异常,而在 Wildfly 中,我只会得到一个 NotFoundException,这意味着应用程序永远不会加载。

我能找到的最接近书中所述的内容是将应用程序 class 的名称指定为 <servlet-name> JAX-RS 规范的一部分,但完全不依赖于部署到 Java EE 服务器)

<servlet>
    <servlet-name>com.restfully.shop.services.ShoppingApplication</servlet-name>
</servlet>
<servlet-mapping>
    <servlet-name>com.restfully.shop.services.ShoppingApplication</servlet-name>
    <url-pattern>/api/*</url-pattern>
</servlet-mapping>

这来自 JAX-RS 规范

If an Application subclass is present that is not being handled by an existing servlet, then the servlet added by the ContainerInitializer MUST be named with the fully qualified name of the Application subclass.