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

发布于 2025-01-07 08:37:26 字数 1183 浏览 2 评论 0原文

是否可以仅使用注释来设置 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>
   ...

Java

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

配置 B(不工作,抛出异常)

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

后者似乎坚持认为应用程序将是Servlet 的子类(例外情况无需猜测)

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

问题

  1. 为什么 web.xml 定义起作用但注释不起作用?有什么区别?

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

Is it possible to set up a JAX-RS application using annotations only? (using Servlet 3.0 and JAX-RS Jersey 1.1.0)

I tried and had no luck. Using some web.xml seems required.


Configuration A (working, but has web.xml configuration)

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>
   ...

Java

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

Configuration B (not working, exception thrown)

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

The latter seems to insist that the Application will be a subclass of Servlet (the exception leaves no guesswork)

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

Questions

  1. Why the web.xml definition worked but the annotation didn't? What's the difference?

  2. Is there a way to have it worked, e.g. have a JAX-RS Application with no web.xml?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

青衫负雪 2025-01-14 08:37:26

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

接受的答案确实有效,但前提是 Web 应用程序部署到 Glassfish 或 Wildfly 等应用程序服务器,并且可能部署到具有 EE 扩展(如 TomEE)的 servlet 容器。它不适用于标准 servlet 容器(例如 Tomcat),我确信大多数在这里寻找解决方案的人都想使用 Tomcat。

如果您使用标准 Tomcat 安装(或其他一些 servlet 容器),则需要包含 REST 实现,因为 Tomcat 不附带 REST 实现。如果您使用 Maven,请将其添加到 dependency 部分:

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

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

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

** PLEASE READ IF YOU USE TOMCAT OR JETTY! **

The accepted answer does work, but only if the webapp is deployed to an app server like Glassfish or Wildfly, and possibly servlet containers with EE extensions like TomEE. It doesn't work on standard servlet containers like Tomcat, which I'm sure most people looking for a solution here want to use.

If you're using a standard Tomcat install (or some other servlet container), you need to include a REST implementation since Tomcat doesn't come with one. If you're using Maven, add this to the dependencies section:

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

Then just add an application config class to your project. If you don't have any special configuration needs aside from setting the context path for the rest services, the class can be empty. Once this class is added, you don't need to configure anything in web.xml (or have one at all):

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

After this, declaring your web services is straight forward using the standard JAX-RS annotations in your Java classes:

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);
  }
}

This should be all you need. If your Tomcat install is running locally on port 8080 and you deploy your WAR file to the context myContext, going to...

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

...should produce the expected result (5).

夜吻♂芭芘 2025-01-14 08:37:26

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

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

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

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

It seems that all I needed to do is this (Servlet 3.0 and above)

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

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

And no web.xml configuration was apparently needed (tried on Tomcat 7)

撩心不撩汉 2025-01-14 08:37:26

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

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

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

简而言之,如果您想使用 no-web.xml 方法,可以使用 javax.ws.rs.core.Applicationjavax.ws.rs.ApplicationPath 注释。

@ApplicationPath("/rest")

尽管您具体询问了 Jersey,您可能还想阅读文章使用 JAX-RS 和 WebSphere 8.5 Liberty Profile 实现 RESTful 服务 其中我描述了 WebSphere Liberty Profile(使用 Apache Wink 作为 JAX-RS 的实现)。

Chapter 2 of the JAX-RS: Java™ API for RESTful Web Services specification describes the publication process of a JAX-RS application in Servlet environment (section 2.3.2 Servlet in the specification).

Please note that Servlet 3 environment is recommended only (section 2.3.2 Servlet, page 6):

It is RECOMMENDED that implementations support the Servlet 3
framework pluggability mechanism to enable portability between
containers and to avail themselves of container-supplied class
scanning facilities.

In short, if you want to use a no-web.xml approach, it's possible with a custom implementation of javax.ws.rs.core.Application that registers RESTful service resources with the javax.ws.rs.ApplicationPath annotation.

@ApplicationPath("/rest")

Although you asked specifically about Jersey you may also like to read the article Implementing RESTful services with JAX-RS and WebSphere 8.5 Liberty Profile in which I described the no-web.xml publication process for WebSphere Liberty Profile (with Apache Wink as the implementation of JAX-RS).

别理我 2025-01-14 08:37:26

您需要在 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

You need to setup the right dependencies in 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>

More details here:
Starter example for jax-rs

乖乖 2025-01-14 08:37:26

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

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/部署.html#deployment.servlet.3

The previously mentioned dependencies did not work for me. From the Jersey User guide:

Jersey provides two Servlet modules. The first module is the Jersey core Servlet module that provides the core Servlet integration support and is required in any Servlet 2.5 or higher container:

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

To support additional Servlet 3.x deployment modes and asynchronous JAX-RS resource programming model, an additional Jersey module is required:

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

The jersey-container-servlet module depends on jersey-container-servlet-core module, therefore when it is used, it is not necessary to explicitly declare the jersey-container-servlet-core dependency.

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

蓝海似她心 2025-01-14 08:37:26

正如 @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

As @Eran-Medan pointed out, JBoss EAP 7.1 (note without a Web Application so no servlet, I was doing it in a EJB 3.2 project) I had to add the "value" attribute as such as I was getting an exception that the value attribute was required.

This worked for me

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

            private Set singletons = new HashSet();

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

            ...
    }

Stack Trace

    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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文