运行Jersey Rest API而不使用容器作为jar

时间:2015-07-30 14:57:05

标签: java rest jersey

目前,我正在使用Tomcat将我的后端与我的Rest API保持一致。当我想使用我的前端时,我只是启动Tomcat,它拥有Backend-Project然后,我可以使用http-requests访问Rest-API的后端。 现在我考虑摆脱Tomcat并将其部署为jar文件,而不是war文件,并通过Main方法在本地运行它。 我这样做了(Source):

public class Main {

    public static void main(String[] args) throws Exception {

        ResourceConfig config = new DefaultResourceConfig(RestApi.class);

        HttpServer server = HttpServerFactory.create("http://localhost:8080/", config);

        server.start(); 
   }

我的Rest-Class的摘录将是:

@Path("/schemas")
public class RestApi {

    @GET
    @Path("/hi")
    public String dropHi() {
        return "hi;
    }
}

运行此主程序,但由于某种原因仍然无法访问Rest-Api。当我试图通过尝试在浏览器中访问http://localhost:8080/api/schemas/hi来获得“hi”时,没有任何反应。可能有什么不对,它甚至会让我想要做什么? 我的想法是稍后在服务器上运行后端,而不使用Tomcat,只需将其作为jar文件运行,然后通过您在系统本地运行的前端访问它。

2 个答案:

答案 0 :(得分:2)

你想要做的事情是有道理的。您需要独立服务器,并且没有任何问题。

我做了类似的事情,但是使用了Jetty服务器和RESTEasy REST实现。虽然我不确定一切都会为您开箱即用(很可能不是)但它应该仍然非常相似,因为Jersey REST和RESTEasy都是根据相同的规格构建的:https://jcp.org/en/jsr/detail?id=311

无论如何,这对我有用:

//Obviously main method from which you start the server

public static void main(String[] consoleArgs) {
    final Server server= new Server(port);
    final HandlerList handlers= new HandlerList();
    addServlets(handlers);
    server.setHandler(handlers);
    server.start();
}

private static void addServlets(HandlerList handlers) {
    final ServletContextHandler servletContextHandler= new ServletContextHandler(ServletContextHandler.SESSIONS);
    servletContextHandler.setContextPath("/");
    handlers.addHandler(servletContextHandler);

    //handlers and servlets that I ommit...

    addRestServiceContainer(servletContextHandler);
}

// and here is the trick... 
// the settings you see here would normally go to web.xml file

private static void addRestServiceContainer(final ServletContextHandler servletContextHandler) {
    ServletHolder holder= new ServletHolder(new HttpServlet30Dispatcher());
    holder.setInitParameter("javax.ws.rs.Application", "com.stackoverflow.rest.application.RestfulServiceContainer");
    holder.setInitParameter("resteasy.servlet.mapping.prefix", "/rest");
    holder.setInitParameter("resteasy.providers", "org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider");
    servletContextHandler.addServlet(holder, RestResourcePaths.REST_SERVICES_BASE_PATH + "/*");
}

作为最后一篇,com.stackoverflow.rest.application.RestfulServiceContainer看起来是这样的:

public class RestfulServiceContainer extends Application {

    private static final Set<Class<?>> fSingletons= new HashSet<Class<?>>();
    private static final Set<Object> fRestfulServices= new HashSet<Object>();

public RestfulServiceContainer() {
    registerServices();
    initProviders();
}

/**
 * Normally, when resteasy.scan is set to true all provider classes (with @Provider) are registered automatically,
 * but since this is a standalone Jetty app it doesn't work. So, we register provider classes here manually.
 */
private void initProviders() {
    fSingletons.add(TrafficInterceptor.class);
    fSingletons.add(LogInterceptor.class);
    fSingletons.add(RateLimitInterceptor.class);
    fSingletons.add(SecurityInterceptor.class);
    fSingletons.add(ExceptionHandler.class);
}

private void registerServices() {
    fRestfulServices.add(new GetWhateverService());
    fRestfulServices.add(new PostStuffService());
}

@Override
public Set<Class<?>> getClasses() {
    return fSingletons;
}

@Override
public Set<Object> getSingletons() {
    return fRestfulServices;
}

}

答案 1 :(得分:1)

我做到了。有两个问题:

  1. 在我的web.xml中有<url-pattern>/api/*</url-pattern>,它已不再使用,因此链接不是http://localhost:8080/api/schemas/hi,而是http://localhost:8080/schemas/hi

  2. 在我的web.xml中,我得到了条目:

    <filter>
        <filter-name>CORS</filter-name>
        <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
        <init-param>
            <param-name>cors.supportedMethods</param-name>
            <param-value>GET, POST, HEAD, PUT, DELETE</param-value>
        </init-param>
    </filter>
    

    不再使用容器,我必须以另一种方式启用CORS。最后,我在this的帮助下做到了这一点:

    public class CORSFilter implements ContainerResponseFilter {
    
        public ContainerResponse filter(ContainerRequest req, ContainerResponse containerResponse) {
    
            ResponseBuilder responseBuilder = Response.fromResponse(containerResponse.getResponse());
    
            // *(allow from all servers) OR http://example.com/
            responseBuilder.header("Access-Control-Allow-Origin", "*")
    
            // As a part of the response to a request, which HTTP methods can be used during the actual request.
            .header("Access-Control-Allow-Methods", "API, CRUNCHIFYGET, GET, POST, PUT, UPDATE, OPTIONS")
    
            // How long the results of a request can be cached in a result    cache.
            .header("Access-Control-Max-Age", "151200")
    
            // As part of the response to a request, which HTTP headers can be used during the actual request.
            .header("Access-Control-Allow-Headers", "x-requested-with,Content-Type");
    
            String requestHeader = req.getHeaderValue("Access-Control-Request-Headers");
    
            if (null != requestHeader && !requestHeader.equals(null)) {
                responseBuilder.header("Access-Control-Allow-Headers", requestHeader);
            }
    
            containerResponse.setResponse(responseBuilder.build());
            return containerResponse;
        }
    }
    

    并在Main方法中设置:

    config.getContainerResponseFilters().add(CORSFilter.class);