私はJavaEE6 Webアプリケーションを持っており、WebSocketプロトコルを使用してブラウザーと通信します。ブラウザはさまざまな種類のメッセージを送信できます。サーバーのonMessageメソッドでは、メッセージの種類に応じて、特定のメッセージハンドラークラスにメッセージをルーティング(またはディスパッチ)したいと思います。サーブレット(@WebServlet( "/ there"))のメカニズムと同様に、アノテーションを介してこれらのメッセージハンドラーを構成または登録したいと思います。また、サーブレットと同様に、メッセージハンドラで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サーブレットの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"
これは正常に機能します。最初のメッセージと2番目のメッセージはそれぞれFirstMessageHandlerとSecondMessageHandlerによって処理されます。キー「third」を処理するために登録された他のハンドラーがないため、3番目のメッセージはデフォルトのメッセージハンドラーによって処理されます。
私の問題:メッセージハンドラーはJavaリフレクションを使用して作成されているため、インジェクションを使用できません。注釈処理とCDIインジェクションを「結婚」させる方法を知っている人はいますか?または、このアプローチはでたらめであり、そのための別の解決策があると誰かが思いますか?
よろしく
セバスチャン