DDD實戰篇 - 消息觸達域的實現 代碼實現

消息觸達域是一個通用域。是一個基礎組件,通過領域事件的方式將其與業務代碼進行解耦。

在不同的限定上下文中,“用戶”有着不同的含義。

賬戶域中:用戶含義表示的是“賬戶”;
消息域中:用戶含義表示的是“消息接收人”;

而消息實體一般有三要素:

  1. 發給誰;
  2. 發什麼;(消息內容,也可以是消息事件+填充內容)
  3. 發送渠道;

消息實體的能力:

  1. 消息send();
  2. 消息頻次處理;

代碼實現

消息實體

@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);
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章