如何在运行grizzly的java se上启用web服务(jaxrs / jersey)中的CDI注入?

如何允许CDI将资源注入到宁静的Web服务资源中? 我使用焊接2(cdi),泽西(jaxrs)和灰熊(web服务器)在标准java上运行。 这是我简单的网络资源:

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(); } } } 

我怀疑需要修改代码以告知jersey使用焊接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(); } } 

看到这个stackoverflowpost后 ,我实现了以下解决方案。 不确定它是否是最好的路线,但它有效。

我创建了一个hk2 Binder并注册了Binder:

 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 getBean(BeanManager bm, Class clazz) { Bean bean = (Bean) bm.getBeans(clazz).iterator().next(); CreationalContext 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()); 

选定的答案可以追溯到前一段时间。 在自定义HK2活页夹中声明每个绑定是不切实际的。 我只需要添加一个依赖项。 尽管它是专为Glassfish设计的,但它完全适合其他容器。 我正在使用Tomcat / Grizzly。

   org.glassfish.jersey.containers.glassfish jersey-gf-cdi 2.14  

以下是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(); } } 

至少Weld 2.2.0.Final没有必要搞乱HK2 Binder。

正如Weld官方文档所述,您只需要注册org.jboss.weld.environment.servlet.Listener 。 从doc剪切的代码:

 public class Main { public static void main(String[] args) throws ServletException, LifecycleException { Tomcat tomcat = new Tomcat(); Context ctx = tomcat.addContext("/", new File("src/main/resources").getAbsolutePath()); Tomcat.addServlet(ctx, "hello", HelloWorldServlet.class.getName()); ctx.addServletMapping("/*", "hello"); ctx.addApplicationListener(Listener.class.getName()); tomcat.start(); tomcat.getServer().await(); } public static class HelloWorldServlet extends HttpServlet { @Inject private BeanManager manager; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/plain"); resp.getWriter().append("Hello from " + manager); } } } 

上面的servlet监听器管理Weld容器的整个生命周期 。 所以没有必要:

  Weld weld = new Weld(); WeldContainer container = weld.initialize(); 

更新正如@EdMelo所指出的,Grizzly HTTP服务器不是完全兼容的Servlet容器。 我不知道这个,谢谢你的提示。 所以我不确定,如果我的答案仍适用于此。