Java 为什么这个简单的 JAX RS 示例不起作用?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20813767/
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 04:33:04  来源:igfitidea点击:

Why is this Simple JAX RS example not working?

javarestjakarta-eejbossjax-rs

提问by Fagner Brack

I am trying to get working a simple JAX RS example, but I am failing to do so.

我正在尝试使用一个简单的 JAX RS 示例,但我没有这样做。

web.xml

网页.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:jsp="http://java.sun.com/xml/ns/javaee/jsp" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>PLAYGROUND</display-name>
  <servlet-mapping>
    <servlet-name>playground.Rest</servlet-name>
    <url-pattern>/api/*</url-pattern>
  </servlet-mapping>
</web-app>

Rest.java

REST.java

package playground;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Application;

public class Rest extends Application {
    @GET
    @Path("hello")
    public String helloworld() {
        return "Hello World!";
    }
}

Accessing http://localhost/{warcontext}/api/hellowith the browser (GET) gives me 404 error status

http://localhost/{warcontext}/api/hello使用浏览器 (GET)访问给我 404 错误状态

It is probably something very silly but I can't figure out.

这可能是非常愚蠢的事情,但我无法弄清楚。

Using: JBoss EAP 6.1.0 (Java EE 6)

使用:JBoss EAP 6.1.0 (Java EE 6)

采纳答案by Xavier Coulon

You need to extend javax.ws.rs.core.Application (it can remain empty) and annotate it with @ApplicationPath("/ide"), then create a JAX-RS resource, ie, a class with an @Path("/hello") annotation. In this class, you'll just need to have your JAX-RS Resource Method annotated with @GET.

您需要扩展javax.ws.rs.core.Application(它可以保持为空)并使用@ApplicationPath("/ide") 对其进行注释,然后创建一个JAX-RS 资源,即一个带有@Path(" /hello") 注释。在本课程中,您只需要使用 @GET 注释您的 JAX-RS 资源方法。

@ApplicationPath("/ide")
public class Rest extends Application { }


@Path("/hello")
public class HelloResource {

  @GET
  @Path("hello")
  public String helloworld() {
      return "Hello World!";
  }
}

You can also take a look at this example: https://github.com/resteasy/Resteasy/tree/master/jaxrs/examples/oreilly-workbook/ex03_1

你也可以看看这个例子:https: //github.com/resteasy/Resteasy/tree/master/jaxrs/examples/oreilly-workbook/ex03_1

回答by Stephane Lallemagne

You need to declare servlet-class in web.xml(servlet name is not the same):

需要在web.xml中声明servlet-class (servlet名称不一样):

  <servlet>
    <servlet-name>Playground REST services</servlet-name>
    <servlet-class>your.package.playground.Rest</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>Playground REST services</servlet-name>
    <url-pattern>/api/*</url-pattern>
  </servlet-mapping>

Use the full name of your class (including package path name) in servlet-class.

在 servlet-class 中使用您的类的全名(包括包路径名)。

回答by Qwertovsky

web.xml

网页.xml

<servlet>
    <servlet-name>RestServlet</servlet-name>
    <servlet-class>javax.ws.rs.core.Application</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>RestServlet</servlet-name>
    <url-pattern>/api/*</url-pattern>
</servlet-mapping>

Rest.java

REST.java

public class Rest {
    @GET
    @Path("hello")
    public String helloworld() {
        return "Hello World!";
    }
}


If you need, you can add

如果需要,您可以添加

YourApplication.java

你的应用程序

package playground;
import javax.ws.rs.core.Application;
...
public class YourApplication extends Application {
    @Override
    public Set<Class<?>> getClasses()
    {
        Set<Class<?>> yourResources = new HashSet<Class<?>>();
        yourResources.add(InvoiceResource.class);
        return yourResources;
    }
}

Then

然后

web.xml

网页.xml

<servlet>
    <servlet-name>RestServlet</servlet-name>
    <servlet-class>playground.YourApplication</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>RestServlet</servlet-name>
    <url-pattern>/api/*</url-pattern>
</servlet-mapping>

If you add @ApplicationPath("/api")for YouApplication, then web.xml shouldn't have servlet-mapping.

如果添加@ApplicationPath("/api")for YouApplication,则 web.xml 不应包含servlet-mapping

回答by Alvin Thompson

I also had issues getting this to work, so I'm posting a more complete how-to for posterity:

我也遇到了让它工作的问题,所以我为后代发布了一个更完整的操作方法:

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

如果您使用标准的 Tomcat 安装(或其他一些 servlet 容器),AFAIK 您无法避免明确告诉它在web.xml文件中启动哪些 servlet *。由于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 使用上下文或生命周期侦听器的方法,请纠正我?