WebSocket使用

详细原理:

https://www.zhihu.com/question/20215561

简介

一种在单个 TCP 连接上进行全双工通讯的协议。
Http协议是通信只能有客户端发起,而且必须在一定时间内应答。所以要实现实时的数据展示,只能能采用轮询的方式,不断的向后台发送请求,从而浪费资源。而webSocket就是只需要发一次请求,就一直能保留。等到有数据了在返回。从而实现实时的数据展示。

在这里插入图片描述

用java代码实现

导包
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artfactId>spring-boot-starter-websocker<artfactId>
</dependency>
新建配置类
@Configuration
public class WebSocketConfig {
	
	@Bean
	public ServerEndpointExporter serverEndpointExporter() {
		return new ServerEndpointExporter();
	}
}

新建Websocket枚举类,用于前端区分数据
public enum MessageTypeEnums implements IEnum {

    /**
     * 1 状态1,2  状态2
     */
    STUTA_ONE(11, "状态1"),
    STUTA_TWO(12, "状态2");

    int code;
    String description;

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    @Override
    public Serializable getValue() {
        return null;
    }

    MessageTypeEnums(int code, String description) {
        this.code = code;
        this.description = description;
    }
}

实现类
@ServerEndpoint("/socketServer/{userId}")
@Component
@Slf4j
public class WebSocketServer {

	//我自己的实现类 需替换
    private static EmailDistributeService emailDistributeService;

    @Autowired
    public void setEmailDistributeService(EmailDistributeService emailDistributeService) {
        WebSocketServer.emailDistributeService = emailDistributeService;
    }

    /**
     * 用线程安全的CopyOnWriteArraySet来存放客户端连接的信息
     */
    private static CopyOnWriteArraySet<ClientModel> webSocketSet = new CopyOnWriteArraySet<>();

    /**
     * websocket封装的session,信息推送,就是通过它来信息推送
     */
    private Session session;

    /**
     * 用户连接时触发,我们将其添加到
     * 保存客户端连接信息的socketServers中
     *
     * @param session
     * @param userId
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("userId") String userId) {
        this.session = session;
        webSocketSet.add(new ClientModel(userId, session));
        log.info("用户:【{}】连接成功", userId);
    }


    /**
     * 连接关闭触发,通过sessionId来移除
     * socketServers中客户端连接信息
     */
    @OnClose
    public void onClose() {
        webSocketSet.forEach(client -> {
            if (client.getSession().getId().equals(session.getId())) {
                log.info("用户:【{}】断开连接", client.getUserId());
                webSocketSet.remove(client);
            }
        });
    }

    /**
     * 发生错误时触发
     *
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        webSocketSet.forEach(client -> {
            if (client.getSession().getId().equals(session.getId())) {
                webSocketSet.remove(client);
                log.error("用户:【{}】发生异常", client.getUserId());
                error.printStackTrace();
            }
        });
    }


    /**
     * 收到客户端发送信息时触发
     *
     * @param message
     */
    @OnMessage
    public void onMessage(String message) {
        ClientModel clientModel = webSocketSet.stream().filter(cl -> cl.getSession() == session)
                .collect(Collectors.toList()).get(0);
        log.info("用户:【{}】发送信息:{}", clientModel.getUserId(), message);
        if (StringUtils.isBlank(message)) {
            return;
        }
        ClientMessageModel clientMessageModel = JSON.parseObject(message, ClientMessageModel.class);
        if (clientMessageModel.getMessageType() == MessageTypeEnums.READ_PERSON_ONLINE.getCode()) {
    
            ReturnModel returnModel = emailDistributeService.pushSelectEmailMessage();
            sendMessage(JSON.toJSONString(returnModel));
        }
    }


    /**
     * 服务端向客户端推送消息
     *
     * @param message
     */
    public void sendMessage(String message) {
        if (StringUtils.isEmpty(message)) {
            return;
        }
      
        //消息示例   其中messageType代表我的枚举类的状态 ,其他都是我需要传的数据
        //{"code":1,"data":{"allCount":21,"allNotSelectedCount":19,"count":21,"messageType":12,"readCount":19,"time":"2021-06-30"}}
        webSocketSet.forEach(client -> {
            try {
                client.getSession().getBasicRemote().sendText(message);
                log.info("服务端推送给客户端消息:【{}】", client.getUserId(), message);
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    }

    /**
     * 服务端向客户端推送消息
     *
     * @param message
     */
    public void sendMessage(String message, String userId) {
        if (StringUtils.isEmpty(message)) {
            return;
        }
        webSocketSet.forEach(client -> {
            try {
                if (StringUtils.isNotBlank(userId) && client.getUserId().equals(userId)) {
                    client.getSession().getBasicRemote().sendText(message);
                    log.info("服务端推送给客户端消息:【{}】", client.getUserId(), message);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    }

    /**
     * 获取在线用户
     *
     * @return
     */
    public synchronized static List<String> getOnlineUsers() {
        List<String> onlineUsers = webSocketSet.stream()
                .map(client -> client.getUserId())
                .collect(Collectors.toList());
        return onlineUsers;
    }

}
当我们需要使用方法是只需要在目标的实现类注入
@Autowired
private WebSocketServer webSocketServer

//在目标方法内使用
void test1(){
	//我准备好的数据
	Map<String,Object>map;
	//服务端发送消息
	webSocketServer.sendMessage(JSON.toJSONString(map));
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值