背景
之前介绍过springboot集成webstock方式,具体参考:
springboot集成websocket实战:站内消息实时推送
这里补充另外一个使用webstock的场景,方便其他同学理解和使用,废话不多说了,直接开始!简单介绍一下业务场景:
现在有一个投票活动,活动详情中会显示投票活动的参与人数、访问数、投票数。这三个投票数据需要实时的进行变化,这里就可以使用webstock进行返回页面。当三个数据发生变化时,服务端发送最新数据给客户端,客户端仅进行展示即可,不用轮询查询数据,页面也会显示动态效果。
实现步骤
1.配置webstock
@Configuration public class WebSocketConfig { @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } }
2.webstocket服务逻辑说明
每个客户端进入活动之后需要与服务端建立一个连接,由于是在微信小程序中进行发布活动,所以使用用户的openID进行用户的唯一标识,每个链接就可以看做是客户端与服务端的一次会话session,使用clients将所有登录的用户创建的session存储起来,方便后期进行消息群发操作,用户退出时将创建session进行关闭操作。投票数、访问量、参与人数,每个指标变化时需要调用webstock服务器中的群发消息功能,这样就能保证三个数据变化之后客户端可以实时显示出最新的数据,达到最终预期的效果。
3.webstocket服务代码实现
@Component @Slf4j @Service @ServerEndpoint("/ws/{openId}") public class WebSocketServer { // 每个在线用户会创建一个WebSocketServer对象 private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>(); // 存放所有在线的客户端 key为用户的唯一标识:userId,value为每个会话连接 private static Map<String, Session> clients = new ConcurrentHashMap<>(); /** * 连接建立成功调用的方法 */ @OnOpen public void onOpen(Session session, @PathParam("openId") String openId) throws IOException { log.info("dataId:{},已建立连接",openId); clients.put(openId, session); webSocketSet.add(this); } /** * 连接关闭调用的方法 */ @OnClose public void onClose(Session session,@PathParam("openId") String openId) { log.info("dataId:{},关闭连接",openId); clients.remove(openId); webSocketSet.remove(this); //从set中删除 } /** * @ Param session * @ Param error */ @OnError public void onError(Session session, Throwable error) { log.error("发生错误"); error.printStackTrace(); } /** * @Author: txm * @Description: 群发消息 * @Param: [] * @return: void * @Date: 2022/12/23 14:28 **/ public void batchSendMsg() throws IOException { VoteServiceImpl voteService = SpringUtils.getBean(VoteServiceImpl.class); // 此处是组装返回类似的参数信息:{"joinCount":15,"visitCount":169,"voteCount":36} String voteStatisticsVo = voteService.findVoteStatisticsVo(); for (Map.Entry<String, Session> integerSessionEntry : clients.entrySet()) { integerSessionEntry.getValue().getBasicRemote().sendText(voteStatisticsVo); } } }
4.业务逻辑触发说明
这里仅以增加访问量操作为例进行说明(投票数增加、参与人数增加同理,只是业务触发逻辑不同),自定义了一个增加访问量的接口,前端调用该接口则活动的访问数量会进行加一处理,webstock服务群发消息的处理就需要在这里完成,参考代码如下:
@Service @Slf4j public class VoteServiceImpl implements VoteService { @Autowired private WebSocketServer webSocketServer; public synchronized void updateVisitCount(Integer voteId) throws IOException { System.out.println("投票活动访问量增加操作"); // 服务端群发消息,更新统计数据 webSocketServer.batchSendMsg(); } }
5.客户端测试地址:http://1json.com/network/ws.html,输入项目地址.
调用更新访问量接口之后,可以看到服务端已经将最新的投票统计信息进行了返回处理:
问题说明
关于配置完成之后测试客户端不能建立连接问题
当时在测试的时候也出现过不能建立连接,分析了一下原因是项目中使用了ssl证书配置,也就是项目本身访问的方式是https访问,所以不能使用ws协议进行访问,需要使用wss协议进行访问(两者的区别可以类比理解为http与https的区别),简单说一下项目配置,没有为了适配wss单独做配置(支持https访问的项目也会支持wss访问).
配置文件:
server: port: 8083 servlet: session: timeout: PT30M ssl: enabled: true key-store: classpath:config/ssl/*****.com.pfx key-store-password: ***** keyStoreType: *****
证书路径:
说一下本地以及测试环境的访问方式:
本地访问:
wss://127.0.0.1:8083/ws/1
服务器访问(使用ip访问不通,只能使用域名):
wss://域名:8083/ws/1
以上是使用webstock实现页面数据实时刷新的实现过程,如果看完感觉有所帮助欢迎评论区留言或点赞!