WebSocket踩过的坑

一:传参:

正常情况下,websocket可以接收路径参数和文本参数(当然也可以接收字节数据),

    @OnMessage
    public void onMessage(String message, Session session, @PathParam("username") String username) {
        log.info("接收到:{}", message + ":" + username);
        session.getAsyncRemote().sendText("hi:" + username + ", " + "copy:" + message);


    }

websocket不支持直接接收实体类,启动时就会报错No decoder was found for message parameters present on the method [onMessage] of class that was annotated with OnMessage,也不支持直接响应实体类,测试时会发现前端无法接收到,是因为websocket需要实现它自己的encoder和decoder接口,才能正常序列化和反序列化;

当然也可以不实现encoder和decoder接口,接收时直接接收json字符串,然后手动反序列化,输出时也手动序列化以字符串形式响应。

二:WebSocket不是单例模式
@ServerEndpoint(value = "/ws/agg/orderAgg")
@Component
@Slf4j
public class OrderAggWebSocketServer {

    private static InspectResultService inspectResultService;

    //@Autowired
    //private RedisTemplate<String, String> redisTemplate;


    @Autowired
    public OrderAggWebSocketServer(InspectResultService inspectResultService) {
        OrderAggWebSocketServer.inspectResultService = inspectResultService;
    }

    public OrderAggWebSocketServer() {
    }
}

如上,虽然我使用的springboot框架,且上面添加了@Component注解,但是WebSocket并不是单例模式。每一个ws连接都会创建一个ws对象,所以当接口中有依赖其他bean时,不能直接使用@Autowired自动注入,而是将依赖的bean声明为静态属性,然后使用构造器注入才能正常注入。

三:websocket请求头固定的key

在websocket请求中我们想自定义请求头然后添加参数,在使用postman测试时完全正常:如下:

我自定义了Authorization请求头字段,传入token进行校验,测试时正常,但是前端联调时不行。

原因:一般情况下,ws请求自定义请求数据只能添加到key为Sec-WebSocket-Protocol的属性下面,且请求中请求头有什么数据,响应时必须同传回客户端,否则接口异常,正确示例如下:

 四:WS接口鉴权:

服务中http请求鉴权是家常便饭了,但是ws接口略有不同,但是也比较简单:在过滤器中,只需要区分出http和ws类型请求,ws类型请求从固定的请求头中获取token然后正常鉴权即可,只是要注意在对请求头参数鉴权和响应时注意上述第三节即可。

区分http和ws接口方法如下:

    private boolean isWebSocket(HttpServletRequest request) {
        String upgrade = request.getHeader("Upgrade");
        return "websocket".equals(upgrade);
    }

 对于ws接口取出token进行,并将请求头信息放在响应头中。

        if (isWebSocket(request)) {
            String wsToken = request.getHeader("Sec-WebSocket-Protocol");
            if (!StringUtils.hasText(wsToken)) {
                return;
            } else {
                response.addHeader("Sec-WebSocket-Protocol", wsToken);
                if (authenticateWS(wsToken, method, uri)) {
                    filterChain.doFilter(request, response);
                    return;
                }
            }
            return;
        }
  • 8
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值