背景
之前介绍过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实现页面数据实时刷新的实现过程,如果看完感觉有所帮助欢迎评论区留言或点赞!