如何在运行 grizzly 的 java se 上启用 Web 服务(jaxrs/jersey)中的 CDI 注入?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17224270/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to enable CDI inject in web service (jaxrs/jersey) on java se running grizzly?
提问by Brice Roncace
How do I allow CDI injection of resources into restful web service resources? I am running on standard java using weld 2 (cdi), jersey (jaxrs), and grizzly (web server). Here is my simple web resource:
如何允许 CDI 将资源注入 Restful Web 服务资源?我使用weld 2 (cdi)、jersey (jaxrs) 和grizzly (web server) 在标准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();
}
}
And here is how I've got weld starting my simple web server:
这是我如何开始我的简单网络服务器的焊接:
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();
}
}
}
And the code that I suspect will need to be modified to inform jersey to use weld for CDI inject resolution:
我怀疑需要修改代码以通知球衣使用焊接进行 CDI 注入解析:
...
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.Hymanson.HymansonFeature;
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 HymansonFeature());
final HttpServer server = GrizzlyHttpServerFactory.createHttpServer(getBaseUri(), resourceConfig);
server.start();
Thread.currentThread().join();
}
...
@Override
public void run() throws IOException, InterruptedException {
startWebServer();
}
}
回答by Brice Roncace
After seeing this stackoverflow post, I implemented the following solution. Not sure if it is the best route to take, but it worked.
看到这个stackoverflow帖子后,我实施了以下解决方案。不确定这是否是最佳路线,但它奏效了。
I created an hk2 Binder and registered the Binder:
我创建了一个 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> 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);
}
}
Then modified the ResourceConfig instantiation from above to:
然后将上面的 ResourceConfig 实例化修改为:
final ResourceConfig resourceConfig = new ResourceConfig()
.packages("training.webservice")
.register(new HymansonFeature())
.register(new WebServiceBinder());
回答by otonglet
The selected answer dates from a while back. It is not practical to declare every binding in a custom HK2 binder. I just had to add one dependency. Even though it was designed for Glassfish it fits perfectly into other containers. I'm using Tomcat / Grizzly.
选定的答案可以追溯到很久以前。在自定义 HK2 绑定器中声明每个绑定是不切实际的。我只需要添加一个依赖项。尽管它是为 Glassfish 设计的,但它也非常适合其他容器。我正在使用 Tomcat/Grizzly。
<dependency>
<groupId>org.glassfish.jersey.containers.glassfish</groupId>
<artifactId>jersey-gf-cdi</artifactId>
<version>2.14</version>
</dependency>
Here is an example with JerseyTest (same principle if you run it from a main method). I just had to declare a dependency on weld-se and declare a Weld container before instantiating my resources - as you also did - and it works out of the box.
这是 JerseyTest 的示例(如果从主方法运行它,则原理相同)。在实例化我的资源之前,我只需要声明对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();
}
}
回答by G. Demecki
Since at least Weld 2.2.0.Final there is no need to mess up with HK2 Binder.
由于至少 Weld 2.2.0.Final 没有必要弄乱 HK2 Binder。
As official Weld documentationstates you just need to register org.jboss.weld.environment.servlet.Listener
. Code snipped from doc:
正如官方 Weld文档所述,您只需要注册org.jboss.weld.environment.servlet.Listener
. 从文档中截取的代码:
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);
}
}
}
Above servlet listener manages the whole lifecycleof the Weld container. So there is no need to:
上面的 servlet 侦听器管理Weld 容器的整个生命周期。所以没有必要:
Weld weld = new Weld();
WeldContainer container = weld.initialize();
UPDATEAs @EdMelo pointed out, Grizzly HTTP server is not a fully compliant Servlet container. I didn't know this, thanks for this hint. So I'm not sure, if my answer still applies here.
更新正如@EdMelo 指出的,Grizzly HTTP 服务器不是一个完全兼容的 Servlet 容器。我不知道这个,谢谢你的提示。所以我不确定我的回答是否仍然适用于这里。