准备材料
- 一个可以测试websocket的网站:http://coolaf.com/tool/chattest
- consul(服务注册中心)
1. 搭建环境
新建spring项目的操作略过,引入依赖
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
配置文件
#微服务建议一定要写服务端口号和微服务名称
server:
#consul服务端口号
port: 8006
#服务别名----注册zookeeper到注册中心的名称
spring:
application:
#微服务名称
name: cloud-payment-service
#数据库配置
datasource:
type: com.alibaba.druid.pool.DruidDataSource
#mysql5.x的没有cj
driver-class-name: com.mysql.cj.jdbc.Driver
#记得先创建数据库
url: jdbc:mysql://localhost:3306/数据库名称?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true
username: xxxx
password: xxxxx#R7000终端密码
#consul注册中心地址
cloud:
consul:
host: localhost
port: 8500
discovery:
#hostname:127.0.0.1
service-name: ${spring.application.name}
prefer-ip-address: true
具体的实现代码:
首先是注入配置类
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter(){
return new ServerEndpointExporter();
}
}
实现类:
@Slf4j
//将目前的类定义成一个websocket服务器端,注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
@ServerEndpoint("/ws/{token}")
@Component
public class MyWebSocket {
// 定义全局变量
// 当前在线连接数
private static final AtomicInteger ONLINE_NUM = new AtomicInteger(0);
// 存放客户端对应的webSocket对象
private static ConcurrentHashMap<String, Session> SESSION_MAP = new ConcurrentHashMap<>();
//concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识
private static ConcurrentHashMap<String, Socket> webSocketSet = new ConcurrentHashMap<String, Socket>();
/**
* 连接建立
* 从请求的URL:ws://localhost:8006/ws/{token}参数里面获取标识token
*/
@OnOpen
public void onOpen(@PathParam("token") String token, Session session){
System.out.println("长连接已建立,用户:" + token);
// 存储连接session,在需要用的地方直接使用
SESSION_MAP.put(token,session);
}
/**
* 收消息
*/
@OnMessage
public void onMessage(Session session, String msg){
String[] split = session.getRequestURI().getPath().split("/");
String userName = split[2];
String outMessage = "客户端 " + session.getId() + " 说:" + msg;
System.out.println(outMessage);
String returnMessage = "你刚才说:" + msg;
SESSION_MAP.keySet().forEach(item->{
try {
SESSION_MAP.get(item).getBasicRemote().sendText("用户"+ userName + "发送:" + msg);
} catch (IOException e) {
throw new RuntimeException(e);
}
});
// session.getBasicRemote().sendText(returnMessage);
}
/**
* 连接断开
* @param token
* @param session
*/
@OnClose
public void onClose(@PathParam("token") String token, Session session){
System.out.println("长连接已断开,用户:" + token);
SESSION_MAP.remove(token);
}
/**
* 长连接出现异常
*/
@OnError
public void onError(Throwable throwable){
System.out.println("长连接出现异常:" + throwable.getMessage());
}
/**
* 后端发送消息
*/
public void sendMessage(String sessionId, String message) {
Session session = SESSION_MAP.get(sessionId);
try {
session.getBasicRemote().sendText(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.演示
首先启动注册中心,命令:
./consul agent -dev
注意上面终端命令需要在consul所在目录下执行
服务注册中心正常启动:
启动后端服务:
打开websocket测试工具网址,输入
ws://ip地址:8006/ws/用户Id
点击【连接】,显示连接成功后,即可发送消息