我有一个 Java EE 6 Web 应用程序并使用 WebSocket 协议与浏览器进行通信。浏览器可以发送各种类型的消息,并且在服务器的onMessage方法中,我想根据消息类型将消息路由(或分派)到特定的消息处理程序类。我想通过注解配置或注册这些消息处理程序,类似于 servlet 的机制(@WebServlet("/there"))。就像在 servlet 中一样,我希望能够在消息处理程序中使用 CDI 注入。
现在我有一个MessageType注释、一个MessageHandler接口和 3 个实现。
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MessageType
{
String value();
}
public interface MessageHandler
{
public void processMessage(String inputMesssage);
}
@MessageType("first")
public class FirstMessageHandler implements MessageHandler
{
@Inject
ResourceBundleProvider resourceBundleProvider;
@Override
public void processMessage(String inputMesssage)
{
System.out.println("FirstMessageHandler#processMessage: " + inputMesssage);
System.out.println("InjectionTest: " + resourceBundleProvider.getValue("label.language"));
}
}
@MessageType("second")
public class SecondMessageHandler implements MessageHandler
{
@Override
public void processMessage(String inputMesssage)
{
System.out.println("SecondMessageHandler#processMessage: " + inputMesssage);
}
}
public class DefaultMessageHandler implements MessageHandler
{
@Override
public void processMessage(String inputMesssage)
{
System.out.println("DefaultMessageHandler#processMessage: " + inputMesssage);
}
}
我还有一个MessageDispatcher类,它使用反射扫描类路径以查找带注释的消息处理程序,实例化它们并将它们放入映射中:
@ApplicationScoped
public class MessageDispatcher
{
private Map<String, MessageHandler> messageHandlerMap = new HashMap<String, MessageHandler>();
@Inject
DefaultMessageHandler defaultMessageHandler;
public MessageDispatcher()
{
registerAnnotatedHandlers();
}
private void registerAnnotatedHandlers()
{
Reflections reflections = new Reflections("namespace");
try
{
for (Class<?> annotatedClass : reflections.getTypesAnnotatedWith(MessageType.class))
{
String annotationValue = annotatedClass.getAnnotation(MessageType.class).value();
for (Class<?> interfaceClass : annotatedClass.getInterfaces())
if (!annotationValue.isEmpty() && interfaceClass.equals(MessageHandler.class))
messageHandlerMap.put(annotationValue, (MessageHandler) annotatedClass.newInstance());
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
public MessageHandler getMessageHandler(String key)
{
MessageHandler messageHandler = messageHandlerMap.get(key);
return messageHandler != null ? messageHandler : defaultMessageHandler;
}
}
最后,在我的 websocket servlet 的onMessage方法中,我从入站消息中提取密钥并将其用于消息路由:
public synchronized void onMessage(String data)
{
String[] message = data.split(":");
// Choose the message handler from the message
MessageHandler messageHandler = messageDispatcher.getMessageHandler(message[0]);
// Process the message by the message handler
messageHandler.processMessage(message[1]);
}
我的 3 条传入示例消息是:
"first:Message to handle with FirstMessageHandler"
"second:Message to handle with SecondMessageHandler"
"third:Message to handle with DefaultMessageHandler"
这很好用,第一条和第二条消息分别由 FirstMessageHandler 和 SecondMessageHandler 处理。第三条消息由默认消息处理程序处理,因为没有注册其他处理程序来处理键“第三”。
我的问题:我不能在消息处理程序中使用注入,因为它们是使用 Java 反射创建的。有人知道如何让注释处理和 CDI 注入“结婚”吗?或者是否有人认为这种方法是胡说八道并且有另一种解决方案?
最好的问候
塞巴斯蒂安