我有一個Java EE 6 Web應用程序,並使用WebSocket協議與瀏覽器進行通信。瀏覽器可以發送各種類型的消息,並在服務器 onMessage方法我想根據消息類型將消息路由(或調度)到特定的消息處理程序類。我想通過註釋來配置或註冊這些消息處理程序,類似於servlet的機制(@WebServlet(「/ there」))。就像在servlet中一樣,我希望能夠在消息處理程序中使用CDI注入。自定義註釋和CDI注入消息路由/處理
現在我有一個消息類型註釋,一個的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它使用reflections掃描類路徑註釋消息處理程序,實例化它們,並將它們放入一個地圖:
@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注入「已婚」嗎?還是有人認爲這種方法是廢話,並有另一個解決方案呢?
問候
塞巴斯蒂安
我想知道事件是如何被實際解僱的。在互聯網上發現的各種CDI事件例子中,事件被注入了某種程度。對我來說,這種方法似乎有點矯枉過正,並且非常靜態,因爲我必須爲每種新類型的消息定義限定符。 –
是的,事件被注入。你只需要創建一個限定符(你已經有了註釋,所以你只有一半)和一個文字。文字將需要用正確的值創建註釋的實例,並且在您啓動事件時使用該實例。 – LightGuard
如果你能舉一個小例子,那將會很棒。特別是如何在傳入websocket消息時觸發事件。 我最初的方法的魅力在於,我可以使用每個消息中的密鑰從註冊處理程序的映射中選擇適當的消息處理程序,而不必使用大的靜態if-else結構。我想以某種方式保持這個概念,並且還有消息處理程序由CDI容器管理,以便將其他依賴注入到它們中。 –