使业务域对象可用于嵌入式 Jetty 服务器中的 Jersey Servlet 上下文

Making business domain objects available to Jersey Servlet Context in embedded Jetty server

使用以下依赖项 (Gradle):

我有一个嵌入式 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

交付生成的模型,JacksonJsonProvider,以及 RestApi class:

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 class,或者说 RestApiServiceImpl?

我从过去 24 小时的阅读中了解到,我需要通过 Jetty、Jersey 或其他一些库(Weld 似乎经常出现)使用某种上下文依赖注入,并尝试了各种组合@Inject@Context 等,但得出的结论是我不知道我实际上在做什么......我什至不确定我是否对这种情况有足够的了解来表达我的意思问题正确。

可应要求提供更多信息。

感谢任何帮助。

编辑:在此处添加 link 到 https://github.com/englishbobster/JersetAndJetty

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

要使 DI 正常工作,首先需要 AbstractBinder。在这里您可以让您的对象可以被注入。

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

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

如果您想更改配置以使用我个人更愿意使用的 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");

现在您可以摆脱其他两个初始参数,因为您正在 ResourceConfig.

中配置它

另一种没有任何初始化参数的方法是

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

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

现在您几乎可以在 Jersey

的任何地方注入 ModelAdapter

在字段中

@Inject
private ModelAdapter adapter;

或者在构造函数中

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

或方法参数

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