Java 使用 JAX-RS 创建 RESTful Web 服务并将其部署到 tomcat

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20442632/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 01:57:22  来源:igfitidea点击:

Create RESTful Web Service with JAX-RS and deploy it to tomcat

javaweb-servicesresttomcat

提问by amedeo avogadro

I'm trying to create and deploy a RESTful Web Service using JAX-RS and deploy it to tomcat. I don't want to use any IDE. In Tomcat I have the following directory structure inside webapps\

我正在尝试使用 JAX-RS 创建和部署 RESTful Web 服务并将其部署到 tomcat。我不想使用任何 IDE。在 Tomcat 中,我在 webapps\ 中有以下目录结构

notifire\WEB-INF\
                 |
                 ---> web.xml
                 |
                 ---> \classes/Notifier.class
                 |
                 ---> \lib\javax.ws.rs-api-2.0

my web.xml contains:

我的 web.xml 包含:

<servlet>
<servlet-name>Web Service Servlet</servlet-name>
<servlet-class>javax.ws.rs.core.Application</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>Web Service Servlet</servlet-name>
<url-pattern>/webservice/*</url-pattern>
</servlet-mapping>

and the class file Notifier.classwas compiled from the file Notifier.java.

并且类文件Notifier.class是从文件编译而来的Notifier.java

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.UriInfo;

@Path("notifier")
public class Notifier {

    @Context
    private UriInfo context;

    @GET
    @Produces("text/html")
    public String getHTML() {

         return "<p></p>";
    }
}

When I try to access the Web Service at http://localhost:8080/notifire/webservice/notifierI get the following error:

当我尝试访问 Web 服务时http://localhost:8080/notifire/webservice/notifier,出现以下错误:

--type Exception report

--message Class javax.ws.rs.core.Application is not a Servlet

--description The server encountered an internal error that prevented it from fulfilling this request.

--type 异常报告

--message 类 javax.ws.rs.core.Application 不是 Servlet

--description 服务器遇到内部错误,无法完成此请求。

Any help is appreciated.

任何帮助表示赞赏。

采纳答案by bh5k

You have the wrong class for your Servlet. Not sure why you are not wanting to use an IDE, but there is a maven archetype that will layout your project structure for you using the appropriate classes that the Jersey developers have defined. My web.xml looks like this:

您的 Servlet 类错误。不确定为什么您不想使用 IDE,但是有一个 maven 原型可以使用 Jersey 开发人员定义的适当类为您布局项目结构。我的 web.xml 看起来像这样:

<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.pluralsight</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>Jersey Web Application</servlet-name>
    <url-pattern>/webapi/*</url-pattern>
</servlet-mapping>

I cover all of this in this course here.

我涵盖所有的这本课程在这里

回答by Alvin Thompson

I had trouble getting this to work as well. Since you have to use web.xmlanyway, the simplest way to get restful web services working is to forget extending javax.ws.rs.core.Applicationentirely and just specify the context path there. You can still use standard jax-rs annotations to declare the actual web services.

我也很难让它正常工作。由于web.xml无论如何您都必须使用,因此让 Restful Web 服务工作的最简单方法是javax.ws.rs.core.Application完全忘记扩展并在那里指定上下文路径。您仍然可以使用标准的 jax-rs 注释来声明实际的 Web 服务。

web.xml:

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

Two noteworthy points:

值得注意的两点:

  1. 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-classelement above. You can replace this with Apache CXF implementation if you want.

  2. The init-paramelement 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-paramelements will be different. Someone who knows CXF please post what they would be.

  1. 您需要在 WAR 文件中捆绑 REST 实现,因为 servlet 容器通常不包含一个。由于 Jersey 是 JAX-RS 的参考实现,因此我在servlet-class上面的元素中使用了它。如果需要,您可以将其替换为 Apache CXF 实现。

  2. init-param元素告诉 Jersey 使用 Web 服务注释搜索您的哪些包来搜索 Java 文件。编辑它以指向您的 Web 服务。请注意,如果您选择使用 apache CXF 而不是 Jersey,则任何init-param元素中所需的内容都会有所不同。知道CXF的人请发布他们会是什么。

If you're using Maven, just add a dependency to jersey-servletin the dependenciessection of your pom.xmlfile:

如果您使用 Maven,只需jersey-servletdependencies您的pom.xml文件部分添加一个依赖项:

<dependencies>
  <dependency>
    <groupId>com.sun.jersey</groupId>
    <artifactId>jersey-servlet</artifactId>
    <version>1.18.2</version>
  </dependency>
  ...
</dependencies>

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

在此之后,使用 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);
  }
}

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

这应该就是你所需要的。如果您的 Tomcat 安装在端口 8080 上本地运行,并且您将 WAR 文件部署到上下文myContext,则转到

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

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

...应该产生预期的结果 (5)。

Cheers!

干杯!

* 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?

* 如果您知道一种将 Jersey servlet 添加到 Tomcat 中的上下文而不使用web.xml--maybe 使用上下文或生命周期侦听器的方法,请纠正我?