将JSR-356 WebSocket @ServerEndpoint与Spring 3 bean集成

我使用Spring 3.2.5而没有全新的JSR-356 WebSockets支持。

我想在我的@ServerEndpoint WebSocket服务器中使用singleton-bean引用,该服务器由servlet容器本身实例化,而不是在Spring上下文中实例化。

干净的方法是什么?

我目前的解决方案:我在静态字段中使用实例制作了@Service单例bean:

 @Service public class WebSocketSupportBean { private volatile static WebSocketSupportBean instance = null; public static WebSocketSupportBean getInstance() { return instance; } public WebSocketSupportBean() { instance = this; } 

并且只是通过静态方法在@ServerEndpoint获取它,如果返回null则断开用户连接(如果在服务器启动期间bean没有创建,但是用户连接):

您可以使用spring framework 3.x设置websockets

我开发了一个小概念validation应用程序来演示如何基于Rossen Stoyanchev的SpringConfiguration与spring-core 4.0一起发布。

应用程序使用uri /wstest设置websocket服务器端点,该端点将使用@Autowired spring bean来选择问候语并回复websocket消息。

启动websocket连接,并在支持websockets的浏览器中运行的html页面( index.html )发送消息。

端点初始化时由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 { 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依赖

  org.springframework spring-websocket  

您可以使@ServerEndpoint对象扩展SpringBeanAutowiringSupport。 然后让它知道以这种方式在基于Spring的Web应用程序中构造的bean:

  @PostConstruct public void init() { SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this); } 

这样@Autowired注释将正确运行:

 @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的覆盖。也许我们创建一个单独的Configurator扩展SpringConfigurator并覆盖该方法将是一个workaroud。 我认为最好使用spring-websocket和messaging api构建一个实时Web应用程序。


 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); } } 

你必须在spring的配置中添加bean定义。

我发现集成JSR 356 websocket @ServerEndpoint的解决方案是通过spring关闭Servlet容器对WebSocket端点的扫描,这可以通过在Spring配置中注册@Bean来完成。 到了这个弹簧,弹簧STOMP websocket不会覆盖普通的JSR 356 websocket,它是websocket的一部分。

 @ServerEndpoint(value="/chatMessage") public class ChatEndpoint{ // Normal websocket body goes here. } 

在配置中添加Bean为:

 @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(); } } 

这一切都为你完成。 但是你应该从@ServerEndpoint删除configurator = SpringConfigurator.class @ServerEndpoint 。 我正在使用Spring Websocket 4.0.0,它工作正常。 您还可以看到此链接 。

如果你还好,那么也可以按照这个链接的概念。

请注意,通常您应该将websocket配置与弹簧的主要配置分开。