2012-12-19 23 views
27

Tomcat 7 web soketlerinin kullanımını gerektiren bir web sunucum var.Tomcat WebSocketServlet ve Google Guice

Bu web sunucusunda, tüm standart Servlet'ler (javax.servlet.http.HttpServlet'u genişletenler), güzel bir şekilde (ve doğru şekilde) Google Guice ile çalışır.

  1. MyHandler örneği @Inject
  2. ile Servlet yapıcısı süslemeleri enjeksiyonu
  3. için işaretlenmiş bir ayarlayıcı oluşturmak & özel Provider için beyan @Singleton
  4. ile Servlet'dir süslemek: Guice işleyicileri sadece ben ile benim Servlet çalışması için

    :

yukarıdaki Örnek noktaları göstermek için

Aynı GUIL işleyicisini nasıl arayabiliriz, yukarıdaki myHandler adı verilen bir WebSocketServlet?

I standardı sunucu uygulaması kullanımı durumunda olduğu gibi aynı stil kabul edilemez, çünkü oldukça standart servlet durumunda olduğu gibi bir Singleton sunucu uygulamasını olmasındansa MessageInbound uzanan bir durumda her bir WebSocket iletişim sonuçlar; Daha sonra MyHandler'u arayacak uygun yöntem MessageInbound örneğinde bir yöntemden (ör. onOpen veya onClose) çağrılır; , HttpServlet örneğinde, MyServlet numaralı örnekte bir yöntemden değil numaralı telefondan.

Ne denedim? Websocket-servlet işleyicilerini MessageInbound örneğinin içinden çağırmak gibi bazı (kavramsal olarak yanlış) çözümler denedim; Tabii ki, kapsam belirleme problemleri Guice yığın izinin altına düşüyor. Kavramsal olarak doğru bunu yapmanın yolu nedir?

+0

Sizi anlarsam, MessageInbound'un yeni bir örneğini oluşturduğunuz WebSocketServlet # createWebSocketInbound'u geçersiz kılarsınız? Bu doğruysa, o zaman Guice'nin sizin için MessageInbound'u oluşturmasına izin verin (gerekirse enjekte edin). Gördüğüm tek sorun, http isteği/yanıtlarının kapsamı olarak ayarlanmasıdır. Ama bu telafi edilebilir. Seni doğru şekilde takip ettim mi? –

+0

Yorumunuz için teşekkür ederim, ancak bu kısmı anlamadım: "Basitçe Guice'nin sizin için MessageInbound'u yaratmasına izin verin (gerekirse enjekte edin)" –

cevap

1

Güncelleme: Eğer Guice kullanmak nasıl

gayet iyi. MessageInbound'un sadece belirli bir kullanımı olduğundan, AbstractGuiceWebSocketServlet ile herhangi bir şeker gereksizdir. Sağlayıcı chatLogHdlr ve sonra manuel yapım tamamdır. Ama AOP desteğini kaybedersin. Eğer gerekliyse Yardımlı Enjeksiyon yapmak isteyebilirsiniz. Ama şimdilik bu iyi.

Bir yan notta, setter enjeksiyonu yerine yapı enjeksiyonu kullanın.

Sorunun ne olduğunu hemen gördüm. Bu Guice değil, Guice-Persist'i nasıl kullanırsınız. Çok fazla GP kullanmadım ve hala saygıdeğer Warp-perspektifi kullanıyorum. Sen Guice-Persist başlatmak için PersistService enjekte etmek gerek

  1. : Ama Kodunuzdaki Guice-inat nasıl kullandığınız ile 2 sorunları görüyoruz. WIKI'da açıklanmaktadır.

    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. sadece ilk kez WebSocket oluk filtreyi gidecek ama sonraki tüm iletişim filtreden geçtiğini gitmeyecek olarak PersistFilter işe yaramaz. @Transactional'ın (işlem başına oturumu) etrafındaki txn'yi kullanmak yoldur.

Konu dışı:

kaç kullanıcıya desteklemek düşünüyorsunuz? Bu bir hardcore sohbet sunucusu olacaksa, bunun yerine Netty kullanayım, ama biraz daha ilgili. buldum Googling:

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

Orjinal cevap:

Yani bu tarz ilgili bir soru?

WebSockets! = Servletler. Biraz farklı bir stil gerektiriyorsa yanlış bir şey yok. Vanilya servletleriyle uğraştığımı hatırlatmayı bile tercih ederim.

Bazı gözlemler:

WebSocketServlet özel bir şey değil. Guice-Servlet ile kolayca kullanabilirsiniz. Şimdi

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

, sen açıklandığı gibi tüm Tomcat tarafından işlendiğini olarak özeldir MessageInbound olarak ör .:

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

Sonra refernce bunu. MessageInbound, WebSocket kapsamıdır. Şimdi Guice'in bu konu hakkında bir fikri yok ve bu şekilde bırakmak mantıklı olabilir.

Yeni başlayanlar için MessageInbound'un Guice tarafından oluşturulduğundan emin olabilirdim. Bu doğrultuda bir şey: Gerektiğinde

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(); 

} 

buradan daha yüksek soyutlama ve/veya scopings gidebilirsiniz

@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)); 
    } 

    } 
} 

. Testleri engellediğinden özellikle #getWsOutbound()'u beğenmiyorum.

Sadece memnun oluncaya kadar stili iyileştirmeye devam edin. Daha fazla yardıma ihtiyacınız varsa cevap verin (cevabı değiştirir).

+0

Cevabınız için teşekkürler. Sorun bu en basit durumdur; Bağlantıları ve kişisel bağlantı kimliklerini takip etmem gerekiyor; [MainSocket.java] 'da [https://github.com/jvzammit/wspoc] ve' createWebSocketInbound 'yöntemimi [https://github.com/jvzammit/wspoc] ile ilgili sorunu yinelemek için basit bir kavram kanıtına bakın (https: // github.com/jvzammit/wspoc/blob/master/wspoc/poc-web/src/main/java/com/cif/dt/app/websocket/MainSocket.java) her açılmış web bağlantısı bağlantısına 'clientNo 'ayarlıyorum . Bunu yapabildiğiniz bu yapıyı nerede yapacağım? –

+0

Önerilen yapınızı [konsept kanıtı] 'na (https://github.com/jvzammit/wspoc) uyguladım ve daha önce olduğu gibi "java.lang.IllegalStateException" ile aynı şeyi aldım. –

+0

Güncelleme yanıtı, umarım bu sizin sorununuzu çözer. –

0

Neyi başarmaya çalıştığınızı tam olarak anlamadım. Guice'de AOP desteğini arardım. MyHandler'ın bazı MessageInbound alt sınıfı örneklerinde kullanılmadan önce ayarlanması gerektiğine inanıyorsunuz. Bir yönü bunu yapabilirdi. Bununla birlikte, sormanız gereken bir soru var: (anlıklaştırma) kontrolü nerede? Tomcat uygulama yapılandırmanızda bir tür temsilci eklemenin bir yolu varsa, Guice, kullanmadan önce uygun MyHandler setini ayarlayabilecek MessageInbound örneklerini "geliştirebilir". GitHub Örneğin baktıktan sonra