前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >websocket使用sendObject产生的问题

websocket使用sendObject产生的问题

作者头像
余生大大
发布2022-11-02 16:31:10
6330
发布2022-11-02 16:31:10
举报
文章被收录于专栏:余生大大余生大大

1. 问题

当在使用WebSocket服务端向客户端发送消息时使用sendObject的方式传递信息出现了以下这个错误

代码语言:javascript
复制
javax.websocket.EncodeException: No encoder specified for object of class

2. 原因

这个错误的原因是当我们使用sendObject方式传递信息时需要指定对应的编码器对传递信息进行编码,编码器的设置就在@ServerEndpoint注解上。

原先的@ServerEndpoint注解内容:

代码语言:javascript
复制
@ServerEndpoint("/api/websocket/client/{clientId}")

只设定了默认的value值,编码器需要加入encoders属性,如下:

代码语言:javascript
复制
@ServerEndpoint(value = "/api/websocket/client/{clientId}",encoders = {ServerEncoder.class})

3. 解决方案

@ServerEndpoint注解上加入指定编码器类:

代码语言:javascript
复制
@ServerEndpoint(value = "/api/websocket/client/{clientId}",encoders = {ServerEncoder.class})

encoders的属性是个数组,所以可以指定多个编码器编码器的泛型需要指定,如果发送消息的实体结构没有适合的编码器则会报上面的错误。

3.1 HashMap编码类

这是一个HashMap的编码类,将HashMap转为了序列化后的JSON字符串,核心就是encode方法,只需要返回Object序列化后的json字符串就行,这里使用的fastjson,也可以自定义其他序列化工具来进行序列化操作。

代码语言:javascript
复制
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.websocket.EncodeException;
import javax.websocket.Encoder;
import javax.websocket.EndpointConfig;
import java.util.HashMap;

/**
 * @author YUSHENGDADA
 * @title: ServerEncoder
 * @projectName v2_lab
 * @description: WebSocket编码器
 * @date 2022/8/22 0022上午 11:42
 */
public class HashMapEncoder implements Encoder.Text<HashMap> {
    private static final Logger log = LoggerFactory.getLogger(HashMapEncoder.class);

    /**
     * 这里的参数 hashMap 要和  Encoder.Text<T>保持一致
     * @param hashMap
     * @return
     * @throws EncodeException
     */
    @Override
    public String encode(HashMap hashMap) throws EncodeException {
        /*
         * 这里是重点,只需要返回Object序列化后的json字符串就行
         * 你也可以使用gosn,fastJson来序列化。
         * 这里我使用fastjson
         */
        try {
            return JSONObject.toJSONString(hashMap);
        }catch (Exception e){
            log.info("ServerEncoder编码异常:{}",e.getMessage());
        }
        return null;
    }

    @Override
    public void init(EndpointConfig endpointConfig) {
        //可忽略
    }

    @Override
    public void destroy() {
        //可忽略
    }
}
3.2 实体编码类

在应用场景中直接使用HashMap传递参数还是不太优雅不好维护,所以这里再提供一个实体编码类,消息传递实体可以固定,业务实体作为其中data数据的内容

3.2.1 消息实体
代码语言:javascript
复制
@Data
public class BaseInfoModel<T> {

    private String code;
    private String msg;
    private T data;
    
    public static <T> BaseResponseMessage success(T data) {
        BaseResponseMessage baseResponseMessage = new BaseResponseMessage();
        baseResponseMessage.code = "0";
        baseResponseMessage.msg = "成功";
        baseResponseMessage.data = data;
        return baseResponseMessage;
    }
}
3.2.2 实体编码类
代码语言:javascript
复制
import com.an.websocket.model.client.BaseResponseMessage;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.json.JsonMapper;

import javax.websocket.EncodeException;
import javax.websocket.Encoder;
import javax.websocket.EndpointConfig;

/**
 * @author YUSHENGDADA
 * @title: BaseModelEncoder
 * @projectName v2_lab
 * @description: 实体编码器
 * @date 2022/8/22 0022下午 14:15
 */
public class BaseModelEncoder  implements Encoder.Text<BaseResponseMessage> {
    @Override
    public String encode(BaseResponseMessage baseResponseMessage) throws EncodeException {
        try {
            JsonMapper jsonMapper = new JsonMapper();
            return jsonMapper.writeValueAsString(baseResponseMessage);

        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public void init(EndpointConfig endpointConfig) {

    }

    @Override
    public void destroy() {

    }
}
3.2.3 注解配置

实体跟实体编码器配置好后加入到注解的属性上,因为是数组直接HashMap的编码器后加入即可。

代码如下:

代码语言:javascript
复制
@ServerEndpoint(value = "/api/websocket/client/{clientId}",encoders = {HashMapEncoder.class, BaseModelEncoder.class})

发送消息的代码

代码语言:javascript
复制
@OnMessage
public void onMessage(String message, Session session,@PathParam("clientId") String clientId){
    UserMessageModel userMessageModel = JSONObject.parseObject(message, UserMessageModel.class);
    log.info("客户端:{} 发送到客户端:{},消息内容:{}",clientId,userMessageModel.getAcceptId(),userMessageModel.getMessage());
    webSocketClientMap.get(userMessageModel.getAcceptId()).sendMessage(BaseResponseMessage.success(userMessageModel));
}

private void  sendMessage(Object message){
    try {
        this.infoSession.getBasicRemote().sendObject(message);
    } catch (IOException e) {
        throw new RuntimeException(e);
    } catch (EncodeException e) {
        throw new RuntimeException(e);
    }
}
3.2.4 验证效果

在客户端将收到的消息打印了出来,丑了点,凑合看,结构没问题就行

在这里插入图片描述
在这里插入图片描述
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-08-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 问题
  • 2. 原因
  • 3. 解决方案
    • 3.1 HashMap编码类
      • 3.2 实体编码类
      相关产品与服务
      文件存储
      文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档