一、需求背景
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();
}