Java TomcatWebSocketServlet和GoogleGuice
我有一个需要使用Tomcat 7 web套接字的web应用程序 在这个webapp中,所有标准servlet(那些扩展了Java TomcatWebSocketServlet和GoogleGuice,java,servlets,websocket,tomcat7,guice,Java,Servlets,Websocket,Tomcat7,Guice,我有一个需要使用Tomcat 7 web套接字的web应用程序 在这个webapp中,所有标准servlet(那些扩展了javax.servlet.http.HttpServlet)都能很好地(正确地)与googleguice一起工作。要使Servlet与Guice处理程序一起工作,我只需: 用@Singleton 为MyHandler实例声明私有Provider,并生成标记为注入的setter 用@Inject 举例说明上述各点: @Singleton public class MyServl
javax.servlet.http.HttpServlet
)都能很好地(正确地)与googleguice一起工作。要使Servlet与Guice处理程序一起工作,我只需:
@Singleton
MyHandler
实例声明私有Provider
,并生成标记为注入的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;
}
...
}
@Singleton
公共类MyServlet扩展了HttpServlet{
私人提供者myHandler;
@注入
MyServlet(){
}
@凌驾
受保护的无效服务(..)引发ServletException{…}
@注入
public void setMyHandler(提供程序myHandler){
this.myHandler=myHandler;
}
...
}
如何从一个调用同一个Guice处理程序,上面称之为myHandler
?
我不能采用与标准servlet用例相同的样式,因为与标准servlet不同,每个WebSocket通信都会导致实例扩展;然后从MessageInbound实例中的方法(例如,onOpen
或onClose
)调用将调用MyHandler
的适当方法不来自上面的MyServlet
实例中的HttpServlet
方法
我试了什么?我确实尝试了一些(概念上是错误的)解决方案,比如从
MessageInbound
实例中调用websocket servlet的处理程序;这当然会导致Guice堆栈跟踪下方的范围界定问题。概念上正确的方法是什么?我不太明白你想要实现什么。我会在Guice中寻找AOP支持。在MessageInbound子类实例的某些方法中使用MyHandler之前,似乎需要设置(注入)MyHandler。一个方面可以做到这一点
但是,您需要问一个问题:(实例化)控件在哪里?如果有某种方法可以在Tomcat应用程序配置中添加某种委托,Guice可以“增强”MessageInbound实例,从而在使用前设置适当的MyHandler。查看GitHub示例后更新: 如何使用Guice很好。因为MessageInbound只有一个特定用法,所以任何类似AbstractGuiceWebSocketServlet的糖都是不必要的。提供程序chatLogHdlr,然后执行手动构造就可以了。但是你失去了AOP支持。如果需要的话,你可以做辅助注射。但现在这还可以 另一方面,使用构造注入代替setter注入 我立刻看出了问题所在这不是Guice,而是如何使用Guice Persist。我没有经常使用GP,仍然使用古老的Warp Persist。但我发现在代码中如何使用Guice存在两个问题:
@Singleton
public class FooGuiceWebSocketServlet extends WebSocketServlet {...}
然后将其称为
serve("/foo").with(FooGuiceWebSocketServlet.class);
现在,正如您所解释的,这是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));
}
}
}
@Singleton
公共类ExampleWebSocketServlet扩展了AbstractGuiceWebSocketServlet{
@凌驾
公共类如果我理解您的意思,您可以重写WebSocketServlet#createWebSocketInbound,在其中创建MessageInbound的新实例?如果这是真的,那么simple只需让Guice为您创建MessageInbound(如果需要,请辅助注入)。我看到的唯一问题是http请求/响应的范围问题,因为guice筛选器使用线程局部变量来跟踪。但这是可以补偿的。我是否正确地理解了您的意见?谢谢您的评论,但我不理解这部分:“然后简单地让guice为您创建MessageInbound(如果需要,请协助注入)”谢谢你的回答。问题是这是最简单的情况;我需要跟踪连接和invidual连接ID;看看一个简单的概念证明来复制这个问题,以及我的createWebSocketInbound
方法,在这个方法中,我为每个打开的websocket连接设置了clientNo
。在这个结构中,我在哪里做这些您的建议是什么?我将您推荐的结构应用于我的,得到了与以前完全相同的java.lang.IllegalStateException
。很棒的东西;我将根据您建议的修复将我的更改推送到github;它很有效!非常感谢!旁注:@Transactional
仅在最低级别使用,即在与交互时使用de>EntityManager
。PersistFilter在请求开始时启动事务,并在返回响应之前提交。使用[@Transactional]时,事务在方法e之前启动
@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();
}