依赖注入到嵌入式Jetty中的WebSocket端点

huangapple go评论135阅读模式
英文:

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 a ServletContainerInitializer that Jetty provides which sets up various things in the ServletContext to allow Weld to wire itself up properly to the ServletContext.
  • The EnhancedListener is also a ServletContainerInitializer 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

https://github.com/jetty-project/embedded-jetty-weld

huangapple
  • 本文由 发表于 2020年10月8日 02:05:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/64249854.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定