Jos*_*mit 27 java servlets guice websocket tomcat7
我有一个webapp,需要使用Tomcat 7 Web套接字.
在这个webapp中,所有标准的Servlet(扩展的javax.servlet.http.HttpServlet)都能很好地(和正确地)与Google Guice一起工作.为了让我的Servlet与Guice处理程序一起使用,我只需:
@SingletonProvider为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;
}
...
}
Run Code Online (Sandbox Code Playgroud)
如何调用同一个Guice处理程序,上面调用myHandler了一个WebSocketServlet?
我不能采用与标准servlet用例相同的样式,因为不是像标准servlet那样拥有Singleton servlet,每个WebSocket通信都会导致实例扩展MessageInbound; 然后MyHandler从MessageInbound实例中的方法(例如onOpen或onClose)调用将调用的适当方法; 不是来自上述HttpServlet实例中的方法MyServlet.
我尝试了什么?我确实尝试了一些(概念上错误的)解决方案,例如从MessageInbound实例中调用websocket-servlet的处理程序; 这当然会导致范围问题降低Guice堆栈跟踪.这样做的概念正确方法是什么?
查看 GitHub 示例后更新:
你如何使用 Guice 就可以了。由于 MessageInbound 只有一种特定用法,因此不需要像 AbstractGuiceWebSocketServlet 那样的任何糖。提供chatLogHdlr然后手动构建就可以了。但是你失去了 AOP 支持。如果需要,您可能需要进行辅助注射。但目前来说这还好。
顺便说一句,使用构造注入而不是设置器注入。
我立即看出问题所在。这不是 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();
}
}
Run Code Online (Sandbox Code Playgroud)PersistFilter 是无用的,因为只有第一次 WebSocket 才会通过过滤器,但所有后续通信都不会通过过滤器。在@Transactional(每笔交易会话)周围使用txn是正确的方法。
无关:
您打算支持多少用户?如果这将成为一个硬核聊天服务器,我会使用 Netty,但它有点复杂。谷歌搜索发现了这个:
http://comoyo.github.com/blog/2012/07/30/integrating-websockets-in-netty/
原答案:
所以这是一个关于风格的问题?
WebSocket != Servlet。如果他们需要稍微不同的风格,也没有什么问题。我什至更希望有人提醒我我不是在处理普通的 servlet。
一些观察结果:
WebSocketServlet没什么特别的。您可以轻松地将它与 Guice-Servlet 一起使用。例如:
@Singleton
public class FooGuiceWebSocketServlet extends WebSocketServlet {...}
Run Code Online (Sandbox Code Playgroud)
然后将其引用为
serve("/foo").with(FooGuiceWebSocketServlet.class);
Run Code Online (Sandbox Code Playgroud)
现在,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));
}
}
}
Run Code Online (Sandbox Code Playgroud)
在哪里
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();
}
Run Code Online (Sandbox Code Playgroud)
您可以根据需要从这里转到更高的抽象和/或范围。我不太喜欢#getWsOutbound(),因为它阻碍了测试。
不断改进风格,直到您满意为止。说出您是否需要更多帮助(将修改答案)。
| 归档时间: |
|
| 查看次数: |
2555 次 |
| 最近记录: |