Spring Cloud/Boot WebSocket 无法注入其他类的解决办法
2017-12-12 14:17
405 查看
SpringBoot官方文档推荐实现的WebSocket的方式是添加@ServerEndpoint这个注解。我也是按照推荐实现的。
但是有问题。
我开始的写的WebSocket的例子:
当客户端发送请求的时候,会报空指针异常,TestInfo 为空。
创建MyWebSocket,也是通过@Bean的形式实现的。其他的地方都没有问题。
我已经autowired了,干嘛没注入啊。
TestInfo是通过Spring容器进行管理的,但是使用ServerEndpoint这个注解的时候,失效了。
猜测原因就是这个MyWebSocket这个并不是Spring容器管理的。但是这个是官方推荐的实现方法 啊。
寻寻觅觅,最后在强大的stackoverflow中找到了解决问题的办法。
https://stackoverflow.com/questions/30483094/springboot-serverendpoint-failed-to-find-the-root-webapplicationcontext
定义一个MyEndpointConfigure
这个类的核心就是getEndpointInstance(Class clazz)这个方法。
定义了获取类实例是通过ApplicationContext获取。
为
@ServerEndpoint(value = “/websocket”,configurator=MyEndpointConfigure.class)
大致的意思可以理解了,创建类需要通过MyEndpointConfigure.getEndpointInstance()这个来实现。
运行一切正常。
但是这种形式并不是正常的Spring容器去正常去管理这个WebSocket,个人觉得并不是很好。
这个帖子同时还给出了第二解决方法。原生的Spring实现的WebSocket的办法。
代码如下:
简单实现几个关键的方法。
TestInfo 直接注入。
编写Configure类
这种实现方法可以查看官方文档。
https://docs.spring.io/spring/docs/4.3.13.RELEASE/spring-framework-reference/htmlsingle/#websocket
经测试可以正常工作。
个人建议采用第二种方法,因为这个是Spring自带的WebSocket的实现方式。
实现上需要花时间看看Spring是如何将WebSocket的请求进行处理。以后有时间补上这个。
但是有问题。
我开始的写的WebSocket的例子:
@ServerEndpoint(value = "/websocket" ) @Component public class MyWebSocket { // 与某个客户端的连接会话,需要通过它来给客户端发送数据 private Session session; @Autowired TestInfo testInfo; /** * 连接建立成功调用的方法 */ @OnOpen public void onOpen(Session session) { System.out.println(this.hashCode()); this.session = session; try { System.out.println(testInfo.name); sendMessage("新用户添加进来了...."); } catch (IOException e) { System.out.println("IO异常"); } } /** * 连接关闭调用的方法 */ @OnClose public void onClose() { System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount()); } /** * 收到客户端消息后调用的方法 * * @param message * 客户端发送过来的消息 */ @OnMessage public void onMessage(String message, Session session) { System.out.println("来自客户端的消息:" + message); } /** * 发生错误时调用 */ @OnError public void onError(Session session, Throwable error) { System.out.println("发生错误"); error.printStackTrace(); } public void sendMessage(String message) throws IOException { this.session.getBasicRemote().sendText(message); } }
当客户端发送请求的时候,会报空指针异常,TestInfo 为空。
创建MyWebSocket,也是通过@Bean的形式实现的。其他的地方都没有问题。
我已经autowired了,干嘛没注入啊。
TestInfo是通过Spring容器进行管理的,但是使用ServerEndpoint这个注解的时候,失效了。
猜测原因就是这个MyWebSocket这个并不是Spring容器管理的。但是这个是官方推荐的实现方法 啊。
寻寻觅觅,最后在强大的stackoverflow中找到了解决问题的办法。
https://stackoverflow.com/questions/30483094/springboot-serverendpoint-failed-to-find-the-root-webapplicationcontext
第一种方法:
继续用ServerEndpoint。定义一个MyEndpointConfigure
/** * * @author lipengbin * */ public class MyEndpointConfigure extends ServerEndpointConfig.Configurator implements ApplicationContextAware { private static volatile BeanFactory context; @Override public <T> T getEndpointInstance(Class<T> clazz) throws InstantiationException { return context.getBean(clazz); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { System.out.println("auto load"+this.hashCode()); MyEndpointConfigure.context = applicationContext; } }
这个类的核心就是getEndpointInstance(Class clazz)这个方法。
定义了获取类实例是通过ApplicationContext获取。
@Configuration public class MyConfigure { @Bean public MyEndpointConfigure newConfigure() { return new MyEndpointConfigure(); } }
修改MyWebSocket的注解
@ServerEndpoint(value = “/websocket” )为
@ServerEndpoint(value = “/websocket”,configurator=MyEndpointConfigure.class)
大致的意思可以理解了,创建类需要通过MyEndpointConfigure.getEndpointInstance()这个来实现。
运行一切正常。
但是这种形式并不是正常的Spring容器去正常去管理这个WebSocket,个人觉得并不是很好。
这个帖子同时还给出了第二解决方法。原生的Spring实现的WebSocket的办法。
第二种解决办法:
与其说是第二种办法,不如说是Spring第二种实现WebSocket的方案。和第一种没有任何的联系。代码如下:
核心Handler,有Spring的风格。
@Component public class WsHandler extends TextWebSocketHandler { @Autowired TestInfo testInfo; @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { super.afterConnectionClosed(session, status); System.out.println("close...."); } @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { super.afterConnectionEstablished(session); System.out.println("----->"+testInfo.test()); System.out.println("建立新的会话"); } @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { System.out.println(message.getPayload()); TextMessage msg=new TextMessage(message.getPayload()); session.sendMessage(msg); } @Override public void handleMessage(WebSocketSession session, WebSocketMes bee8 sage<?> message) throws Exception { super.handleMessage(session, message); } @Override public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception { super.handleTransportError(session, exception); } }
简单实现几个关键的方法。
TestInfo 直接注入。
编写Configure类
@Configuration @EnableWebSocket public class WsConfigure implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { System.out.println("=========================="); registry.addHandler(myHandler(), "/websocket").setAllowedOrigins("*"); } @Bean public WsHandler myHandler() { return new WsHandler(); } }
这种实现方法可以查看官方文档。
https://docs.spring.io/spring/docs/4.3.13.RELEASE/spring-framework-reference/htmlsingle/#websocket
经测试可以正常工作。
个人建议采用第二种方法,因为这个是Spring自带的WebSocket的实现方式。
实现上需要花时间看看Spring是如何将WebSocket的请求进行处理。以后有时间补上这个。
相关文章推荐
- Mockito InjectMocks字段无法注入其他InjectMocks字段的解决办法
- MacBook的浏览器无法连接到服务器,其他应用可以正常使用的解决办法
- 用VS2010编写的C++程序,在其他电脑上无法运行,提示缺少mfc100.dll的解决办法 vc链接静态库的时候要注意的问题
- Ubuntu中apt-get 安装失败,导致无法安装其他软件的解决办法。
- win7网络发现不能启用,无法共享其他机器的解决办法
- "无法启动应用程序,工作组信息文件丢失,或是已被其他用户已独占方式打开"解决办法
- 用VS2010编写的C++程序,在其他电脑上无法运行,提示缺少mfc100.dll的解决办法
- 局域网中无法访问其他电脑的解决办法
- ora-12154 tns 无法处理服务名(执行的程序途径不一致导致,枚举网络数种方法,大家还有其他解决办法?)
- 关于VC编译的程序在其他电脑上无法运行的解决办法
- 用VS2010编写的C++程序,在其他电脑上无法运行,提示缺少mfc100.dll的解决办法
- 用VS2010编写的C++程序,在其他电脑上无法运行,提示缺少mfc100.dll的解决办法
- Android SDK Manager在添加Platforms和其他Packages时提示无法在相应目录创建文件夹的解决办法!
- **线程里面使用注解(线程里面spring使用注解无法注入值的解决办法)**
- "无法启动应用程序,工作组信息文件丢失,或是已被其他用户已独占方式打开"解决办法
- 安装linux,导致开机无法选择其他系统的解决办法
- [转]lenovo.com.cn 及其他联想旗下网站无法访问的解决办法
- Android SDK Manager无法下载其他版本的API 解决办法
- Qt程序发布到其他电脑上无法运行解决办法(二)