当前位置: 首页 > wzjs >正文

app与微网站的区别是什么意思品牌建设成功的案例

app与微网站的区别是什么意思,品牌建设成功的案例,中铁建设集团有限公司总承包公司,国外空间网站备案Websocket 数据实时更新(消息提醒功能)异步事件发布 需求 实现一个消息提醒功能,类似CSDN中我的消息功能,这里是能实时接收到官方或其他用户给你发消息。方法 我这里采用的是 Websocket 异步事件发布,有些人是直接 W…

Websocket 数据实时更新(消息提醒功能)异步+事件发布

需求

	实现一个消息提醒功能,类似CSDN中我的消息功能,这里是能实时接收到官方或其他用户给你发消息。

在这里插入图片描述

方法

我这里采用的是 Websocket +异步+事件发布,有些人是直接 Websocket +异步,具体区别放在后面

1、创建Websocket服务端(照抄即可,具体有备注),前端通过调用/ws/message接口就可以获取连接。
MessageRealTime是我的消息实体,
配置

@Configuration
public class WebSocketConfig {@Beanpublic ServerEndpointExporter serverendpointExporter(){return new ServerEndpointExporter();}
}

创建服务端

/*** @Description WebSocket 服务端,监听地址为 /ws/message**/
@ServerEndpoint("/ws/message")
@Component
@Slf4j
public class WsServerEndPoint {// 使用线程安全的ConcurrentHashMap管理用户Sessionprivate static final Map<String, Session> sessionMap = new ConcurrentHashMap<>();/*** 客户端连接建立时触发*/@OnOpenpublic void onOpen(Session session) {String userId = AuthContext.getUserId();try {// 如果已有连接,关闭旧连接Session oldSession = sessionMap.get(userId);if (oldSession != null && oldSession.isOpen()) {oldSession.close();log.info("关闭用户 {} 的旧连接", userId);}sessionMap.put(userId, session);log.info("WebSocket 连接建立:userId={}", userId);} catch (Exception e) {log.error("WebSocket onOpen 异常,userId={}", userId, e);}}/*** 接收客户端消息时触发*/@OnMessagepublic void onMessage(String text, @PathParam("userId") String userId) {log.info("收到用户 {} 的消息:{}", userId, text);}/*** 客户端连接关闭时触发*/@OnClosepublic void onClose(Session session, @PathParam("userId") String userId) {sessionMap.remove(userId);log.info("WebSocket 连接关闭:userId={}", userId);}/*** WebSocket 发生错误时触发*/@OnErrorpublic void onError(Session session, Throwable error, @PathParam("userId") String userId) {log.error("WebSocket 出现错误,userId={}", userId, error);}/*** 向指定用户发送消息*/public void sendMsgToUser(List<MessageRealTime> messageRealTimes) throws IOException {ObjectMapper mapper = new ObjectMapper();for (MessageRealTime messageRealTime : messageRealTimes) {String toUserId = messageRealTime.getToUser();Session session = sessionMap.get(toUserId);if (session != null && session.isOpen()) {String msgStr = mapper.writeValueAsString(messageRealTime);session.getBasicRemote().sendText(msgStr);log.info("向用户 {} 发送消息:{}", toUserId, msgStr);} else {log.warn("用户 {} 的连接不存在或已关闭,无法发送消息", toUserId);}}}

MessageRealTime(消息实体)

@Data
@TableName("t_message_real_time")
@Schema(description = "实时消息实体类")
public class MessageRealTime extends BaseEntity {private static final long serialVersionUID = 1L;@TableId(value = "ID",type = IdType.ASSIGN_ID)@Schema(description = "主键ID")private String id;@TableField("TITLE")@Schema(description = "标题")private String title;@TableField("SEND_USER")@Schema(description = "发送方ID")private String sendUser;@TableField("TO_USER")@Schema(description = "接收方ID")private String toUser;@TableField("TYPE")@Schema(description = "消息类型")private String type;@TableField("CONTENT")@Schema(description = "内容")private String content;@TableField("SEND_TIME")@Schema(description = "发送时间")private LocalDateTime sendTime;@TableField("SKIP_URL")@Schema(description = "跳转URL")private String skipUrl;@TableField("IS_READ")@Schema(description = "是否已读(0未读,1已读)")private String isRead;
}

2、事件发布监听

/*** 自定义的应用事件类,继承自 Spring 的 ApplicationEvent。* 用于在应用中发布“消息推送”相关事件,携带需要推送的消息数据(messageList),* 结合 Spring 的事件监听机制(@EventListener 和 @Async),可实现业务逻辑与消息推送逻辑的解耦,* 同时实现异步消息发送,提升系统响应速度和扩展能力。*/
public class MessageSendEvent extends ApplicationEvent {private final List<MessageRealTime> messageList;public MessageSendEvent(Object source, List<MessageRealTime> messageList) {super(source);this.messageList = messageList;}public List<MessageRealTime> getMessageList() {return messageList;}
}

事件监听,监听后异步推送消息

@Slf4j
@Component
@RequiredArgsConstructor
public class MessageSendListener {private final WsServerEndPoint wsServerEndPoint;@Async@EventListenerpublic void handleMessageSendEvent(MessageSendEvent event) {try {wsServerEndPoint.sendMsgToUser(event.getMessageList());} catch (Exception e) {log.error("消息推送失败", e);}}
}

3、发送消息接口(随便写在哪都行只要你能调用,我这里写在了service实现类中)

@Service
public class MessageRealTimeServiceImpl extends ServiceImpl<MessageRealTimeMapper, MessageRealTime> implements MessageRealTimeService {@Resourceprivate ApplicationEventPublisher eventPublisher;@Overridepublic void sendMsg(List<MessageRealTime> messageRealTimes) {// 1.保存数据this.saveBatch(messageRealTimes);// 2.发布事件eventPublisher.publishEvent(messageRealTimes);}}

4、使用(直接调我们的发送消息方法接口)

messageRealTimeService.sendMsg(messageRealTimes);

5、前端对接:(这个我随便AI的不知道对不对,连接倒是没问题,其他的大家酌情参考)

