我有一个需要使用Tomcat 7网络套接字的webapp。
在此网络应用程序中,所有标准Servlet(扩展javax.servlet.http.HttpServlet
)都可以很好地(并且正确地)与 Google Guice 一起使用。为了使我的Servlet与Guice处理程序一起使用,我只需:
@Singleton
Provider
实例& amp;声明私有MyHandler
生成一个标记为注射的setter @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;
}
...
}
如何从WebSocketServlet
调用同一个Guice处理程序,上面称为myHandler
?
我不能采用与标准servlet用例相同的样式,因为不是像标准servlet那样拥有Singleton servlet,每个WebSocket通信都会产生一个扩展MessageInbound
的实例;然后从MessageInbound实例中的方法(例如MyHandler
或onOpen
)调用调用onClose
的适当方法; 不来自HttpServlet
个实例中的方法{/ 1}}。
我尝试了什么?我尝试了一些(概念上错误的)解决方案,例如从MyServlet
实例中调用websocket-servlet的处理程序;这当然会导致范围问题降低Guice堆栈跟踪。这样做的概念正确方式是什么?
答案 0 :(得分:1)
查看GitHub示例后更新:
你如何使用Guice就好了。由于MessageInbound只有一个特定的用法,因此不需要任何与AbstractGuiceWebSocketServlet一样的糖。提供者chatLogHdlr然后做手动构建就可以了。但是你失去了AOP的支持。如果需要,您可能需要执行Assisted Inject。但是现在这很好。
另一方面,使用施工注射而不是二次注射。
我立即看到了什么问题。 这不是Guice,而是你如何使用Guice-Persist。我没有经常使用GP,仍然使用古老的Warp-persist。但是我在你的代码中看到了如何使用Guice-persist的两个问题:
您需要注入PersistService才能启动Guice-Persist。它在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();
}
}
PersistFilter没有用,因为只有WebSocket第一次通过过滤器,但所有后续通信都不会通过过滤器。在@Transactional(每次交易会话)周围使用txn是可行的方法。
题外话:
您打算支持多少用户?如果这将是一个硬核聊天服务器,我会使用Netty,但它更多涉及。谷歌搜索发现了这个:
http://comoyo.github.com/blog/2012/07/30/integrating-websockets-in-netty/
原始答案:
所以这是关于风格的问题?
WebSockets!= Servlets。如果它们需要稍微不同的风格,那就没有错。我甚至更愿意提醒我不要处理香草小服务。
一些观察结果:
WebSocketServlet没什么特别的。您可以轻松地将它与Guice-Servlet一起使用。 E.g:
@Singleton
public class FooGuiceWebSocketServlet extends WebSocketServlet {...}
然后将其称为
serve("/foo").with(FooGuiceWebSocketServlet.class);
现在,MessageInbound是特别的,因为Tomcat正如您所解释的那样处理。 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()因为它阻碍了测试。
在你满意之前,不断改进风格。如果您需要更多帮助(将修改答案),请说明。
答案 1 :(得分:0)
我并不完全明白你想要完成的事情。我会在Guice寻找AOP支持。在使用MessageInbound子类的某些方法之前,似乎需要设置MyHandler(注入)。实例。一个方面可以做到这一点。
但是,您需要问一个问题:(实体化)控制在哪里?如果有某种方法可以在Tomcat应用程序配置中添加某种委托,Guice可以“增强”#34; MessageInbound实例,在使用之前,它将具有正确的MyHandler设置。