27

Tomcat 7 Web ソケットの使用を必要とする Web アプリケーションがあります。

この webapp では、すべての標準サーブレット ( を拡張するもの) がGoogle Guicejavax.servlet.http.HttpServletとうまく (そして正しく) 動作します。サーブレットを Guice ハンドラーで動作させるには、次のようにします。

  1. でサーブレットを装飾する@Singleton
  2. Providerたとえば、プライベートを宣言しMyHandler、注入用にマークされたセッターを生成します
  3. サーブレットのコンストラクターを装飾します@Inject

上記のポイントを示す例:

@Singleton
public class MyServlet extends HttpServlet {

    private Provider<MyHandler> myHandler;

    @Inject
    MyServlet() {
    }

    @Override
    protected void service(..) throws ServletException { ... }

    @Inject
    public void setMyHandler(Provider<MyHandler> myHandler) {
        this.myHandler = myHandler;
    }

    ...
}

myHandler上記のから呼び出された同じ Guice ハンドラをどのように呼び出すことができWebSocketServletますか?

標準サーブレットの場合のようにシングルトン サーブレットを使用するのではなく、各 WebSocket 通信によってインスタンスが拡張されるため、標準サーブレットのユース ケースと同じスタイルを採用することはできませんMessageInbound。次に、呼び出す適切なメソッドがMessageInbound インスタンス内のMyHandlerメソッド (onOpenまたは など) から呼び出されます。上記のようにインスタンス内のメソッドからではありませんonCloseHttpServletMyServlet

私は何を試しましたか?MessageInboundインスタンス内から websocket-servlet のハンドラーを呼び出すなど、いくつかの (概念的に間違った) 解決策を試しました。もちろん、Guice スタック トレースの下位にスコープの問題が発生します。これを行う概念的に正しい方法は何ですか?

4

2 に答える 2

1

GitHubの例を見た後に更新します。

Guiceの使い方は問題ありません。MessageInboundの特定の使用法は1つしかないため、AbstractGuiceWebSocketServletのような砂糖は不要です。プロバイダーchatLogHdlrを実行してから、手動で構築しても問題ありません。ただし、AOPサポートは失われます。それが必要な場合は、アシストインジェクトを実行することをお勧めします。しかし、今のところこれは問題ありません。

ちなみに、セッターインジェクションの代わりにコンストラクションインジェクションを使用してください。

何が問題なのかすぐにわかりました。これはGuiceではなく、Guice-Persistの使用方法です。私はGPをあまり使用しませんでしたが、それでも由緒あるWarp-persistを使用しています。しかし、コードでGuice-persistを使用する方法に2つの問題があります。

  1. Guice-Persistを開始するには、PersistServiceを挿入する必要があります。それはWIKIで説明されています。

    public class PocWebApp extends GuiceServletContextListener {
    
    @Inject
    PersistService ps;
    
    @Override
    protected Injector getInjector() {
        Injector injector = Guice.createInjector(new ServletModule() {
    
            @Override
            protected void configureServlets() {
                install(new JpaPersistModule("DesktopPU"));
                serve("/socket/main/").with(MainSocket.class);
            }
    
        });
        injector.injectMembers(this);
        return injector;
    }
    
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        super.contextInitialized(servletContextEvent);
        ps.start();
    }
    }
    
  2. PersistFilterは、WebSocketがフィルターを通過するのは初めてですが、それ以降のすべての通信はフィルターを通過しないため、役に立ちません。@Transactional(Session-per-transaction)のすぐ近くでtxnを使用するのが方法です。

オフトピック:

何人のユーザーをサポートするつもりですか?これが筋金入りのチャットサーバーになる場合は、代わりにNettyを使用しますが、多少複雑です。グーグルはこれを見つけました:

http://comoyo.github.com/blog/2012/07/30/integrating-websockets-in-netty/

元の答え:

それで、これはスタイルについての質問ですか?

WebSockets!=サーブレット。少し違うスタイルが必要な場合でも問題ありません。バニラサーブレットを扱っていないことを思い出してもらいたいと思います。

いくつかの観察:

WebSocketServletは特別なものではありません。Guice-Servletで簡単に使用できます。例えば:

 @Singleton
 public class FooGuiceWebSocketServlet extends WebSocketServlet {...}

そしてそれを次のように参照します

 serve("/foo").with(FooGuiceWebSocketServlet.class);

さて、あなたが説明したように、すべてTomcatによって処理されるように特別なMessageInbound 。MessageInboundはWebSocketスコープです。現在、Guiceはこのスコープについて何も知らないので、そのままにしておくのが理にかなっているかもしれません。

手始めに、MessageInboundがGuiceによって作成されていることを確認します。この線に沿った何か:

@Singleton
public class ExampleWebSocketServlet extends AbstractGuiceWebSocketServlet {

    @Override
    public Class<? extends StreamInbound> serveWith() {
        return Foo.class;
    }

    public static class Foo extends MessageInbound {

    @Inject GuiceCreatedAndInjected bar;

    @Override
    protected void onBinaryMessage(ByteBuffer byteBuffer) throws IOException {
        // do nothing
    }

    @Override
    protected void onTextMessage(CharBuffer charBuffer) throws IOException {
        // this getSwOutbonds() is not very friendly to testing
        getWsOutbound().writeTextMessage(bar.echo(charBuffer));
    }

   }
}

どこ

public abstract class AbstractGuiceWebSocketServlet extends WebSocketServlet {

    @Inject Injector injector;

    @Override
    protected StreamInbound createWebSocketInbound(String subProtocol, HttpServletRequest request) {
        return injector.getInstance(serveWith());
    }

    public abstract Class<? extends StreamInbound> serveWith();

}

必要に応じて、ここからより高度な抽象化やスコーピングに進むことができます。#getWsOutbound()はテストの妨げになるため、特に好きではありません。

満足するまでスタイルを改善し続けてください。さらにヘルプが必要な場合は言ってください(答えを変更します)。

于 2013-02-19T03:14:14.867 に答える
0

私はあなたが何を成し遂げようとしているのかよくわかりませんでした。GuiceでAOPサポートを探します。MessageInboundサブクラスのインスタンスの一部のメソッドで使用する前に、MyHandlerを設定(挿入)する必要があるようです。アスペクトはそれを行うことができます。

ただし、質問する必要がある質問が1つあります。それは、(インスタンス化)制御はどこにあるのかということです。Tomcatアプリケーション構成にある種の委任を追加する方法がある場合、GuiceはMessageInboundインスタンスを「拡張」し、使用前に適切なMyHandlerを設定することができます。

于 2013-02-18T16:40:32.917 に答える