  1. 建立 WebSocket 连接
const wsUrl = `ws://your-domain.com/myWs/${userId}?token=${token}`;
const socket = new WebSocket(wsUrl);

2.监听连接事件

socket.onopen = () => {console.log('WebSocket连接成功');
};socket.onerror = (err) => {console.error('WebSocket连接出错', err);
};socket.onclose = () => {console.warn('WebSocket连接已关闭');
};
  1. 接收服务端推送的消息
socket.onmessage = (event) => {const data = JSON.parse(event.data);console.log('收到消息', data);// 示例处理逻辑:弹出提醒if (data.title && data.content) {// 比如使用 Element Plus 的 ElNotificationElNotification({title: data.title,message: data.content,type: 'info',duration: 5000});}// 可根据 data.type 做不同业务跳转
};

前端接收到消息可以是重新调接口刷新局部数据或在原来数据的基础上加数据,具体做法取决于业务。

总结

到这就结束了,估计有点懵,我大致表述一下整个过程:

一、前端建立连接
当前端调用 /ws/message 接口成功建立 WebSocket 连接后,服务端即可在某些业务条件下实时推送消息给前端。

例如,在你的审核业务中,A 审核完成后需要 B 审核,那么在 A 审核完成的逻辑中,就需要调用:

messageRealTimeService.sendMsg(messageRealTimes);

来触发发送消息提醒。

二、消息发送的两大步骤

  1. 保存业务数据
    将构建好的消息实体 messageRealTimes 正常保存至数据库中。

