如何从服务器中运行的线程触发 CDI 事件



我希望我的udp服务器在线程中运行,每次收到数据报时都会触发一个事件,发送格式化为json的数据。

public class UDPServer extends Thread {
private SocketUDPCommunication comm;
@Inject @Notify
private StatusChangeHandler sch;
public UDPServer() {
comm = new SocketUDPCommunication();
}

@Override
public void run() {
DatagramPacket response;
comm.setPort(Utils.UDP_SERVER_PORT);
comm.createSocket();
while (!Thread.currentThread().isInterrupted()) {
System.out.println("Waiting for clients to connect on port:" + comm.getSocket().getLocalPort());
try {
response = comm.receiveResponse();
} catch (SocketTimeoutException e) {
continue;
}                           
byte[] byteSend = comm.discardOffset(response);
Status status = frameToJson(byteSend);
Genson genson = new Genson();
String json = genson.serialize(status);
sch.sendChangedStatus(json);    //Raise the cdi event, sch not initialized!!
}
}
@Override
public void interrupt() {
super.interrupt();
comm.closeConnection();
}
}

为此事件定义了一个侦听器,它将调用 websocket 终结点方法将此消息广播到所有连接的客户端:

public class StatusChangeObserver {
public void statusChanged(@Observes StatusChange sce) {
WebsocketEndPoint.sendAll(sce.getJson());
}
}
@ServerEndpoint(value="/websocket")
public class WebsocketEndPoint {
private static Set<Session> userSessions = Collections.synchronizedSet(new HashSet<Session>());
@OnOpen
public void onOpen(Session userSession) {
System.out.println("Opening new connection");
userSessions.add(userSession);
}
@OnClose
public void onClose(Session userSession) {
System.out.println("Connection closed. Id: " + userSession.getId());
userSessions.remove(userSession);
}

public static void sendAll(String message) {
for (Session session : userSessions) {
if (session.isOpen()) {
session.getAsyncRemote().sendText(message);
}
}     
}
}

以及实际触发事件的处理程序:

@Notify
public class StatusChangeHandler {
@Inject
private Event<StatusChange> statusChangedEvent;
public void sendChangedStatus(String json) {
StatusChange sce = new StatusChange(json);
statusChangedEvent.fire(sce);
}
}

StatusChange是一个简单的POJO,它将包含要广播的消息。@Notify限定符:

@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER, TYPE})
public @interface Notify {
}

这些是我使用依赖注入的第一步,所以我不太确定我应该如何从线程中触发事件,以及如何初始化sch对象。 我发现这个页面建议使用WeldWeldContainer类来初始化 CDI,但我无法使用 maven 找到这个类。这是正确的方法吗?在这种情况下,有人知道如何将这些类包含在我的项目中吗?

这里有带有焊接库的公共存储库。

https://mvnrepository.com/artifact/org.jboss.weld

但是,你需要什么?在环境中你会使用它吗?例如,在 wildfly 中,集成了 cdi 1.1 或 cdi 1.2,您无需添加此库。

有关详细信息,请使用 http://weld.cdi-spec.org/

既然你在Tomcat上,我们谈论的是servlet环境。为此,Weld 提供了一个 servlet JAR,它会自动为您引导 CDI。无需手动处理Weld/WeldContainer

这是指向 Weld 文档的链接,其中解释了您需要哪些工件/依赖项以及如何使用它。

添加后,CDI 应该在将应用程序部署到 Tomcat 时为您引导。

最新更新