查看 GitHub 示例后更新:
你如何使用 Guice 就很好。由于 MessageInbound 只有一种特殊用法,因此不需要像 AbstractGuiceWebSocketServlet 这样的糖。提供者 chatLogHdlr 再做手动构建就可以了。但是你失去了 AOP 支持。如果需要,您可能需要进行辅助注射。但现在这很好。
附带说明一下,使用构造注入而不是 setter 注入。
我立即看到了问题所在。这不是 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 (Session-per-transaction) 附近使用 txn 是要走的路。
题外话:
您打算支持多少用户?如果这将是一个核心聊天服务器,我会改用 Netty,但它会涉及更多。谷歌搜索发现了这个:
http://comoyo.github.com/blog/2012/07/30/integrating-websockets-in-netty/
原答案:
所以这是一个关于风格的问题?
WebSockets != Servlet。如果他们需要稍微不同的风格,这没有什么错。我什至更愿意被提醒我不是在处理 vanilla servlet。
一些观察:
WebSocketServlet没什么特别的。您可以轻松地将它与 Guice-Servlet 一起使用。例如:
@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(),因为它会阻碍测试。
继续改进风格,直到您满意为止。说如果您需要更多帮助(将修改答案)。