如何在java se running grizzly上启用CDI注入Web服务(jaxrs/jersey)?

2022-09-04 19:20:23

如何允许 CDI 将资源注入到宁静的 Web 服务资源中?我在标准Java上运行,使用weld 2(cdi),jersey(jaxrs)和grizzly(Web服务器)。这是我的简单网络资源:

import training.student.StudentRepository;
import javax.inject.Inject;
import javax.ws.rs.*;

@Path("student")
public class StudentWebResource {
  @Inject
  private StudentRepository studentRepository;  

  @GET
  @Path("count")
  @Produces(MediaType.TEXT_PLAIN)
  public Integer getCount() {
    return studentRepository.studentCount();
  }
}

以下是我如何让焊接启动我的简单Web服务器:

public class Main {
  public static void main(String[] args) throws Exception {
    startCdiApplication();
  }

  public static void startCdiApplication() throws Exception {
    Weld weld = new Weld();
    try {
      WeldContainer container = weld.initialize();
      Application application = container.instance().select(WebServer.class).get();
      application.run();
    } 
    finally {
      weld.shutdown();
    }
  }
}

我怀疑需要修改的代码,以通知球衣使用焊接进行CDI注入分辨率:

...
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.jackson.JacksonFeature;
import org.glassfish.jersey.server.ResourceConfig;

public class WebServer implements Application {

  /*
   * startup the grizzly http server to make available the restful web services
   */
  private void startWebServer() throws IOException, InterruptedException {
    final ResourceConfig resourceConfig = new ResourceConfig().packages("training.webservice").register(new JacksonFeature());
    final HttpServer server = GrizzlyHttpServerFactory.createHttpServer(getBaseUri(), resourceConfig);
    server.start();
    Thread.currentThread().join();
  }

  ...

  @Override
  public void run() throws IOException, InterruptedException {
    startWebServer();
  }
}

答案 1

在看到这个堆栈溢出帖子后,我实现了以下解决方案。不确定这是否是最好的路线,但它有效。

我创建了一个 hk2 活页夹并注册了该活页夹:

public class WebServiceBinder extends AbstractBinder {

  @Override
  protected void configure() {
    BeanManager bm = getBeanManager();
    bind(getBean(bm, StudentRepository.class))
        .to(StudentRepository.class);
  }

  private BeanManager getBeanManager() {
    // is there a better way to get the bean manager?
    return new Weld().getBeanManager();
  }

  private <T> T getBean(BeanManager bm, Class<T> clazz) {
    Bean<T> bean = (Bean<T>) bm.getBeans(clazz).iterator().next();
    CreationalContext<T> ctx = bm.createCreationalContext(bean);
    return (T) bm.getReference(bean, clazz, ctx); 
  }
}

然后,将上面的 ResourceConfig 实例化修改为:

final ResourceConfig resourceConfig = new ResourceConfig()
    .packages("training.webservice")
    .register(new JacksonFeature())
    .register(new WebServiceBinder());

答案 2

所选答案可追溯到不久前。在自定义 HK2 活页夹中声明每个装订是不切实际的。我只需要添加一个依赖项。尽管它是为玻璃鱼设计的,但它可以完美地放入其他容器中。我正在使用雄猫/灰熊。

   <dependency>
        <groupId>org.glassfish.jersey.containers.glassfish</groupId>
        <artifactId>jersey-gf-cdi</artifactId>
        <version>2.14</version>
    </dependency>

下面是 JerseyTest 的一个示例(如果您从 main 方法运行它,则原理相同)。我只需要在实例化我的资源之前声明对 weld-se 的依赖性并声明一个 Weld 容器 - 就像你也做了的那样 - 它开箱即用。

public class GrizzlyTest extends JerseyTest {
    private Weld weld;
    private WeldContainer container;

    @Override
    protected Application configure() {
        weld = new Weld();
        container = weld.initialize();
        return new ResourceConfig(MyResource.class);
    }

    @Test
    public void test() {
        System.out.println(target("myresource").request().get(String.class));
    }

    @After
    public void after() {
        weld.shutdown();
    }
}

推荐