82

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

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


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

web.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 应用程序?

4

6 回答 6

171

** 如果您使用 TOMCAT 或 JETTY,请阅读!**

接受的答案确实有效,但前提是 webapp 部署到 Glassfish 或 Wildfly 等应用服务器,以及可能具有 EE 扩展的 servlet 容器,如 TomEE。它不适用于像 Tomcat 这样的标准 servlet 容器,我敢肯定大多数在这里寻找解决方案的人都想使用它。

如果您使用的是标准 Tomcat 安装(或其他一些 servlet 容器),则需要包含 REST 实现,因为 Tomcat 没有提供。如果您使用的是 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)。

于 2014-11-03T19:38:14.090 回答
51

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

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

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

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

于 2012-02-21T18:21:18.597 回答
15

JAX-RS:Java™ API for RESTful Web Services规范的第 2 章描述了 JAX-RS 应用程序在 Servlet 环境中的发布过程(规范中的第2.3.2 节 Servlet)。

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

建议实现支持 Servlet 3 框架可插拔机制,以实现容器之间的可移植性并利用容器提供的类扫描工具。

简而言之,如果您想使用 no-web.xml 方法,可以使用 javax.ws.rs.core.Application 的自定义实现,该实现使用javax.ws.rs.ApplicationPath注释注册 RESTful 服务资源。

@ApplicationPath("/rest")

尽管您专门询问了 Jersey,但您可能还想阅读使用 JAX-RS 和 WebSphere 8.5 Liberty Profile 实现 RESTful 服务的文章,其中我描述了WebSphere Liberty Profile的 no-web.xml 发布过程(使用 Apache Wink 作为JAX-RS)。

于 2013-04-01T21:18:38.147 回答
7

您需要在 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 的入门示例

于 2015-08-19T07:57:27.560 回答
2

前面提到的依赖项对我不起作用。来自泽西用户指南:

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

于 2018-03-05T18:53:16.120 回答
0

正如@Eran-Medan 指出的那样,JBoss EAP 7.1(注意没有 Web 应用程序所以没有 servlet,我在 EJB 3.2 项目中这样做)我必须添加“值”属性,因为我得到了一个例外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
于 2017-05-25T20:01:58.547 回答