快速上手SpringBoot下即时通讯技术WebSocket

1.在pom.xml内引入依赖

	<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
	</dependency>

2. 编写私信处理器

@Slf4j
public class MessageHandler extends TextWebSocketHandler {

    @Resource
    private MessageDao messageDao;
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    private static final ObjectMapper MAPPER = new ObjectMapper();

    private static final Map<Long, WebSocketSession> SESSIONS = new HashMap<>();

    //用户和服务端建立连接后
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {

        Long id = BaseContext.getUserId();
        //将用户session放入map,后续会使用相应session通信
        SESSIONS.put(id, session);
    }

    //用户关闭连接后
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        Long id = BaseContext.getUserId();
        SESSIONS.remove(id);
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage textMessage) throws Exception {

        String path = session.getUri().getPath();
        String[] flag = StringUtils.split(path, "/");
        String key = LOGIN_TOKEN_KEY + flag[1];

        Long id = Long.valueOf(stringRedisTemplate.opsForValue().get(key));

        JsonNode jsonNode = MAPPER.readTree(textMessage.getPayload());
        Long toId = jsonNode.get("toId").asLong();
        String msg = jsonNode.get("msg").asText();

        Message message = Message.builder()
                .from(id)
                .to(toId)
                .msg(msg)
                .build();

        //将消息保存到mongodb
        message = messageDao.saveMessage(message);
        String messageJSON = JSONUtil.toJsonStr(message);

        //判断to用户是否在线
        WebSocketSession toSession = SESSIONS.get(toId);
        if (toSession != null && toSession.isOpen()) {
            //向to用户发送消息
            toSession.sendMessage(new TextMessage(messageJSON));
            messageDao.updateMessageStatus(message.getId(), 0);
        }
    }
}

3.编写建立连接前的拦截器

public class MessageHandshakeInterceptor implements HandshakeInterceptor {
    
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    public MessageHandshakeInterceptor(){}

    public MessageHandshakeInterceptor(StringRedisTemplate stringRedisTemplate){
        this.stringRedisTemplate = stringRedisTemplate;
    }
    
    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {

        //获取路径中的token
        String path = request.getURI().getPath();
        String[] flag = StringUtils.split(path, "/");
        if (flag.length != 2){
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return false;
        }

        //在redis查询是否存在(是否登陆)
        String key = LOGIN_TOKEN_KEY + flag[1];
        String id = stringRedisTemplate.opsForValue().get(key);
        if (StringUtils.isEmpty(id)){
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return false;
        }
        BaseContext.setMember(Long.valueOf(id));
        return true;
    }

    @Override
    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {

    }
}

4. 编写配置类

@Configuration
@EnableWebSocket
@Import(MessageHandler.class)
public class WebSocketConfig implements WebSocketConfigurer {

    @Resource
    private MessageHandler messageHandler;
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
    //注入处理器与设置访问路径
        registry.addHandler(this.messageHandler,"/ws/{token}")
                //允许跨域
                .setAllowedOrigins("*")
                .addInterceptors(new MessageHandshakeInterceptor(stringRedisTemplate));
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值