gpt4 book ai didi

java - Tomcat WebSocketServlet 和 Google Guice

转载 作者:IT老高 更新时间:2023-10-28 21:16:22 28 4
gpt4 key购买 nike

我有一个需要使用 Tomcat 7 网络套接字的 webapp。

在这个 web 应用程序中,所有标准 Servlet(那些扩展 javax.servlet.http.HttpServlet)都可以很好地(并且正确地)与 Google Guice 一起工作。为了让我的 Servlet 与 Guice 处理程序一起工作,我只是:

  1. @Singleton
  2. 装饰 servlet
  3. MyHandler 实例声明私有(private) Provider 并生成一个标记为注入(inject)的 setter
  4. @Inject
  5. 装饰 Servlet 的构造函数

举例说明以上几点:

@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 调用上面称为 myHandler 的同一个 Guice 处理程序?

我不能采用与标准 servlet 用例相同的样式,因为每个 WebSocket 通信都会产生一个扩展 MessageInbound 的实例,而不是像标准 servlet 那样具有单例 servlet。 ;然后从 MessageInbound 实例中的方法(例如 onOpenonClose)调用将调用 MyHandler 的适当方法; 不是来自 HttpServlet 实例中的方法,如上面的 MyServlet

我尝试了什么?我确实尝试了一些(概念上错误的)解决方案,例如从 MessageInbound 实例中调用 websocket-servlet 的处理程序;这当然会导致降低 Guice 堆栈跟踪的范围问题。这样做的概念正确方法是什么?

最佳答案

查看 GitHub 示例后更新:

您使用 Guice 的方式很好。由于 MessageInbound 只有一种特殊用法,因此不需要像 AbstractGuiceWebSocketServlet 这样的糖。提供者 chatLogHdlr 再做手动构建就可以了。但是你失去了 AOP 支持。如果需要,您可能需要进行辅助注入(inject)。但现在这很好。

附带说明,使用构造注入(inject)而不是 setter 注入(inject)。

我立即看到了问题所在。 这不是 Guice,而是你如何使用 Guice-Persist。 我没有经常使用 GP,仍然使用古老的 Warp-persist。但我发现您在代码中使用 Guice-persist 的方式存在 2 个问题:

  1. 你需要注入(inject) 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();
    }
    }
  2. PersistFilter 没用,因为只有第一次 WebSocket 会通过过滤器,但所有后续通信都不会通过过滤器。在@Transactional (Session-per-transaction) 附近使用 txn 是可行的方法。

题外话:

您打算支持多少用户?如果这将是一个核心聊天服务器,我会改用 Netty,但它会涉及更多。谷歌搜索发现:

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

原答案:

所以这是一个关于风格的问题?

WebSockets != Servlets。 如果它们需要稍微不同的样式,那也没有错。我什至更愿意被提醒我不是在处理 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()因为它会妨碍测试。

不断改进风格,直到您满意为止。说你是否需要更多帮助(将修改答案)。

关于java - Tomcat WebSocketServlet 和 Google Guice,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13958143/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com