一、需求背景
1、本系統和其他系統進行交互,單方面交互有限制,發送測試超過限制仍未收到回覆則爲失敗。
2、發送的方式有多種。
3、發送方式與業務類型相關,如一種業務類型需要兩種及以上發送方式
4、發送指定業務消息時需要把文件copy到對應的服務器上(只成功拷貝異常)
二、概要設計
1、類圖
2、er圖
三、詳細設計
1、MessageSendFactory
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
/**
* 消息發送擴展類的實例化化工廠
* 1、注入消息發送的具體實現方式,通過code來路由
*
* @author wb-zcf274530
*
*/
public class MessageSendFactory implements ApplicationContextAware{
private ApplicationContext context;
private static Map<String, MessageSend> messageSendAnnotationsMap = new ConcurrentHashMap<String, MessageSend>();
@Autowired
private NotifyBizProcessorFactory processorFactory;
@Autowired
private BogdaNotifyTaskBo bogdaNotifyBo;
Logger logger = LoggerFactory.getLogger(MessageSendFactory.class);
private void init() {
Map<String, MessageSend> messageSendMap = this.context.getBeansOfType(MessageSend.class);
if (messageSendMap != null) {
for (MessageSend processor : messageSendMap.values()) {
NotifyType anotation = processor.getClass().getAnnotation(NotifyType.class);
if (anotation != null) {
NotifyConstantEnum[] notifyTypes = anotation.notifyTypes();
if (ArrayUtil.isNotEmpty(notifyTypes)) {
for (NotifyConstantEnum notifyType : notifyTypes) {
messageSendAnnotationsMap.put(notifyType.name(), processor);
}
}
}
}
}
}
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.context = applicationContext;
}
public void send(Long id) {
try{
BogdaNotifyTaskDo notifyTask = bogdaNotifyBo.queryNotifyTaskById(id);
if(messageSendAnnotationsMap.containsKey(notifyTask.getNotifyType())){
//TODO 在執行send前後注入對應的業務處理
processorFactory.beginAction(notifyTask);
messageSendAnnotationsMap.get(notifyTask.getNotifyType()).send(notifyTask);
processorFactory.finishAction(notifyTask);
}else{
throw new BogdaException(BogdaExceptionMessageConstants.CODE_NOTIFY_TYPE_NO_EXIST,BogdaExceptionMessageConstants.DEFAULT_MESSAGE);
}
}catch(Exception e){
//發送失敗的忽略掉,但也算是一次發送
logger.warn("MessageSendFactory.send exception,id = "+id, e);
}
}
public void setBogdaNotifyBo(BogdaNotifyTaskBo bogdaNotifyBo) {
this.bogdaNotifyBo = bogdaNotifyBo;
}
}
2、MetaQMessageSend
import java.util.UUID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@NotifyType(notifyTypes={NotifyConstantEnum.BOGDA_SEND_NOTIFY_TYPE_MQ})
public class MetaQMessageSend implements MessageSend{
@Autowired
private SenderFactory senderFactory;
@Autowired
private BogdaNotifyTaskHistoryBo bogdaNotifyTaskHistoryBo;
private String groupName;
Logger logger = LoggerFactory.getLogger(MetaQMessageSend.class);
@Override
public void send(BogdaNotifyTaskDo notifyTask) {
String key = UUID.randomUUID().toString();
try{
sendMessageToGW(notifyTask,key);
addNotifyTaskHistory(new BogdaNotifyTaskHistoryDo(key,String.valueOf(notifyTask.getBillId()),String.valueOf(notifyTask.getId()),PatentsConstants.PROPOSAL_CODE_SUCCESS,JSONObject.toJSONString(new PatentMQInfo(String.valueOf(notifyTask.getBillId())))));
}catch(Exception e){
addNotifyTaskHistory(new BogdaNotifyTaskHistoryDo(key,String.valueOf(notifyTask.getBillId()),String.valueOf(notifyTask.getId()),PatentsConstants.PROPOSAL_CODE_FAIL,JSONObject.toJSONString(new PatentMQInfo(String.valueOf(notifyTask.getBillId())))));
logger.error("MetaQSendProcessor.execute Exception,notifyTask = "+JSONObject.toJSONString(notifyTask), e);
}
}
/**
* 添加任務發送歷史記錄
* 1、type爲send
* @param notifyTaskHistory
*/
@Override
public void addNotifyTaskHistory(BogdaNotifyTaskHistoryDo notifyTaskHistory){
this.bogdaNotifyTaskHistoryBo.addBogdaNotifyTaskHistory(notifyTaskHistory);
}
/**
* 發送任務
* @param notifyTask
* @param instanceId
* @throws MQClientException
* @throws RemotingException
* @throws MQBrokerException
* @throws InterruptedException
*/
private void sendMessageToGW(BogdaNotifyTaskDo notifyTask,String key) throws Exception{
try {
MQProducerHandler mqProducerHandler = this.senderFactory.borrow(groupName, notifyTask.getTopic());
synchronized(mqProducerHandler){
mqProducerHandler.sendMessage(notifyTask.getTag(), key, JSONObject.toJSONString(new PatentMQInfo(String.valueOf(notifyTask.getBillId()))).getBytes());
}
} catch (Exception e) {
this.senderFactory.destory(groupName);
throw e;
}
}
public void setGroupName(String groupName) {
this.groupName = groupName;
}
}
3、NotifyBizProcessorFactory
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class NotifyBizProcessorFactory implements ApplicationContextAware{
private static Map<String, NotifyBizProcessor> bizProcessorAnnotationsMap = new ConcurrentHashMap<String, NotifyBizProcessor>();
private ApplicationContext applicationContext;
Logger logger = LoggerFactory.getLogger(NotifyBizProcessorFactory.class);
public void init(){
Map<String, NotifyBizProcessor> bizProcessorMap = this.applicationContext.getBeansOfType(NotifyBizProcessor.class);
if (bizProcessorMap != null) {
for (NotifyBizProcessor processor : bizProcessorMap.values()) {
NotifyType anotation = processor.getClass().getAnnotation(NotifyType.class);
if (anotation != null) {
NotifyConstantEnum[] notifyTypes = anotation.notifyTypes();
if (ArrayUtil.isNotEmpty(notifyTypes)) {
for (NotifyConstantEnum notifyType : notifyTypes) {
bizProcessorAnnotationsMap.put(notifyType.name(), processor);
}
}
}
}
}
}
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext = applicationContext;
}
public void beginAction(BogdaNotifyTaskDo notifyTask) throws Exception{
if(bizProcessorAnnotationsMap.containsKey(notifyTask.getNotifyType())){
bizProcessorAnnotationsMap.get(notifyTask.getNotifyType()).beginAction(notifyTask);
}else{
throw new BogdaException(BogdaExceptionMessageConstants.CODE_NOTIFY_TYPE_NO_EXIST,BogdaExceptionMessageConstants.DEFAULT_MESSAGE);
}
}
public void finishAction(BogdaNotifyTaskDo notifyTask) throws Exception{
if(bizProcessorAnnotationsMap.containsKey(notifyTask.getNotifyType())){
bizProcessorAnnotationsMap.get(notifyTask.getNotifyType()).finishAction(notifyTask);
}else{
throw new BogdaException(BogdaExceptionMessageConstants.CODE_NOTIFY_TYPE_NO_EXIST,BogdaExceptionMessageConstants.DEFAULT_MESSAGE);
}
}
}
4、MessageSend
package com.alibaba.bogda.commonservice.send;
import com.alibaba.bogda.dal.intellprop.BogdaNotifyTaskDo;
import com.alibaba.bogda.dal.intellprop.BogdaNotifyTaskHistoryDo;
/**
* 消息發送基礎類
* 1、擴展發送任務表中的具體發送方式
* @author wb-zcf274530
*
*/
public interface MessageSend {
/**
* 發送記錄
* @param notifyTask
*/
public void send(BogdaNotifyTaskDo notifyTask);
/**
* 記錄發送歷史
* @param notifyTaskHistory
*/
public void addNotifyTaskHistory(BogdaNotifyTaskHistoryDo notifyTaskHistory);
}
5、NotifyBizProcessor
public interface NotifyBizProcessor {
/**
* 在引擎操作之前執行業務方法
*/
public void beginAction(BogdaNotifyTaskDo notifyTask) throws Exception;
/**
* 在引擎操作之後執行業務方法
*
* @throws WorkFlowException
*/
public void finishAction(BogdaNotifyTaskDo notifyTask) throws Exception;
}
6、NotifyType
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface NotifyType {
/**
* 對應的任務類型
*
* @return
*/
NotifyConstantEnum[] notifyTypes();
}