Интеграция JSR-356 WebSocket @ServerEndpoint с весенними 3 бобами
Я использую Spring 3.2.5 без полной поддержки новых WebSockets JSR-356.
Я хотел бы иметь ссылку singleton-bean в моем @ServerEndpoint
сервер WebSocket, который создается самим Контейнером сервлета, а не в контексте Spring.
что такое чистый способ сделать это?
мое текущее решение: я сделал @Service
одноэлементный боб с экземпляром в статическом поле:
@Service
public class WebSocketSupportBean {
private volatile static WebSocketSupportBean instance = null;
public static WebSocketSupportBean getInstance() {
return instance;
}
public WebSocketSupportBean() {
instance = this;
}
и просто получить его в @ServerEndpoint
статическим методом, отключение пользователя при возврате null (если bean не jet создан при запуске сервера, но пользователь подключается):
5 ответов
вы можете настроить websockets с spring framework 3.x
Я разработал небольшое приложение для доказательства концепции, чтобы продемонстрировать, как, на основе SpringConfiguration Россена Стоянчева, выпущенного с spring-core 4.0.
приложение устанавливает конечную точку сервера websocket с uri /wstest
который будет использовать @Autowired
spring bean, чтобы выбрать приветствие и ответить на сообщение websocket.
соединение websocket инициируется и сообщения, отправленные html страница (index.html
) работает в браузере, который поддерживает WebSockets.
Регистрация конечной точки производится ServletContextListener при инициализации контекста, и когда конечная точка будет создана, она будет связана с spring:
@WebListener
public class MyApplication implements ServletContextListener {
private final static String SERVER_CONTAINER_ATTRIBUTE = "javax.websocket.server.ServerContainer";
@Override
public void contextInitialized(ServletContextEvent sce) {
ServletContext container = sce.getServletContext();
final ServerContainer serverContainer = (ServerContainer) container.getAttribute(SERVER_CONTAINER_ATTRIBUTE);
try {
serverContainer.addEndpoint(new MyEndpointConfig(MyEndpoint.class, "/wstest"));
} catch (DeploymentException e) {
e.printStackTrace();
}
}
}
и конечная точка:
@Component
public class MyEndpoint extends Endpoint {
@Autowired
MyService myService;
@Override
public void onOpen(Session session, EndpointConfig config) {
session.addMessageHandler(new MyMessageHandler(session));
}
class MyMessageHandler implements MessageHandler.Whole<String> {
final Session session;
public MyMessageHandler(Session session) {
this.session = session;
}
@Override
public void onMessage(String message) {
try {
String greeting = myService.getGreeting();
session.getBasicRemote().sendText(greeting + ", got your message (" + message + "). Thanks ! (session: " + session.getId() + ")");
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Проверьте полный источник и готовы запустить пример на моем страница Github.
попробовать
@ServerEndpoint(value = "/ws", configurator = SpringConfigurator.class)
и добавьте зависимость maven
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
</dependency>
вы можете сделать свой объект @ServerEndpoint расширить SpringBeanAutowiringSupport. Затем просто сделайте это в курсе бобов, которые строятся в веб-приложении на основе Spring следующим образом:
@PostConstruct
public void init() {
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
}
таким образом @ Autowired аннотация будет worl правильно:
@Autowired MyService myService;
попробуйте это,это работает для меня
@Component
@ServerEndpoint(value = "/instantMessageServer",configurator = SpringConfigurator.class)
public class InstantMessageServer{
private static IChatService chatService;
@Autowired
public InstantMessageServer(IChatService chatService){
this.chatService = chatService;
}
public InstantMessageServer(){}
}
Я нашел это решение на https://spring.io/blog/2013/05/23/spring-framework-4-0-m1-websocket-support но есть еще один глюк, класс, аннотированный @ServerEndpoint, не может получить httpsession с SpringConfigurator, в нем нет переопределения метода modifyhandler.Возможно, мы создадим отдельный конфигуратор, расширяющий SpringConfigurator, и переопределим этот метод как workaroud. Лучше строить в реальном времени веб-приложение с spring-websocket и API обмена сообщениями, я думаю.
public class ModifiedServerEndpointConfigurator extends SpringConfigurator{
@Override
public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
HttpSession httpSession = (HttpSession) request.getHttpSession();
sec.getUserProperties().put(HttpSession.class.getName(),httpSession);
super.modifyHandshake(sec, request, response);
}
}
вы должны добавить определение bean в конфигурации spring.
решение, которое я нашел для интеграции JSR 356 websocket @ServerEndpoint
отключить сканирование контейнера сервлета для конечных точек WebSocket весной, что можно сделать, зарегистрировав @Bean в конфигурации Spring. К этой весне не переопределяет нормальный JSR 356 websocket spring STOMP websocket, который является частью websocket.
@ServerEndpoint(value="/chatMessage")
public class ChatEndpoint{
// Normal websocket body goes here.
}
добавление компонентов в конфигурацию as:
@Configuration
public class WebsocketConfig{
@Bean
public ChatEndpoint chatEndpoint(){
return new ChatEndpoint();
}
// main one is ServerEndpointExporter which prevents Servlet container's scan for WebSocket
@Bean
public ServerEndpointExporter endpointExporter(){
return new ServerEndpointExporter();
}
}
Это все сделано для вас. Но вы должны удалить configurator = SpringConfigurator.class
С @ServerEndpoint
.
Я использую Spring Websocket 4.0.0, и он отлично работает.
Вы также можете увидеть это ссылке.
если вы в порядке, то следуйте этому ссылке также для концепции.
обратите внимание, что обычно вы должны сделать конфигурацию websocket отдельно от основной конфигурации вашей весны.