Deployment of a JAX-RS application using web.xml, Servlet 3.0 and Jersey
我正在尝试使用 web.xml、servlet 3.0 和 jersey API 部署我的应用程序。不幸的是,它不起作用。
这是 MyApplication.class :
1 2 3 4 5 6 7 8 9 | package com.example; public class MyApplication extends Application { public Set<Class< ? >> getClasses() { Set<Class< ? >> s = new HashSet<Class< ? >>(); s.add(MyResource.class); return s; } } |
这是我的资源:
1 2 3 4 5 6 7 8 | @Path("/helloworld") @Produces(MediaType.TEXT_PLAIN) public class MyResource { @GET public String getHello() { return"HelloWorld !"; } } |
还有我的 web.xml :
1 2 3 4 5 6 7 8 9 | <web-app> <servlet> <servlet-name>com.example.MyApplication</servlet-name> </servlet> <servlet-mapping> <servlet-name>com.example.MyApplication</servlet-name> <url-pattern>/webapi/*</url-pattern> </servlet-mapping> </web-app> |
在客户端,我正在使用这个网址:
http://localhost:8080/[项目名称]/webapi/helloworld
我有这个错误:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | java.lang.NullPointerException sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294) java.lang.ClassLoader.loadClass(ClassLoader.java:247) org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1629) org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1559) org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:491) org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99) org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953) org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408) org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1023) org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589) org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:1852) java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895) java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918) java.lang.Thread.run(Thread.java:662) |
怎么了? :/ 我正在使用 Tomcat 7.
PS:使用 servlet 2.x,它可以工作:
1 2 3 4 5 6 7 8 9 10 11 12 | <servlet> <servlet-name>Jersey Web Application</servlet-name> <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> <init-param> <param-name>jersey.config.server.provider.packages</param-name> <param-value>com.example</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>Jersey Web Application</servlet-name> <url-pattern>/webapi/*</url-pattern> </servlet-mapping> |
但我稍后需要异步模式。
谢谢!
更新:自从写了这个答案,我已经找到了一种方法来避免使用官方 Glassfish Jersey 实现在 Tomcat 上需要 web.xml。详情请看这里。
如果您正在使用标准的 Tomcat 安装(或其他一些 servlet 容器),AFAIK 您无法避免明确告诉它要在
web.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0" > <servlet> <servlet-name>rest-test</servlet-name> <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class> <init-param> <param-name>com.sun.jersey.config.property.packages</param-name> <param-value>com.domain.mypackage</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name> rest-test</servlet-name> <url-pattern>/rest/*</url-pattern> </servlet-mapping> </web-app> |
两个值得注意的点:
您需要在 WAR 文件中捆绑一个 REST 实现,因为 servlet 容器通常不包含一个。由于 Jersey 是 JAX-RS 的参考实现,这就是我在上面的
如果您使用的是 Maven,只需在
1 2 3 4 5 6 7 8 | <dependencies> <dependency> <groupId>com.sun.jersey</groupId> jersey-servlet</artifactId> <version>1.18.2</version> </dependency> ... </dependencies> |
在此之后,可以直接在 Java 类中使用标准 JAX-RS 注释来声明 Web 服务:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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 文件部署到上下文
1 | http://localhost:8080/myContext/rest/calc/1.0/addTwoNumbers;firstNumber=2;secondNumber=3 |
...应该会产生预期的结果 (5)。
干杯!
* 如果您知道不使用
1 2 3 4 5 6 7 8 9 10 11 12 | package com.example; @ApplicationPath("/webapi") public class MyApplication extends Application { public Set<Class< ? >> getClasses() { Set<Class< ? >> s = new HashSet<Class< ? >>(); s.add(MyResource.class); return s; } } |
你需要在WEB-INF文件夹下创建web.xml,代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | <?xml version="1.0" encoding="UTF-8"?> <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> <servlet> <servlet-name>ServletAdaptor</servlet-name> <servlet-class> org.glassfish.jersey.servlet.ServletContainer </servlet-class> <init-param> <param-name>jersey.config.server.provider.packages</param-name> <param-value>package where MyResource resides</param-value> </init-param> <init-param> <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name> <param-value>true</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>ServletAdaptor</servlet-name> <url-pattern>/webresources/*</url-pattern> </servlet-mapping> <session-config> <session-timeout> 30 </session-timeout> </session-config> </web-app> |
现在您可以删除您的 MyApplication 类。部署和测试 Web 服务。它会工作
访问此链接可能会有所帮助:
https://jersey.java.net/documentation/latest/deployment.html#deployment.servlet.2
部分:4.7.1。 Servlet 2.x 容器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <web-app> <servlet> <servlet-name>MyApplication</servlet-name> <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> <init-param> ... </init-param> </servlet> ... <servlet-mapping> <servlet-name>MyApplication</servlet-name> <url-pattern>/myApp/*</url-pattern> </servlet-mapping> ... </web-app> |