如何设置 JAX-RS 应用程序只使用注释(没有 web.xml) ?

是否可以仅使用注释来设置 JAX-RS 应用程序? (使用 Servlet 3.0和 JAX-RS Jersey 1.1.0)

我试过了,没有运气。似乎需要使用一些 web.xml


配置 A (正常工作,但具有 web.xml 配置)

Xml

   ...
<servlet>
<servlet-name>org.foo.rest.MyApplication</servlet-name>
</servlet>
<servlet-mapping>
<servlet-name>org.foo.rest.MyApplication</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
...

爪哇咖啡

@ApplicationPath("/")
public class MyApplication extends Application {
...
}

配置 B (不工作,引发异常)

@ApplicationPath("/")
@WebServlet("/*") // <--
public class MyApplication extends Application {
...
}

后者似乎坚持认为 Application 将是 Servlet 的一个子类(这个例外不会留下任何猜测)

java.lang.ClassCastException: org.foo.rest.MyApplication cannot be cast to javax.servlet.Servlet

问题

  1. 为什么 web.xml 定义有效而注释没有效? 有什么区别吗?

  2. 有没有一种方法可以让它工作,例如有一个没有 web.xml 的 JAX-RS 应用程序?

122513 次浏览

看起来我所需要做的就是这个(Servlet 3.0及以上版本)

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;


@ApplicationPath("/*")
public class MyApplication extends Application {
...
}

而且显然不需要 web.xml 配置(在 Tomcat 7上进行了尝试)

JAX-RS: 用于 RESTful Web 服务的 JavaTM API规范的第2章描述了 JAX-RS 应用程序在 Servlet 环境中的发布过程(规范中的 2.3.2 Servlet部分)。

请注意,仅推荐 Servlet3环境(第2.3.2节 Servlet,第6页) :

建议实现支持 Servlet 3 框架可插入性机制,以实现 集装箱和利用自己的集装箱提供类 扫描设备。

简而言之,如果您希望使用 no-web.xml 方法,那么可以通过使用 应用程序路径注释注册 RESTful 服务资源的自定义 应用程序实现。

@ApplicationPath("/rest")

虽然您特别询问了 Jersey,但您可能还想阅读一下文章 使用 JAX-RS 和 WebSphere 8.5 Liberty Profile 实现 RESTful 服务,其中我描述了 WebSphereLiberty 概要的 no-web.xml 发布过程(使用 Apache Wink 作为 JAX-RS 的实现)。

如果你使用 TOMCAT 或者 JETTY 请阅读

接受的答案 是的可以工作,但是只有当 Web 应用被部署到像 Glassfish 或 Wildfly 这样的应用服务器上,或者可能部署到具有像 TomEE 这样的 EE 扩展的 servlet 容器上时才能工作。它的 没有工作在像 Tomcat 这样的标准 servlet 容器上,我相信大多数在这里寻找解决方案的人都想使用它。

如果您使用的是标准的 Tomcat 安装(或其他 servlet 容器) ,那么您需要包含一个 REST 实现,因为 Tomcat 没有自带的 REST 实现。如果您正在使用 Maven,请将其添加到 dependencies部分:

<dependencies>
<dependency>
<groupId>org.glassfish.jersey.bundles</groupId>
<artifactId>jaxrs-ri</artifactId>
<version>2.13</version>
</dependency>
...
</dependencies>

然后向项目中添加一个应用程序配置类。如果除了为其他服务设置上下文路径之外,您没有任何特殊的配置需求,那么该类可以是空的。一旦添加了这个类,就不需要在 web.xml中配置任何东西(或者根本不需要配置) :

package com.domain.mypackage;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;


@ApplicationPath("rest") // set the path to REST web services
public class ApplicationConfig extends Application {}

在此之后,使用 Java 类中的标准 JAX-RS 注释直接声明 Web 服务:

package com.domain.mypackage;
import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.GET;
import javax.ws.rs.MatrixParam;
import javax.ws.rs.Path;


// It's good practice to include a version number in the path so you can have
// multiple versions deployed at once. That way consumers don't need to upgrade
// right away if things are working for them.
@Path("calc/1.0")
public class CalculatorV1_0 {
@GET
@Consumes("text/plain")
@Produces("text/plain")
@Path("addTwoNumbers")
public String add(@MatrixParam("firstNumber") int n1, @MatrixParam("secondNumber") int n2) {
return String.valueOf(n1 + n2);
}
}

这应该就是你所需要的。如果您的 Tomcat 安装在本地端口8080上运行,并且您将 WAR 文件部署到上下文 myContext,那么将..。

http://localhost:8080/myContext/rest/calc/1.0/addTwoNumbers;firstNumber=2;secondNumber=3

... 应该产生预期的结果(5)。

您需要在 pom.xml 中设置正确的依赖项

<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
</dependency>

更多详情请浏览此网页: Jax-rs 的初始示例

正如@Eran-Medan 指出的,JBoss EAP 7.1(注意,没有 Web 应用程序,所以没有 servlet,我是在 EJB 3.2项目中做的)我必须添加“ value”属性,因为我得到了一个异常,即 value 属性是必需的。

这招对我很管用

    @ApplicationPath(value="/*")
public class MyApplication extends Application {


private Set singletons = new HashSet();


public MyApplication() {
singletons.add(new MyService());
}


...
}

堆栈跟踪

    Caused by: java.lang.annotation.IncompleteAnnotationException: javax.ws.rs.ApplicationPath missing element value
at sun.reflect.annotation.AnnotationInvocationHandler.invoke(AnnotationInvocationHandler.java:80)
at com.sun.proxy.$Proxy141.value(Unknown Source)
... 21 more

前面提到的依赖项对我来说不起作用:

Jersey 提供了两个 Servlet 模块。第一个模块是 Jersey 核心 Servlet 模块,它提供核心 Servlet 集成支持,并且在任何 Servlet 2.5或更高的容器中都是必需的:

<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
</dependency>

为了支持其他 Servlet 3. x 部署模式和异步 JAX-RS 资源编程模型,需要额外的 Jersey 模块:

<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
</dependency>

Jersey-Container-servlet 模块依赖于 jersey-Container-servlet-core 模块,因此在使用它时,不需要显式声明 jersey-Container-servlet-core 依赖项。

Https://jersey.github.io/documentation/latest/deployment.html#deployment.servlet.3