新手小白学java的第不知道多少天
<dependency>
<groupId>org.glassfish.tyrus</groupId>
<artifactId>tyrus-server</artifactId>
<version>1.17</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
这是项目依赖 在此遇到了两个大坑:
- 前端访问socket 404
- socket中无法自动装配
基本用法
创建socket配置类
@Configuration
public class WebsocketConfig {
@Bean
public ServerEndpointExporter ServerEndpointExporter(){
return new ServerEndpointExporter();
}
}
在此我踩了一个坑,我一直以为是返回的是操作socket的那个类,这个是固定写法,直接cv即可
然后使用socket
@Component
@ServerEndpoint("/websocket") //指定socket服务器路径
public class SocketController {
@OnOpen
public void onOpen(Session session) {
//监听连接
System.out.println("连接成功");
}
@OnMessage
public void onMessage(Session session, String msg) {
// 监听消息
}
@OnClose
public void onClose(Session session) {
//监听关闭
System.out.println("连接关闭");
}
@OnError
public void onError(Session session, Throwable throwable) {
//监听发生错误
System.out.println("发生错误");
}
}
Component不能少
ServerEndpoint指定服务器路径,前端请求就是ws://127.0.0.1:80/websocket
通过session.getBasicRemote().sendObject();发送消息
基本到这就可以跑起来了 如果要使用Service或者Mapper
// 因为websocket是多实例的,每创建一个连接就会创建一个bean,而spring中,如果没有特别声明,创建的都是单实例
// 在程序启动时,容器就对此bean进行了初始化,但是之后的连接时创建的对象,是没有任何bean注入操作的
所以在socketController中做如下操作
public static ApplicationContext applicationContext; //这个是sb的启动类那返回的
public static void setApplicationContext(ApplicationContext applicationContext) {
SocketController.applicationContext = applicationContext; //在启动类将applicationcontext传入即可
}
// 启动类
ConfigurableApplicationContext run = SpringApplication.run(LianxiApplication.class, args);
SocketController.setApplicationContext(run);
//socketController
//有要使用的bean直接getBean(bean.class)获取即可使用
RecommendService recommendService = SocketController.applicationContext.getBean(RecommendService.class);
我还需要存储数据库,当时报错
javax.websocket.EncodeException: No encoder specified for object of class [class com.example.lianxi.entity.Recommend] java.lang.RuntimeException:
javax.websocket.EncodeException: No encoder specified for object of class [class com.example.lianxi.entity.Recommend]
这是因为缺少消息编码器
public class SockenEncoder implements Encoder.Text<Recommend> {//消息编码器类
@Override
public String encode(Recommend recommend) throws EncodeException { //将对象编码为字符串
return JSON.toJSONString(recommend); //返回对象的时候将通过这个方法进行序列化
}
@Override
public void init(EndpointConfig endpointConfig) { //初始化编码器
}
@Override
public void destroy() { 、、销毁编码器
}
}
要对socketcontroller进行修改
@ServerEndpoint("/websocket")改为
@ServerEndpoint(value = "/websocket", encoders = {SockenEncoder.class})
这个的意思是value指定socket路径,encoders指定编码器的文件
现在就可以愉快的玩耍了
如果需要根据不同的id发送不同的内容,可以
private static final Map<String, Session> socketMap = new HashMap<>();
put("key",session) //这样就可以了,根据key获取session,然后通过session即可发送消息
必须使用static,否则每次请求都会重置,想了好久才解决。。。