英文:
Dependency injection into websocket endpoint on embedded jetty
问题
以下是翻译好的部分:
我有一个以下的WebSocket端点:
import javax.inject.Inject;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
@ServerEndpoint(value = "/blabla")
public class WebsocketService {
@Inject
private DatabaseProvider dbProvider;
@OnOpen
public void onOpen(Session session) throws IOException {
//做一些事情
}
@OnMessage
public void onMessage(Session session, String socketPacket) throws IOException {
//做一些其他事情,包括使用 dbProvider
}
// ...
}
启动嵌入式服务器的代码:
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
import javax.websocket.server.ServerContainer;
//其他导入
public static void main(String[] args) {
Server server = null;
try {
server = new Server(3081);
ServletContextHandler context = new ServletContextHandler();
context.setContextPath("/");
ServerContainer serverContainer = WebSocketServerContainerInitializer.configureContext(context);
serverContainer.addEndpoint(WebsocketService.class);
server.setHandler(context);
server.start();
server.join();
} catch (Exception e) {
logger.error(e.getMessage());
} finally {
if (server != null) {
server.destroy();
}
}
}
上述代码对于没有依赖注入的情况下运行得很好。然而,我想将 dbProvider 注入到我的 WebsocketService
中,并在 onMessage 方法中使用它。
问题1: 如何为WebSocket服务器进行依赖注入?
附注:有多个关于如何使用 ResourceConfig + AbstractBinder + ServletContainer 为REST端点进行依赖注入的示例,但我不确定如何将其应用于WebSocket服务器的情况。
问题2: 如何在同一服务器上添加一个简单的资源端点(用于提供JavaScript)?
英文:
I have a the following websocket endpoint:
import javax.inject.Inject;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
@ServerEndpoint(value = "/blabla")
public class WebsocketService {
@Inject
private DatabaseProvider dbProvider;
@OnOpen
public void onOpen(Session session) throws IOException {
//do something
}
@OnMessage
public void onMessage(Session session, String socketPacket) throws IOException {
//do something else
}
...
}
The code to start the embedded server:
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
import javax.websocket.server.ServerContainer;
//other imports
public static void main(String[] args) {
Server server = null;
try {
server = new Server(3081);
ServletContextHandler context = new ServletContextHandler();
context.setContextPath("/");
ServerContainer serverContainer = WebSocketServerContainerInitializer.configureContext(context);
serverContainer.addEndpoint(WebsocketService.class);
server.setHandler(context);
server.start();
server.join();
} catch (Exception e) {
logger.error(e.getMessage());
} finally {
if (server != null) {
server.destroy();
}
}
}
The code above works perfectly for the case without dependency injection. However, I want to inject the dbProvider into my WebsocketService and use it in the onMessage method.
QUESTION 1: How to do the injection for the websocket server?
P.S. There are multiple examples of how dependency injection is done for REST endpoinds using ResourceConfig + AbstractBinder + ServletContainer, but I am not sure how it can be applied for the case with the websocket server.
QUESTION 2: How to add a simple resource endpoint to the same server (to serve javascript)?
答案1
得分: 0
在这个问题中涉及到很多不同的部分。
首先,你需要设置Weld(CDI实现)以将其与你的 ServletContextHandler
正确集成。
通常是这样设置的...
ServletContextHandler context = new ServletContextHandler();
// 启用 Weld + CDI
context.setInitParameter(
CdiServletContainerInitializer.CDI_INTEGRATION_ATTRIBUTE,
CdiDecoratingListener.MODE);
context.addBean(
new ServletContextHandler.Initializer(context,
new CdiServletContainerInitializer()));
context.addBean(
new ServletContextHandler.Initializer(context,
new org.jboss.weld.environment.servlet.EnhancedListener()));
然后,注入(实际上是装饰)会在Jetty和Weld之间自动进行内部处理。
注意: ServletContextHandler.Initializer
是一个便利类,允许你的嵌入式Jetty运行任意 javax.servlet.ServletContainerInitializer
,而无需进行完整的WebApp和复杂的初始化过程。
CdiServletContainerInitializer
是Jetty提供的一个ServletContainerInitializer
,它在ServletContext
中设置了各种内容,以允许Weld正确地将自己连接到ServletContext
。EnhancedListener
也是Weld提供的一个ServletContainerInitializer
,它完成了Weld + CDI 的一侧连接过程。
用于提供静态文件的话,你需要在 ServletContextHandler
中定义一个 "Base Resource",然后将 DefaultServlet
添加到 "/"
的 "default" url-pattern 中。
ServletContextHandler context = new ServletContextHandler();
context.setBaseResource(Resource.newResource(webRootUri));
context.addServlet(DefaultServlet.class, "/");
如果你想要查看所有这些内容的完整示例,请查看以下示例项目:
https://github.com/jetty-project/embedded-jetty-weld
英文:
Quite a few moving parts in this question.
First you have to setup Weld (the CDI implementation) to properly integrate it with your ServletContextHandler
Typically seen like this ...
ServletContextHandler context = new ServletContextHandler();
// Enable Weld + CDI
context.setInitParameter(
CdiServletContainerInitializer.CDI_INTEGRATION_ATTRIBUTE,
CdiDecoratingListener.MODE);
context.addBean(
new ServletContextHandler.Initializer(context,
new CdiServletContainerInitializer()));
context.addBean(
new ServletContextHandler.Initializer(context,
new org.jboss.weld.environment.servlet.EnhancedListener()));
Then the injection (actually decoration) is automatically taken care of internally between Jetty and Weld.
Note: the ServletContexthandler.Initializer
is a convenience class to allow your embedded-jetty to run an arbitrary javax.servlet.ServletContainerInitializer
without all of the overhead of a full blown WebApp and it's complex initialization process.
- The
CdiServletContainerInitializer
is aServletContainerInitializer
that Jetty provides which sets up various things in theServletContext
to allow Weld to wire itself up properly to theServletContext
. - The
EnhancedListener
is also aServletContainerInitializer
that weld provides which does it's side of the wiring up for Weld + CDI.
For serving static files, you'll want to have a "Base Resource" defined in your ServletContextHandler
and then add the DefaultServlet
to the "default" url-pattern of "/"
.
ServletContextHandler context = new ServletContextHandler();
context.setBaseResource(Resource.newResource(webRootUri));
context.addServlet(DefaultServlet.class, "/");
If you want to see all of this together, check out the example project at
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论