使用web.xml,Servlet 3.0和Jersey部署JAX-RS应用程序 [英] Deployment of a JAX-RS application using web.xml, Servlet 3.0 and Jersey
问题描述
我正在尝试使用web.xml,servlet 3.0和jersey API部署我的应用程序.不幸的是,它不起作用.
I'm trying to deploy my application, using web.xml, servlet 3.0, and jersey API. Unfortunately, it doesn't work.
这是MyApplication.class:
This is MyApplication.class :
package com.example;
public class MyApplication extends Application {
public Set<Class<?>> getClasses() {
Set<Class<?>> s = new HashSet<Class<?>>();
s.add(MyResource.class);
return s;
}
}
这是MyResource:
This is MyResource :
@Path("/helloworld")
@Produces(MediaType.TEXT_PLAIN)
public class MyResource {
@GET
public String getHello() {
return "HelloWorld !";
}
}
还有我的web.xml:
And my web.xml :
<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
On client side, I'm using this url : http://localhost:8080/[projectname]/webapi/helloworld
我有这个错误:
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.
What's wrong ? :/ I'm using Tomcat 7.
PS:使用servlet 2.x,它可以工作:
PS : with a servlet 2.x, it works :
<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>
但是稍后我将需要异步模式.
but i will need asynchronous mode later.
谢谢!
推荐答案
更新:自编写此答案以来,我发现了一种避免使用官方的Tomcat上需要web.xml的方法Glassfish Jersey实施.在此处查看以获得详细信息.
Update: Since writing this answer, I've found out a way to avoid needing a web.xml on Tomcat using the official Glassfish Jersey implementation. Look here for details.
如果您正在使用标准的Tomcat安装(或某些其他servlet容器),则AFAIK不能避免在web.xml
文件*中明确告诉它要启动哪些servlet.由于无论如何都必须使用web.xml
,因此使宁静的Web服务正常工作的最简单方法是忘记完全扩展javax.ws.rs.core.Application
,而只需在其中指定上下文路径即可.您仍然可以使用标准的jax-rs批注来声明实际的Web服务.
If you're using a standard Tomcat install (or some other servlet container), AFAIK you can't avoid explicitly telling it what servlets to start in the web.xml
file*. Since you have to use web.xml
anyway, the simplest way to get restful web services working is to forget extending javax.ws.rs.core.Application
entirely and just specify the context path there. You can still use standard jax-rs annotations to declare the actual web services.
web.xml:
<?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>
两个值得注意的地方:
-
由于servlet容器通常不包含REST实施,因此您需要将REST实施捆绑在WAR文件中.由于Jersey是JAX-RS的参考实现,因此我在上面的
servlet-class
元素中使用了该实现.您可以根据需要将其替换为Apache CXF实现.
You will need to bundle a REST implementation in your WAR file, since servlet containers don't usually contain one. Since Jersey is the reference implementation for JAX-RS, that's the one I'm using in the
servlet-class
element above. You can replace this with Apache CXF implementation if you want.
init-param
元素告诉Jersey用来搜索带有Web服务注释的Java文件的包.编辑此内容以指向您的Web服务.请注意,如果您选择使用apache CXF而不是Jersey,则所有init-param
元素中所需的内容都会有所不同.认识CXF的人请发表他们的想法.
The init-param
element tells Jersey which of your packages to search for Java files with web service annotations. Edit this to point to your web services. Note that if you opt to use apache CXF instead of Jersey, the stuff needed in any init-param
elements will be different. Someone who knows CXF please post what they would be.
如果使用的是Maven,只需在pom.xml
文件的dependencies
部分中为jersey-servlet
添加依赖项:
If you're using Maven, just add a dependency to jersey-servlet
in the dependencies
section of your pom.xml
file:
<dependencies>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-servlet</artifactId>
<version>1.18.2</version>
</dependency>
...
</dependencies>
此后,使用Java类中的标准JAX-RS批注直接声明Web服务:
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);
}
}
这应该是您所需要的.如果您的Tomcat安装在端口8080上本地运行,并且您将WAR文件部署到上下文myContext
,则转到
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
...应该产生预期的结果(5).
...should produce the expected result (5).
干杯!
*如果您知道在不使用web.xml
的情况下将泽西servlet添加到Tomcat中的上下文的方法,请有人纠正我-也许是使用上下文或生命周期侦听器?
* Someone please correct me if you know of a way to a add the Jersey servlet to the context in Tomcat without using web.xml
--maybe by using a context or life cycle listener?
这篇关于使用web.xml,Servlet 3.0和Jersey部署JAX-RS应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!