您的位置:首页 > 编程语言 > Java开发

Spring Cloud/Boot WebSocket 无法注入其他类的解决办法

2017-12-12 14:17 405 查看
SpringBoot官方文档推荐实现的WebSocket的方式是添加@ServerEndpoint这个注解。我也是按照推荐实现的。

但是有问题。

我开始的写的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的请求进行处理。以后有时间补上这个。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