Ответ 1
Обновление после просмотра примера GitHub:
Как вы используете Guice, все в порядке. Поскольку существует только одно конкретное использование MessageInbound, любой сахар, например, с AbstractGuiceWebSocketServlet, не нужен. Провайдер chatLogHdlr, а затем делает ручную конструкцию в порядке. Но вы теряете поддержку АОП. Если это необходимо, вам может понадобиться Assisted Inject. Но пока это нормально.
В боковом примечании используйте инъекцию конструкции вместо инъекции установщика.
Я сразу понял, в чем проблема. Это не Guice, а скорее как вы используете Guice-Persist. Я много не использовал GP и все еще использую почтенный Warp-persist. Но я вижу 2 проблемы с тем, как вы используете 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 будет проходить через фильтр, но все последующие сообщения не будут проходить через фильтр. Использование txn только вокруг @Transactional (сеанс за транзакцию) - это путь.
Не по теме:
Сколько пользователей вы намерены поддерживать? Если это будет хардкорный чат-сервер, я бы вместо этого использовал Netty, но он несколько больше задействован. Googling нашел это:
http://comoyo.github.com/blog/2012/07/30/integrating-websockets-in-netty/
Оригинальный ответ:
Итак, это вопрос о стиле?
WebSockets!= Сервлеты. Нет ничего плохого, если они требуют немного другого стиля. Я даже предпочел бы напомнить, что я не имею дело с серфингистами ванили.
Некоторые наблюдения:
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();
}
Вы можете перейти отсюда к более высоким абстракциям и/или scopings по мере необходимости. Мне не особенно нравится # getWsOutbound(), поскольку это мешает тестированию.
Просто продолжайте улучшать стиль, пока не будете удовлетворены. Скажите, нужна ли вам дополнительная помощь (измените ответ).