消息触达域是一个通用域。是一个基础组件,通过领域事件的方式将其与业务代码进行解耦。
在不同的限定上下文中,“用户”有着不同的含义。
在账户域中:用户含义表示的是“账户”;
在消息域中:用户含义表示的是“消息接收人”;
而消息实体一般有三要素:
- 发给谁;
- 发什么;(消息内容,也可以是消息事件+填充内容)
- 发送渠道;
消息实体的能力:
- 消息send();
- 消息频次处理;
代码实现
消息实体
@Data
public class Message {
/**
* 消息id
*/
private String messageId;
/**
* 消息内容(发什么)
*/
private MessageContext context;
/**
* 消息接收者(发给谁)
*/
private List<String> allNotifier;
/**
* 消息渠道(怎么发)
*/
private ChannelEnum channel;
/**
* 消息频次控制(触发时机)
*/
private Predicate<Message> trigger;
public void send() {
CustomApplicationContext.getContext()
.publishEvent(new ApplicationNotifyEvent(Lists.newArrayList(this)));
}
public enum ChannelEnum {
EMAIL, //邮件
SMS; //短信
}
@Data
private static class MessageContext {
/**
* 消息事件,选填
*/
private String event;
/**
* 标头,选填
*/
private Map<String, String> title;
/**
* 内容,必填
*/
private Map<String, String> content;
}
}
领域事件
public class ApplicationNotifyEvent extends ApplicationEvent {
private List<Message> messages;
public ApplicationNotifyEvent(List<Message> messages) {
super(messages);
this.messages = messages;
doCheckMessage(messages);
}
public List<Message> getMessages() {
return messages;
}
/**
* 校验逻辑
*/
protected void doCheckMessage(List<Message> messages) {
}
}
消息监听者(公共):
@Slf4j
@Service
public class BasicNotifyListener implements ApplicationListener<ApplicationNotifyEvent> {
@Override
public void onApplicationEvent(ApplicationNotifyEvent event) {
batchSendMsg(event);
}
protected void batchSendMsg(ApplicationNotifyEvent event) {
List<Message> messageEntities = event.getMessages();
if (CollectionUtils.isEmpty(messageEntities)) {
return;
}
messageEntities.forEach(this::sendMessageAsync);
}
public void sendMessageAsync(Message message) {
//消息频次触发控制
if (!Optional.ofNullable(message.getTrigger()).map(r -> r.test(message)).orElse(true)) {
return;
}
//todo 业务处理
}
}
工具方法
@Component
public class CustomApplicationContext<T extends ApplicationEvent> implements ApplicationContextAware {
private static ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
context = applicationContext;
}
public static ApplicationContext getContext() {
return context;
}
public static <T> void publishEventIfNotNull(T event) {
//兼容消息为null的场景
if (event == null) {
return;
}
context.publishEvent(event);
}
}
网友评论