  2. 消息推送
    通过事件发布机制触发异步推送,实现消息的实时通知。

三、为什么不用简单的 @Async 异步注解?
很多时候,我们习惯直接在 sendMsg 方法上添加 @Async 来实现异步:

@Async
public void sendMsg(List<MessageRealTime> messageList) {this.saveBatch(messageList);wsServerEndPoint.sendMsgToUser(messageList);
}

这种做法虽然可以异步执行,但存在严重缺陷:

❌ 事务失效:保存数据和推送消息都在异步线程中,事务无法生效,可能导致数据还没提交就推送消息。

❌ 数据未提交,前端查不到:前端收到通知,但访问接口时查不到数据库记录。

❌ 保存失败无法回滚:推送失败时无法让调用方感知,也无法回滚业务操作。

❌ 扩展性差:将业务保存与推送耦合,不易复用、维护和扩展。

四、推荐方案:事件发布 + 异步监听
使用 Spring 的事件机制,主线程中只负责保存业务数据和发布事件,由监听器异步处理消息推送逻辑。

五、后续扩展
后续需要添加短信通知、写日志,也可以很方便地新增监听器方法或监听器类,只需要在 MessageSendEvent 类中添加信的消息类型即可,加上handleMessageSendEvent对应的处理推送方法即可。比如:

public class MessageSendEvent extends ApplicationEvent {private final List<MessageRealTime> messageList;private final List<NoticeInfo> noticeInfos;public MessageSendEvent(Object source, List<MessageRealTime> messageList, List<NoticeInfo> noticeInfos) {super(source);this.messageList = messageList;this.noticeInfos = noticeInfos;}public List<MessageRealTime> getMessageList() {return messageList;}public List<NoticeInfo> getNoticeInfos() {return noticeInfos;}
}
@Slf4j
@Component
@RequiredArgsConstructor
public class MessageSendListener {private final WsServerEndPoint wsServerEndPoint;@Async@EventListenerpublic void handleMessageSendEvent(MessageSendEvent event) {try {wsServerEndPoint.sendMsgToUser(event.getMessageList());} catch (Exception e) {log.error("消息推送失败", e);}}@Async@EventListenerpublic void handleNoticeSendEvent(MessageSendEvent event) {try {wsServerEndPoint.sendMsgToUser(event.getNoticeInfos()); //推送方法需要重新写,改变一下接收类型即可。} catch (Exception e) {log.error("消息推送失败", e);}}
}

文章转载自:

http://FaNOh48g.dwwbt.cn
http://1om4PBb2.dwwbt.cn
http://N34M3XMd.dwwbt.cn
http://JRfvGlQd.dwwbt.cn
http://SVkoZ7mK.dwwbt.cn
http://ZMAQuFho.dwwbt.cn
http://fy7QB9KM.dwwbt.cn
http://u1ho9lTZ.dwwbt.cn
http://QzIVpVeq.dwwbt.cn
http://sPJVgFrm.dwwbt.cn
http://FkgymPBY.dwwbt.cn
http://yJvvAxyD.dwwbt.cn
http://YSFNlEzS.dwwbt.cn
http://JZBHHGz5.dwwbt.cn
http://gSQij1yA.dwwbt.cn
http://nitUtHeh.dwwbt.cn
http://ycxd2H8U.dwwbt.cn
http://uwnx9C6Z.dwwbt.cn
http://VpaYddZ4.dwwbt.cn
http://IL39SCH9.dwwbt.cn
http://TJbhzBmn.dwwbt.cn
http://hnlamc6F.dwwbt.cn
http://tMfDAJab.dwwbt.cn
http://lUHVVfhg.dwwbt.cn
http://wPFXbbGg.dwwbt.cn
http://ZiOZiCdV.dwwbt.cn
http://s562pySu.dwwbt.cn
http://JtPiONMN.dwwbt.cn
http://xgsR2eWg.dwwbt.cn
http://rqRzGiqH.dwwbt.cn
http://www.dtcms.com/wzjs/725126.html

相关文章:

  • 卓业网站建设网页制作与设计怎么设置圆角
  • 一步一步网站建设教程优化方案生物
  • 做网站 收费wordpress账户密码为空
  • 沈阳谷歌网站建设wordpress xueqiu
  • 耿马网站建设高端建站价格
  • 私人可以做org后缀网站吗宁波建设商城网站
  • 网站的工作简报怎么做河南省建设网站首页
  • 淘宝客网站怎么做seo网站上百度要怎么做
  • 南山网站设计费用手机网站制作步骤
  • 网站改版 降权网站防止镜像
  • 网站流量下滑电话销售的10个小技巧
  • 如何禁止某ip访问网站济南网站建设熊掌号
  • 如何用万网做自己的网站广东省住房和建设局网站
  • 建一个网站需要什么资料ui设计模板网站
  • 长沙专业网站设计服务自己建设网站需要什么条件
  • 河南国邦卫可生物科技有限公司网站建设怎么查询在建工程
  • 东台网站制作响应式网站建设代理
  • 网站后台系统的易用性手机网站轮播图
  • 怎么做记步数的程序到网站信息平台 网站的建设
  • 青岛网上注册公司官网外包seo服务口碑好
  • 宽带多少钱一个月网站建设seoppt
  • 周村网站建设公司网站建设的环境分析
  • 中国变装网站教你如何做女人公司的网站建设公司
  • 网站中备案与不备案的区别宁波优化推广选哪家
  • 做图片推广的网站有哪些企业如何加强互联网网站建设
  • dlink nas做网站网站建设开发企业
  • 网站开发建设交印花税吗微信官方网站下载
  • 湖南3合1网站建设价格广州建设银行招聘网站
  • 营销型网站整体优化国展做网站的公司
  • 陕西省交通建设集团公司网站商贸公司起名字大全免费