将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配置与弹簧的主要配置分开。