[Java] 纯文本查看 复制代码 @ServerEndpoint(path = "/websocket",port = "${testWebsocketPort}",allIdleTimeSeconds = "10")
@Slf4j
public class UserWebSocket{
//redis
private static StringRedisTemplate redisTemplate;
private String uid;
private String token;
@Autowired
public void setRedisTemplate(StringRedisTemplate redisTemplate) {
UserWebSocket.redisTemplate = redisTemplate;
}
@Autowired
public void setPxUserService(PxUserService pxUserService) {
UserWebSocket.pxUserService = pxUserService;
}
//用户服务类
private static PxUserService pxUserService;
//保存所有客户连接
public static final Map<String, WsClient> clients = new ConcurrentHashMap<>();
//有新的连接进入时,对该方法进行回调 注入参数的类型:Session、HttpHeaders...
@BeforeHandshake
public void handshake(Session session, HttpHeaders headers) {
System.out.println("新链接: " +
"" + session.channel().id().asShortText() + "当前在线: " + clients.size());
//设置协议
session.setSubprotocols("stomp");
}
//当有新的WebSocket连接完成时,对该方法进行回调 注入参数的类型:Session、HttpHeaders...
@OnOpen
public void onOpen(Session session, HttpHeaders headers,@RequestParam String uid,@RequestParam String token) {
synchronized(UserWebSocket.clients){
log.info(String.format("新用户加入: uid-%s id-%s" ,uid,session.channel().id().asShortText()));
//是否登录
if(pxUserService.isLogin(uid,token)){
//判断是否已连接 已连接则移除
WsClient client1 = clients.get(uid);
if(null != client1){
client1.getSession().close();
clients.remove(uid);
}
//登录成功 写入信息
UserInfo userInfo = pxUserService.getUserInfo(uid);
WsClient client = new WsClient();
client.setSession(session);
client.setUserInfo(userInfo);
clients.put(uid,client);
this.uid = uid;
this.token = token;
}else {
//未登录
sendMsgErr("token错误",session);
session.close();
}
}
}
//当有WebSocket连接关闭时,对该方法进行回调 注入参数的类型:Session
@OnClose
public void onClose(Session session) throws IOException {
synchronized(UserWebSocket.clients){
//清理uid
removeUser(this.uid);
}
System.out.println("链接关闭: " + session.channel().id().asShortText() + "当前在线: " + clients.size());
}
//当有WebSocket抛出异常时,对该方法进行回调 注入参数的类型:Session、Throwable
@OnError
public void onError(Session session, Throwable throwable) {
synchronized(UserWebSocket.clients){
session.close();
removeUser(this.uid);
}
System.out.println("链接异常: " + session.channel().id().asShortText() + "当前在线: " + clients.size());
throwable.printStackTrace();
}
//当接收到字符串消息时,对该方法进行回调 注入参数的类型:Session、String
@OnMessage
public void onMessage(Session session, String message) {
System.out.println("消息: " + session.channel().id().asShortText() + "当前在线: " + clients.size());
System.out.println(message);
WsClient userInfo = clients.get(this.uid);
if(null != userInfo){
sendMsgOkAll(userInfo.getUserInfo().getName() + "|" + message);
}
}
//当接收到Netty的事件时,对该方法进行回调 注入参数的类型:Session、Object
@OnEvent
public void onEvent(Session session,Object evt) {
synchronized(UserWebSocket.clients){
if (evt instanceof IdleStateEvent) {
IdleStateEvent idleStateEvent = (IdleStateEvent) evt;
switch (idleStateEvent.state()) {
case READER_IDLE:
System.out.println("read idle");
break;
case WRITER_IDLE:
System.out.println("write idle");
break;
case ALL_IDLE:
System.out.println("all idle");
//如果这个会话等于存入的会话则删除 避免无用会话删除了正常的链接
WsClient client = clients.get(this.uid);
if(null != client && session.equals(client.getSession())){
clients.remove(this.uid);
}
session.close();
System.out.println("进入空闲断开链接: " + session.channel().id().asShortText() + "当前在线: " + clients.size());
break;
default:
break;
}
}
}
}
/**
* 成功消息
* @param ans
* @param session
*/
public void sendMsgOk(Object ans,Session session){
WsServerAns wsServerAns = new WsServerAns(WsResultCode.SUCCESS.getCode(), WsResultCode.SUCCESS.getMsg());
wsServerAns.setData(ans);
session.sendText(JSON.toJSONString(ans));
}
/**
* 错误消息
* @param msg
* @param session
*/
public void sendMsgErr(String msg,Session session){
WsServerAns wsServerAns = new WsServerAns(WsResultCode.ERR.getCode(), msg);
session.sendText(JSON.toJSONString(wsServerAns));
}
/**
* 广播所有用户
* @param msg
*/
public void sendMsgOkAll(String msg){
WsServerAns wsServerAns = new WsServerAns(WsResultCode.SUCCESS.getCode(), WsResultCode.SUCCESS.getMsg());
wsServerAns.setData(msg);
clients.forEach((k,v)->{
v.getSession().sendText(JSON.toJSONString(wsServerAns));
});
}
public void removeUser(String uid){
if(null != uid){
clients.remove(this.uid);
}
}
}
我尝试过 就算所有代码都加锁 也会有死链接的情况 websocket刚接触 对多线程这块很不熟 |