Как вставить Jetty и Jersey в мое приложение Java

Итак, я пытаюсь встроить jetty в свое веб-приложение, чтобы, если я упакую его как банку, кто-то может просто запустить файл jar, не беспокоясь о настройке сервера. Однако у меня возникают проблемы с настройкой моего основного класса, чтобы причал мог получить доступ к моим классам ресурсов. Я посмотрел учебники, но они не дали мне именно то, что я ищу. Это то, что у меня есть до сих пор.

package pojo;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;

public class Main {

    public static void main(String[] args) throws Exception {
        Server server = new Server(8080);
        ServletContextHandler context = new ServletContextHandler(ServletContextHandler.NO_SESSIONS);
        context.setContextPath("/");
        ServletHolder h = new ServletHolder(new DefaultServlet());
        h.setInitParameter("javax.ws.rs.Application","resources.DBCollection");
        context.addServlet(h, "/*");
        server.setHandler(context);
        server.start();
        server.join();
    }
}

И я пытаюсь сопоставить его с этим классом:

package resources;


import java.util.ArrayList;
import java.util.List;

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

import pojo.Party;

@Path("/parties")
public class DBCollection {

    @Context
    UriInfo url;

    @Context
    Request request;

    String name;

    @GET
    @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
    public List<Party> getAllParties() throws Exception
    {
        List<Party> list = new ArrayList<Party>();
        list.addAll(DBConnection.getPartyCollection().values());
        return list;
    }

    @GET
    @Path("count")
    @Produces(MediaType.TEXT_PLAIN)
    public String getPartyCount() throws Exception
    {
        return String.valueOf(DBConnection.getPartyCollection().size());
    }

    @Path("{party}")
    public DBResource getParty(@PathParam("party")String party)
    {
        return new DBResource(url,request,party);
    }
}

Здесь мой файл POM:

<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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>PartyAPI</groupId>
    <artifactId>PartyAPIMaven</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
        <dependency>
            <groupId>com.codahale.metrics</groupId>
            <artifactId>metrics-core</artifactId>
            <version>3.0.1</version>
        </dependency>
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-server</artifactId>
            <version>1.17.1</version>
        </dependency>

        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-server</artifactId>
            <version>9.0.0.RC0</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-servlet</artifactId>
            <version>9.0.0.RC0</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-servlets</artifactId>
            <version>9.0.0.RC0</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.eclipse.persistence</groupId>
            <artifactId>eclipselink</artifactId>
            <version>2.6.0-SNAPSHOT</version>
        </dependency>

    </dependencies>
    <repositories>
        <repository>
            <id>oss.sonatype.org</id>
            <name>OSS Sonatype Staging</name>
            <url>https://oss.sonatype.org/content/groups/staging</url>
        </repository>
    </repositories>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>1.6</version>
                <configuration>
                    <createDependencyReducedPom>true</createDependencyReducedPom>
                    <filters>
                        <filter>
                            <artifact>*:*</artifact>
                            <excludes>
                                <exclude>META-INF/*.SF</exclude>
                                <exclude>META-INF/*.DSA</exclude>
                                <exclude>META-INF/*.RSA</exclude>
                            </excludes>
                        </filter>
                    </filters>
                </configuration>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer
                                    implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
                                <transformer
                                    implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <manifestEntries>
                                        <Main-Class>com.resteasy.Star.Main</Main-Class>

                                    </manifestEntries>

                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

Ответ 1

Несколько вещей.

  • Jetty 9.0.0.RC0 является старым, но еще не стабильным кандидатом на выпуск, рассмотрим возможность перехода на стабильную окончательную версию, например 9.0.4.v20130625
  • Вам нужно что-то, что соединит этот класс Jax RS в сервлет api. Обычно делается через сервлет или какую-то инициализацию с выбранной вами библиотекой. (В вашем случае Джерси).

В вашем примере вы только установили DefaultServlet для обслуживания статических файлов, ничего не было настроено для использования вашего объекта DBCollection.

Для Джерси вам нужно настроить org.glassfish.jersey.servlet.ServletContainer и настроить его сервлет-сопоставления в контексте вашего выбора.

Пример:

package com.example;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;

public class Main
{
    public static void main(String[] args)
    {
        Server server = new Server(8080);

        ServletContextHandler context = new ServletContextHandler(ServletContextHandler.NO_SESSIONS);
        context.setContextPath("/");
        server.setHandler(context);

        ServletHolder jerseyServlet = context.addServlet(org.glassfish.jersey.servlet.ServletContainer.class, "/webapi/*");
        jerseyServlet.setInitOrder(1);
        jerseyServlet.setInitParameter("jersey.config.server.provider.packages","com.example");

        ServletHolder staticServlet = context.addServlet(DefaultServlet.class,"/*");
        staticServlet.setInitParameter("resourceBase","src/main/webapp");
        staticServlet.setInitParameter("pathInfoOnly","true");

        try
        {
            server.start();
            server.join();
        }
        catch (Throwable t)
        {
            t.printStackTrace(System.err);
        }
    }
}

В этом примере добавлен ServletContainer, который предоставляет трикотаж ServletContextHandler, который Jetty использует для поиска того, что делать на основе входящего запроса. Затем он добавляет DefaultServlet для обработки любых запросов на контент, которые Джерси не обрабатывает (например, статический контент).

Ответ 2

Если вы хотите полностью управлять жизненным циклом вашего ресурса DBCollection программным способом (например, вы сами создаете его, выполняете некоторые настройки/инициализацию и т.д.), вместо того, чтобы создать для вас экземпляр для Джерси, вы можете использовать ResourceConfig вроде:

ServletContextHandler sch = new ServletContextHandler();
sch.setContextPath("/xxx");

TheResource resource = new TheResource();
ResourceConfig rc = new ResourceConfig();
rc.register(resource);

ServletContainer sc = new ServletContainer(rc);
ServletHolder holder = new ServletHolder(sc);
sch.addServlet(holder, "/*");

Server server = new Server(port);
server.setHandler(sch);
server.start();
server.join();

Обратите внимание на строку TheResource resource = new TheResource();. Здесь мы создаем собственный экземпляр TheResource, и теперь мы можем манипулировать им по своему усмотрению.