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

时间:2013-12-28 11:02:17

标签: java rest java-ee jboss jax-rs

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

的web.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

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!";
    }
}

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

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

使用: JBoss EAP 6.1.0(Java EE 6)

4 个答案:

答案 0 :(得分:3)

您需要扩展javax.ws.rs.core.Application(它可以保持为空)并使用@ApplicationPath(“/ ide”)对其进行注释,然后创建一个JAX-RS资源,即带有@的类路径(“/ 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!";
  }
}

您还可以查看此示例:https://github.com/resteasy/Resteasy/tree/master/jaxrs/examples/oreilly-workbook/ex03_1

答案 1 :(得分:3)

的web.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

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

如果需要,可以添加

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;
    }
}

然后

的web.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>

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

答案 2 :(得分:0)

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

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

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

答案 3 :(得分:0)

我也有问题让这个工作,所以我发布了一个更完整的后代方法:

如果您正在使用标准的Tomcat安装(或其他一些servlet容器),AFAIK就无法明确告诉它在web.xml文件*中启动哪些servlet。因为无论如何必须使用web.xml,让最安静的Web服务工作的最简单方法是忘记完全扩展javax.ws.rs.core.Application并在那里指定上下文路径。您仍然可以使用标准的jax-rs注释来声明实际的Web服务。

的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>

两个值得注意的要点:

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

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

  3. 如果您正在使用Maven,只需在jersey-servlet文件的dependencies部分中向pom.xml添加依赖关系:

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

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

    干杯!

    *如果您知道如何在不使用web.xml的情况下将Jersey servlet添加到Tomcat中的上下文中,有人可以解释一下 - 可能是通过使用上下文或生命周期监听器?