如何仅使用注释(不使用web.xml)设置JAX-RS Application?


80

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


1
如果可以尝试使用NetBeans,则可以使用一个向导来创建RESTFul Web服务。看来您要尝试的是此向导在6.8版中所做的。我正在使用7.0.1,并且新方法更简单,但为此使用了一个servlet,即com.sun.jersey.spi.container.servlet.ServletContainer,但它在web.xml中定义
perissf 2012年

Answers:


166

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

接受的答案确实有效,但前提是将Web应用程序部署到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)。


6
@JavaDude-您必须配置Maven以生成WAR文件,即使该文件web.xml不存在。在你的pom.xml,在“构建>插件”,加(如果尚未有)<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-war-plugin</artifactId><version>2.3</version><configuration><failOnMissingWebXml>false</failOnMissingWebXml></configuration></plugin>
Alvin Thompson

6
@JavaDude-重要的部分是<failOnMissingWebXml>false</fai‌​lOnMissingWebXml>选项。
Alvin Thompson

3
@JavaDude-否则,您可能没有创建扩展类并向Application其添加@ApplicationPath注释的类。该类可以为空,但必须在那里。
Alvin Thompson

3
仅添加jersey-container-servlet,而无需拉出整个jaxrs-ri依赖项就足够了。例如,在我的情况下为'org.glassfish.jersey.core:jersey-server:2.18'+ 'org.glassfish.jersey.containers:jersey-container-servlet:2.18'
leveluptor

3
由于问题清楚地用“ java-ee”标记,因此我不理解关于提供和支持不能解决jee环境的答案的模糊性。-1
Jan Galinski 2015年

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上试用)


1
不明白它是如何工作的,您可以仅使用注释而无需任何其他配置?我已经尝试过这种方法,但仍然无法正常工作...
Filipe 2014年

2
@Filipe:我猜您正在使用Tomcat或其他一些servlet容器。这实际上不适用于Tomcat之类的servlet容器-仅适用于Glassfish或Wildfly等应用服务器,以及TomEE。如果您使用的是Tomcat,请参阅下面的我的答案。
2014年

8
此答案不适用于Tomcat或Jetty!请查看我的答案以使这些(和其他)servlet容器中的内容正常工作。
2014年

1
根据您的实现,您确实需要一个web.xml,尽管一个空的就足够了。参见docs.jboss.org/resteasy/docs/3.0.9.Final/userguide/html_single/…–
Benjamin Maurer

这适用于WebSphere Liberty,但不适用于WebSphere 8.x和9.0 Classic。
阿基米德·特拉哈诺

15

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

请注意,仅建议使用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)。


1
谢谢!,我还有一个与之息息相关的问题,使我发疯,有没有办法在根目录中拥有路径(例如@ApplicationPath(“ / *”)),并且仍然仅使用Annotations服务JSP?(尽管即使使用web.xml配置也无法实现)-问题在这里:stackoverflow.com/questions/10874188/…,因为您似乎对JAX-RS的了解非常好,请您看看吗?:)也许您会看到我所缺少的...谢谢!
Eran Medan

我不知道。胆量告诉我,它不应该使用任何其他配置,因为解析资源以处理请求的过程是从与URL模式的完全匹配开始的。我会看看并回应。感谢您鼓励我扩展知识!:-)
Jacek Laskowski

即时通讯使用@ApplicationPath("")有在JBoss EAP 7根我的REST服务(相对于Web应用程序上下文根)我既没有beans.xml也没有web.xml
朱利安·克朗格

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的入门示例


如果使用ResourceConfig / Application,如何删除web.xml?
BAE

是的,但是您需要在pom.xml中添加它:我<failOnMissingWebXml>
ACV

谢谢。但是web.xml可以做什么,而ResourceConfig不能吗?
BAE

不,我认为,因为不再需要servlet规范3.0 web.xml。但是有时使用web.xml更为方便,因为如果您要更改某些内容,则不需要重新编译。
ACV

而且,如果您不使用Maven怎么办?我的项目现在太大,无法切换回去。
TheRealChx101 '17

1

前面提到的依赖项对我不起作用。从Jersey用户指南中:

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


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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.