使用 Eclipse 和 Payara 服务器的 Jersey REST 应用程序未找到 HTTP 状态 404

HTTP Status 404 Not Found For Jersey REST application with Eclipse and Payara server

我正在尝试使用 Payara 服务器在 Eclipse 中为预订系统开发 Jersey 服务器应用程序。当我 运行 项目时,我得到 "HTTP Status 404 - Not Found"。我检查了几个教程和 Whosebug 帖子,但找不到错误。有人可以帮我吗?

预订服务接口:

public interface BookingService {

    public Response addBooking(Room room);

    public Response cancelBooking(Room room);

    public Room getRoom(int roomNumber);

    public Room[] getAllAvailableRooms();
}

预订服务实施:

@Path("/booking")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class BookingServiceImpl implements BookingService{

private static Map<Integer,Room> rooms = new HashMap<Integer,Room>();

@POST
@Path("/add")
public Response addBooking(Room room) {
    Response response = new Response();

    if(rooms.get(room.getNumber()).isBooked()) {
        response.setMessage("This room is not available");
        return response;
    }
    room.bookRoom();
    response.setMessage("Room successfully booked");

    return response;
}

@GET
@Path("/delete")
public Response cancelBooking(Room room) {
    Response response = new Response();
    if(!rooms.get(room.getNumber()).isBooked()) {
        response.setMessage("This room is not booked so booking cannot be cancelled");
        return response;
    }

    room.cancelBooking();
    response.setMessage("The booking for room " + room.getNumber() + "has been successfully cancelled");
    return null;
}

@GET
@Path("/getAll")
public Room[] getAllAvailableRooms() {
    Set<Integer> keys = rooms.keySet();
    Room[] roomArray = new Room[keys.size()];
    int i=0;
    for(Integer key : keys){
        if (!rooms.get(key).isBooked()) {
            roomArray[i] = rooms.get(key);
            i++;
        }
    }
    return roomArray;
}

pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>se.kth.id1212</groupId>
<artifactId>ID1212BookingSystem</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>ID1212BookingSystem Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>3.8.1</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.core</groupId>
        <artifactId>jersey-server</artifactId>
        <version>2.20</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.containers</groupId>
        <artifactId>jersey-container-servlet</artifactId>
        <version>2.20</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-json-jackson</artifactId>
        <version>2.13</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.core</groupId>
        <artifactId>jersey-common</artifactId>
        <version>2.22.2</version>
        <scope>test</scope>
    </dependency>
</dependencies>
<build>
    <finalName>ID1212BookingSystem</finalName>
    <plugins>
        <plugin>
            <artifactId>maven-war-plugin</artifactId>
            <version>2.6</version>
            <configuration>
                <warSourceDirectory>WebContent</warSourceDirectory>
                <failOnMissingWebXml>false</failOnMissingWebXml>
            </configuration>
        </plugin>
        <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.3</version>
            <configuration>
                <source>1.7</source>
                <target>1.7</target>
            </configuration>
        </plugin>
    </plugins>
</build>

编辑:当我研究这个问题时,我读到 web.xml 文件在使用 jersey 2 时除了显示名称外不必指定任何其他内容。我不知道这是不是真的,但下面是web.xml 我在阅读之前使用的文件,但它也不起作用。

<web-app>
    <display-name>Archetype Created Web Application</display-name>
    <!-- Jersey Servlet configurations -->
    <servlet>
        <servlet-name>Jersey REST Service</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>javax.ws.rs.Application</param-name>
            <param-value>se.kth.id1212.ID1212BookingSystem</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Jersey REST Service</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
    <!-- Jersey Servlet configurations -->
</web-app>

编辑2,添加了以下图片:

甚至,您最新的 web.xml 有问题,您需要慢慢来,将每个更改与教程进行比较。按照提到的教程

您的 web.xml

中应该有以下 init-param
<init-param>
    <param-name>jersey.config.server.provider.packages</param-name>
    <param-value>se.kth.id1212.ID1212BookingSystem</param-value>
</init-param>

但是,你写的是

<init-param>
    <param-name>javax.ws.rs.Application</param-name>
    <param-value>se.kth.id1212.ID1212BookingSystem</param-value>
</init-param>

此外,仅作为旁注,/add 期望 POST,这意味着它将在其正文中期望请求数据。我建议使用一些 REST 客户端,可能是 POSTMAN 用于您的测试。

==更新==

我真的不明白,你为什么在你的web.xml中使用下面的包名????

<param-value>se.kth.id1212.ID1212BookingSystem</param-value>

我确定,在某处,你没有失误BookingServiceImpl的包应该是server.service而不是se.kth.id1212.ID1212BookingSystem。因此,在 param-value 中,您应该提供相同的软件包名称,而不是随机名称。。所以,应该是

 <param-value>server.service</param-value>

此外,我明白了,您在 class 上使用了 Produces/Consumes 注释,而应该在每个方法上使用

 @Produces(MediaType.APPLICATION_JSON)
 @Consumes(MediaType.APPLICATION_JSON)
 public class BookingServiceImpl implements BookingService{

这是我的拙见,请不要将您的知识与可用的教程混为一谈。首先尝试通过 EXACTLY 遵循任何可用的教程(可能只是 copy/paste)来理解实现。选择最简单的教程可能只是打印 Hello World

您的应用程序似乎没有定义侦听根 URL 的 REST 端点。如果您的应用程序 运行 在 URL 上,例如 http://localhost/myapp,那么获得 URL 的 HTTP 404 响应是完全正常的。您只能从绑定到某些 REST 方法的 URL 中获得有效响应。

因为 BookingServiceImpl 绑定到“/booking”,并且它的所有方法都绑定到“/add”或“/getAll”等子路径,您可以通过组合

来访问 REST 方法
  • 应用程序上下文根,例如"myapp"(我不知道)
  • JAX-RS应用根路径,即web.xml中定义的“/*”,表示为空
  • BookingServiceImpl路径,即“/booking”
  • BookingServiceImpl 方法的路径,例如 getAllAvailableRooms
  • 的“/getAll”

所以要调用 getAllAvailableRooms 方法,您应该使用像 http://localhost/myapp/booking/getAll 这样的 URL 而不仅仅是 http://localhost/myapp.

在最近的 Payara Server 版本中,当您转到应用程序详细信息并单击 "Modules and Components" 中的 "View endpoints" 时,您应该能够在 Web 管理控制台中看到所有可用的 URL =] table在最下面,截图见文末

补充说明:

我建议在单独的 class 中定义 JAX-RS 应用程序,该应用程序扩展 javax.ws.rs.Application 并接受带有 servlet 映射的 @ApplicationPath 注释。那么你的 web.xml 中就不需要任何东西了,你甚至可以删除它。这是等同于您的 web.xml 的 Java 代码(是的,就这么简单,所有其他代码都是可选的):

@ApplicationPath("/")  // maps the servlet to "/*"
public class MyRESTApplication extends Application {
}

我还建议观看 short video 关于在 Netbeans 中使用 Payara 创建 REST 服务的内容(它在 Eclipse 中应该非常相似,IDE 没有太大关系)。您可以跳过介绍并从 3:30.

开始

Payara 管理控制台中的 REST 端点详细信息