此方法用于:前端不方便使用SSE,在IM项目中应用,需要用到用户的前后端websocket连接
创建连接池服务类
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONObject;
import com.wxmblog.base.common.utils.SpringUtils;
import com.wxmblog.base.common.utils.TokenUtils;
import com.wxmblog.base.websocket.common.constant.WebSocketConstants;
import com.wxmblog.base.websocket.common.rest.response.MessageListResponse;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import javax.annotation.Resource;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@Log4j2
public class WebSocketService {
// 存连接池的map
private static final Map<Integer, ChannelHandlerContext> contextMap = new ConcurrentHashMap<>();
// redis实例化-用来存消息通知或者需要的数据
@Resource
@Qualifier
private static RedisTemplate redisTemplate = SpringUtils.getBean(RedisTemplate.class);
// 将WS连接注册到连接池
public static void registerContext(int userId, ChannelHandlerContext ctx) {
contextMap.put(userId, ctx);
}
// 通过连接池内关于相关用户的连接发到指定用户,也可以遍历所有人发送
public static void sendMessage(int userId) {
//拿到连接
ChannelHandlerContext ctx = contextMap.get(userId);
//存在发送 否则不发
if (ctx != null && ctx.channel().isActive()) {
//获取发送的消息 后面是获取信息的方法
JSONObject notice = getResponse(userId);
//发送
ctx.writeAndFlush(new TextWebSocketFrame(noticeResponse.toString()));
log.info("发送消息给user ID: {}:{}", userId,noticeResponse.toString());
} else {
log.warn("当前没有ws连接user ID: {}", userId);
}
}
// 解除注册,放在断开连接的方法里,这里我没做,因为组装userid传过来太麻烦,直接没成功就失败的原理,忽略了这里
public static void unregisterContext(int userId) {
contextMap.remove(userId);
}
}
注册连接池的服务
这里用在了请求连接处,也可以放在“第一次握手的地方”,但是一定要拿到userid这种区分标识数据,做为key
@Override
protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) {
String text = msg.text();
WebSocketMessage message = null;
ChannelUtil channelUtil = SpringUtils.getBean(ChannelUtil.class);
try {
message = JSON.parseObject(text, WebSocketMessage.class);
} catch (JSONException e) {
channelUtil.sendText(ctx.channel(), "消息格式错误 例:{\"messageType\":\"CONNECT\",\"info\":\"UserId\"}");
}
if (message != null && MessageTypeEnum.CONNECT.equals(message.getMessageType())) {
log.info("收到连接" + message.getInfo());
if (StringUtils.isNotBlank(message.getInfo())) {
// 做相关业务代码处理
// ......
// 注册连接池
WebSocketService.registerContext(userId, ctx);
}
} else if ...
使用连接池的服务
这里不做赘述了,WebSocketService.sendMessage(user_id);这样就可以放在需要使用的地方了。
如果有帮助点赞支持吧!3Q!