消息中心组件
消息中心模块waf-message-parent,是用于定义系统中的消息接口,提供消息服务的模块,消息中心支持自定义扩展,该模块可作为独立的springboot应用,也可内嵌到主应用中。
1、消息中心扩展依赖
- 独立的springboot应用扩展
<!-- 指定waf-parent为parent,版本号为实际发布的版本-->
<parent>
<groupId>com.wiseda.waf</groupId>
<artifactId>waf-parent</artifactId>
<version>1.0.1.RELEASE</version>
</parent>
<!-- 扩展消息中心依赖,版本号不需要指定,继承parent中的版本-->
<dependency>
<groupId>com.wiseda.waf</groupId>
<artifactId>waf-message-server</artifactId>
</dependency>
- 内嵌到主应用
<!-- 内嵌只需要依赖waf-message-server,版本号不需要指定,继承parent中的版本-->
<dependency>
<groupId>com.wiseda.waf</groupId>
<artifactId>waf-message-server</artifactId>
</dependency>
2、消息配置
- 独立的springboot应用扩展
独立应用部署,一般采用restful api调用,在application yml文件的配置api地址(根据实际情况调整IP、端口)。
# 调用模块配置(如waf-framwork---> waf-proxy,则在waf-framwork的yml文件需要配置waf-message的restful地址)
waf:
api:
# 消息中心rest服务地址(本地如不需要发送可将值设置为空)
message-rest-url: http://localhost:8010/waf-message/waf
// waf-proxy 调用示例
public Boolean sendMsg(MessageSendModel sendModel,String msgType) throws Exception {
String reqUrl = String.format("%s/uniformMessage/%s/sendMsg",messageUrl,msgType);
try {
ResponseEntity<Return> response = restTemplate.exchange(reqUrl, HttpMethod.POST, getHttpEntity(sendModel), Return.class);
return JsonMapperUtil.jsonToObject(response, Boolean.class);
} catch (CustomException e) {
throw new Exception(e.getBody());
}
}
- 内嵌到主应用
以maven依赖waf-message-server后直接以service注入的方式调用,这里如果有websocket消息需要配置WebSocketConfig,参考配置
# application yaml配置
waf:
server:
# 如有websocket地址,需要添加可匿名访问(不然前端调用不通)
exclusions: /waf/websocket/messages/**
<!-- maven添加依赖-->
<!--消息中心模块-->
<dependency>
<groupId>com.wiseda.waf</groupId>
<artifactId>waf-message-server</artifactId>
</dependency>
3、统一消息发送
基础框架在waf-message-parent提供了可以独立部署或以waf-message-service内嵌的方式接入统一的消息。在实际项目中使用时,只需要继承AbstractUniformMessageSend,实现里面的initReceiveType,sendMsg接口方法即可以Service的方式注入即可使用。
3.1、接口类图结构

3.2、接口实现扩展
@Slf4j
@Service(MessageServiceConsts.DINGTALK_SERVICE)
public class DingtalkMessageSend<T> extends AbstractUniformMessageSend{
@Override
public MessageReceiveObjEnum initReceiveType() {
MessageReceiveObjEnum.THIRD_PARTY.setCode("dingtalk");
return MessageReceiveObjEnum.THIRD_PARTY;
}
@Override
public T sendMsg(MessageSendModel sendModel) {
log.info("dingtalk send msg:{}",sendModel.getData());
return (T)new Boolean(true);
}
}
@Service可以指定一个service名,不指定使用类名(类名的第一个字母转成小写,其他不变做为service名)initReceiveType设置接收类型(根据接收类型来查询实际发送的用户属性,如发送短信需要手机号、发送第三消息需要第三方系统映射的账号等)sendMsg具体执行发送的接口实现(因每种消息类型发送的方式都不同,这里根据实际的发送情况来实现)MessageReceiveObjEnum 枚举属性
| 编码 | 名称 | 描述 |
|---|---|---|
| USER | 用户ID | 用于系统内部消息 |
| MOBILE | 手机号 | 用于需要发送短信 |
| 邮件 | 用于发送邮件 | |
| THIRD_PARTY | 第三方系统 | 需要指定第三系统类型(如微信、钉钉等) |
MessageSendModel 消息发送模型
- MessageSendEnum sendType
编码 名称 描述 ALL 所有人 USER 指定用户 ORG 组织机构 发给某些部门 GROUP 用户组 发给某些用户组 - String[] objIds 与
MessageSendEnum对应,ALL时不需要传值,发送时会去封装 - boolean convertObjId 是否需要转换
objIds,为true才会根据MessageSendEnum设置的类型去转换出对应的用户模型 List<MessageUserModel>userModelListconvertObjId为true转换出来的用户对象- T data 自定义数据结构(发送时所需要的数据)
3.3、应用测试示例
参照waf-message-framework中com.wiseda.waf.message.service.UniformMessageFactoryTest

4、websocket消息推送
在发布系统公告或消息时可以通过websocket的方式实时推送消息到用户终端。
4.1、系统消息websocket流程图

4.2、流程说明
waf-message-server:消息中心应用
- 提供redis队列订阅发布,用于分布式部署时websocket消息推送。
- 提供系统消息websocket rest api服务
waf-proxy:服务代理应用
- websocket rest api服务封装,用于其他模块调用。
waf-system:系统管理应用
- 在系统通知公告或消息
发布、撤销、删除时调用waf-porxy中系统消息websocket api服务将消息推送到客户端。
- 在系统通知公告或消息
4.3、后端消息推送示例
// waf-proxy 服务方法
com.wiseda.waf.proxy.service.message.SysMessageProxyService#sendMsg
public Map sendMsg(WebSocketSysMsg sysMsg) throws Exception {
}
// waf-system 调用示例:推送websocket消息
try {
SysMessage message = this.getById(id);
MessageSendModel sendModel = new MessageSendModel();
sendModel.setSendType(MessageSendEnum.ALL.name().equals(message.getReceiveType())?MessageSendEnum.ALL:MessageSendEnum.USER);
if(MessageSendEnum.USER==sendModel.getSendType()){
sendModel.setObjIds(message.getReceiveCodes().split(","));
}
sendModel.setData(id);
TokenHolder.setToken(token);
// restful 调用 (独立部署调用方式)
messageProxyService.sendMsg(sendModel,MessageServiceConsts.WEBSOCKET_SERVICE);
// 内嵌waf-message-server调用
// messageFactory.sendMsg(sendModel,MessageServiceConsts.WEBSOCKET_SERVICE);
} catch (Exception e) {
log.warn("系统消息websocket推送失败:{}",e.getMessage());
}
4.4、前端基本使用
// 在前端只要定义一个方法,在页面监听 onmessage ,接收的消息进行处理
initWebSocket: function() {
const token = Vue.ls.get(ACCESS_TOKEN)
const wsuri = `${process.env.VUE_APP_MESSAGE_API}/websocket/messages/${token}`// ws地址
this.ws = new WebSocket(wsuri)
this.ws.onopen = () => {
console.log('WebSocket连接成功')
}
this.ws.onerror = event => {
console.log('WebSocket连接发生错误', event)
}
this.ws.onmessage = event => {
console.log(event)
var da = JSON.parse(event.data)
console.log(da)
this.msg_data.unshift(da)
}
this.ws.onclose = event => {
console.log('WebSocket连接关闭', event)
}
// 组件销毁时调用,中断websocket链接
this.over = () => {
this.ws.close()
}
},
// 也可以通过WebSocket对象来调用send发送消息,发送的消息在后端@OnMessage 注解的方法来接收
sendMsg: function() {
this.ws.send('{"code":200,"message":"发送消息!","data":"' + this.inpuVal + '"}')
}
5、项目实际应用
在基础框架中提供了waf-message-parent组件,做了一个统一消息的接口定义,实现了一个简单的消息推送服务(基于redis的队列监听实现分页式的消息实时推送),对于项目中的实际需求场景,是采用独立部署,还是内嵌到主应用来进行扩展,对于发送消息可以采用统一消息发送的接口,实现具体的发送消息,保持接口调用的一致性,方便扩展维护。
