使嵌入式Jetty服务器中的Jersey Servlet Context可以使用业务域对象

时间:2016-05-18 14:04:17

标签: dependency-injection jersey jersey-2.0 embedded-jetty

使用以下依赖项(Gradle):

  • org.glassfish.jersey.containers:jersey-container-servlet:2.22.2

  • org.eclipse.jetty:jetty-servlet:9.3.2.v20150730

我有一个嵌入式Jetty服务器,带有一个Jersey servlet容器......就像这样......

package mypkg.rest.jersey;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.glassfish.jersey.server.ServerProperties;
import org.glassfish.jersey.servlet.ServletContainer;
import se.transmode.tnm.alarm.api.AlarmRetrieval;
import mypkg.rest.RestServer;
import mypkg.rest.jersey.serviceImpl.ModelAdapter;

public class JerseyBasedRestServer implements RestServer {

public static final int INITIALIZE_ON_USE = 0;
private Server server;
private final ServletContextHandler context;
private final ServletHolder servlet;
private final ModelAdapter modelAdapter;

public JerseyBasedRestServer(BusinessObjects businessObjects) {
    this.modelAdapter = new ModelAdapter(businessObjects);  //I want this instance to somehow be available for my ServletContainer to use.

    context = new ServletContextHandler(ServletContextHandler.SESSIONS);
    servlet = context.addServlet(ServletContainer.class, "/*");
    servlet.setInitOrder(INITIALIZE_ON_USE);
    servlet.setInitParameter(ServerProperties.PROVIDER_PACKAGES, "mypackage.jersey.generated.api.service");
    servlet.setInitParameter(ServerProperties.MEDIA_TYPE_MAPPINGS, "json : application/json");
    context.setContextPath("/");
}

private void startServlet() {
    try {
        servlet.start();
        servlet.initialize();
    } catch (Exception e) {
        log.error("Failed to initialize servlet. {}", e.getMessage());
    }
}

@Override
public void init(int port) {
    server = new Server(port);
    server.setHandler(context);
    try {
        server.start();
        server.join();
        startServlet();
    } catch (Exception e) {
        log.error("Failed to start jetty server for rest interface");
    } finally {
        server.destroy();
    }
}

Jersey容器将运行使用Swagger代码生成工具生成的服务器代码和模型

https://github.com/swagger-api/swagger-codegen#getting-started

提供生成的模型,JacksonJsonProviderRestApi类:

package mypackage.jersey.generated.api.service

Path("/")
public class RestApi  {
   private final RestApiService delegate = new RestApiServiceImpl(); //Integration point of the generated code

   @GET
   @Path("/list/")
   @Consumes({ "application/json" })
   @Produces({ "application/json" })
   public Response retrieveAlarmList(@Context SecurityContext securityContext) throws NotFoundException {
    return delegate.retrieveAlarmList(securityContext);
   }
}

为了整合生成的代码,我们将自己实现RestApiServiceImpl

ModelAdapter的工作是将业务对象转换为生成的休息模型。

所以问题是如何创建我们的业务对象的适配器实例,在这种情况下ModelAdapter,它位于Jersey servlet上下文的上下文之外,可用于RestApi类或者更确切地说是RestApiServiceImpl

我从阅读过去的24小时了解到,我需要通过Jetty,Jersey或其他一些库来使用某种Context Dependency Injection(Weld似乎看起来很多),并尝试了{的各种组合{1}},@Inject等等,但得出结论我不知道我在做什么......我甚至不确定我对这种情况有足够的了解问题正确。

可根据要求提供更多信息。

感谢任何帮助。

编辑:在https://github.com/englishbobster/JersetAndJetty

添加了一个链接

使用@peeskillets建议,但仍无效。

1 个答案:

答案 0 :(得分:2)

你需要让DI工作的第一件事是AbstractBinder。这是您可以注入对象的地方。

class Binder extends AbstractBinder {
    @Override
    protected void configure() {
       bind(modelAdapter).to(ModelAdapter.class);
    }
}

然后你需要在Jersey上注册活页夹。最简单的方法是在Jersey的ResourceConfig注册。在您的情况下,您没有使用它。您正在配置“web.xml”中的所有内容。为此,您应该查看this post

如果您想更改配置以使用{I}个人使用的ResourceConfig,您可以执行此操作

package com.some.pkg;

public class JerseyConfig extends ResourceConfig {
    public JerseyConfig() {
        packages("mypackage.jersey.generated.api.service");
        property(ServerProperties.MEDIA_TYPE_MAPPINGS, "json : application/json");
        register(new Binder());
    }
}

然后使用Jetty配置它,你可以

servlet.setInitParameter(ServletProperties.JAXRS_APPLICATION_CLASS, 
                         "com.some.pkg.JerseyConfig");

现在你可以摆脱其他两个init-params,因为你在ResourceConfig内配置它。

另一种没有任何init-params的方法就是

ResourceConfig config = new JerseyConfig();
ServletHolder jerseyServlet = new ServletHolder(ServletContainer(config));
context.addServlet(jerseyServlet, "/*");

查看最后一个代码段的完整示例here

现在你可以在泽西岛的任何地方注入ModelAdapter

在一个字段中

@Inject
private ModelAdapter adapter;

或者在构造函数中

@Inject
public RestApi(ModelAdapter adapter) {
    this.adapter = adapter;
}

或方法参数

@GET
public Response get(@Context ModelAdapter adapter) {}