接入层(api)代码架构实现(责任链模式)

master
3y 4 years ago
parent 7c1feb607d
commit 0de73b0da1

@ -54,6 +54,7 @@ austin项目**核心流程**`austin-api`接收到发送消息请求,直接
- 接入腾讯云渠道发送一条短信 - 接入腾讯云渠道发送一条短信
- 使用SpringData JPA将短信发送记录存储至MySQL - 使用SpringData JPA将短信发送记录存储至MySQL
- 完成对Kafka接入 - 完成对Kafka接入
- 接入层(api)代码架构实现(责任链模式)

@ -0,0 +1,15 @@
package com.java3y.austin.constant;
/**
*
*/
public class AustinConstant {
/**
* boolean
*/
public final static Integer TRUE = 1;
public final static Integer FALSE = 0;
}

@ -1,5 +1,6 @@
package com.java3y.austin.pojo; package com.java3y.austin.domain;
import com.java3y.austin.dto.ContentModel;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Builder; import lombok.Builder;
import lombok.Data; import lombok.Data;
@ -9,6 +10,7 @@ import java.util.Set;
/** /**
* *
*
* @author 3y * @author 3y
*/ */
@Data @Data
@ -24,6 +26,7 @@ public class TaskInfo {
/** /**
* Id(使) * Id(使)
*
*/ */
private Long businessId; private Long businessId;
@ -53,9 +56,12 @@ public class TaskInfo {
private Integer msgType; private Integer msgType;
/** /**
* *
* message_templatecontentJSON()
* (pushimg)
* ContentModel
*/ */
private String content; private ContentModel contentModel;
/** /**
* .. * ..

@ -0,0 +1,8 @@
package com.java3y.austin.dto;
/**
*
* ()
*/
public class ContentModel {
}

@ -0,0 +1,6 @@
package com.java3y.austin.dto;
public class EmailContentModel extends ContentModel {
}

@ -0,0 +1,6 @@
package com.java3y.austin.dto;
public class ImContentModel extends ContentModel {
}

@ -0,0 +1,5 @@
package com.java3y.austin.dto;
public class MiniProgramContentModel extends ContentModel {
}

@ -0,0 +1,5 @@
package com.java3y.austin.dto;
public class OfficialAccountsContentModel extends ContentModel {
}

@ -0,0 +1,5 @@
package com.java3y.austin.dto;
public class PushContentModel extends ContentModel {
}

@ -0,0 +1,31 @@
package com.java3y.austin.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author 3y
* <p>
*
*
* urlcontent
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class SmsContentModel extends ContentModel {
/**
*
*/
private String content;
/**
*
*/
private String url;
}

@ -1,6 +1,7 @@
package com.java3y.austin.enums; package com.java3y.austin.enums;
import com.java3y.austin.dto.*;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import lombok.ToString; import lombok.ToString;
@ -12,16 +13,26 @@ import lombok.ToString;
@ToString @ToString
@AllArgsConstructor @AllArgsConstructor
public enum ChannelType { public enum ChannelType {
IM(10, "IM(站内信)"), IM(10, "IM(站内信)", ImContentModel.class),
PUSH(20, "push(通知栏)"), PUSH(20, "push(通知栏)", PushContentModel.class),
SMS(30, "sms(短信)"), SMS(30, "sms(短信)", SmsContentModel.class),
EMAIL(40, "email(邮件)"), EMAIL(40, "email(邮件)", EmailContentModel.class),
OFFICIAL_ACCOUNT(50, "OfficialAccounts(服务号)"), OFFICIAL_ACCOUNT(50, "OfficialAccounts(服务号)", OfficialAccountsContentModel.class),
MINI_PROGRAM(60, "miniProgram(小程序)") MINI_PROGRAM(60, "miniProgram(小程序)", MiniProgramContentModel.class),
; ;
private Integer code; private Integer code;
private String description; private String description;
private Class contentModelClass;
public static Class getChanelModelClassByCode(Integer code) {
ChannelType[] values = values();
for (ChannelType value : values) {
if (value.getCode().equals(code)) {
return value.getContentModelClass();
}
}
return null;
}
} }

@ -12,7 +12,7 @@ import lombok.ToString;
@ToString @ToString
@AllArgsConstructor @AllArgsConstructor
public enum IdType { public enum IdType {
USER_ID(10, "userid"), USER_ID(10, "userId"),
DID(20, "did"), DID(20, "did"),
PHONE(30, "phone"), PHONE(30, "phone"),
OPEN_ID(40, "openId"), OPEN_ID(40, "openId"),

@ -1,4 +1,4 @@
package com.java3y.austin.constant; package com.java3y.austin.enums;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
@ -24,7 +24,8 @@ public enum RespStatusEnum {
/** /**
* *
*/ */
CLIENT_BAD_PARAMETERS("A0100", "客户端参数错误"), CLIENT_BAD_PARAMETERS("A0001", "客户端参数错误"),
TEMPLATE_NOT_FOUND("A0002", "找不到模板或模板已被删除"),
/** /**
* *
@ -41,6 +42,8 @@ public enum RespStatusEnum {
PROCESS_TEMPLATE_IS_NULL("P0003","流程模板配置为空"), PROCESS_TEMPLATE_IS_NULL("P0003","流程模板配置为空"),
PROCESS_LIST_IS_NULL("P0004","业务处理器配置为空" ), PROCESS_LIST_IS_NULL("P0004","业务处理器配置为空" ),
; ;
/** /**

@ -1,6 +1,6 @@
package com.java3y.austin.vo; package com.java3y.austin.vo;
import com.java3y.austin.constant.RespStatusEnum; import com.java3y.austin.enums.RespStatusEnum;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;

@ -0,0 +1,40 @@
package com.java3y.austin;
import com.alibaba.fastjson.JSON;
import com.java3y.austin.config.TaskInfoParseConfig;
import com.java3y.austin.domain.TaskInfo;
import com.java3y.austin.handler.SmsHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Optional;
/**
* @author 3y
* MQ
*/
@Component
@Slf4j
public class Receiver {
@Autowired
private SmsHandler smsHandler;
@KafkaListener(topics = {"austin"}, groupId = "sms")
public void consumer(ConsumerRecord<?, String> consumerRecord) {
Optional<String> kafkaMessage = Optional.ofNullable(consumerRecord.value());
if (kafkaMessage.isPresent()) {
List<TaskInfo> lists = JSON.parseArray(kafkaMessage.get(), TaskInfo.class);
for (TaskInfo taskInfo : lists) {
smsHandler.doHandler(taskInfo);
}
log.info("receiver message:{}", JSON.toJSONString(lists));
}
}
}

@ -1,4 +1,4 @@
package com.java3y.austin.pojo; package com.java3y.austin.domain;
import lombok.Builder; import lombok.Builder;
import lombok.Data; import lombok.Data;

@ -1,7 +1,6 @@
package com.java3y.austin.handler; package com.java3y.austin.handler;
import com.java3y.austin.domain.MessageTemplate; import com.java3y.austin.domain.TaskInfo;
import com.java3y.austin.pojo.TaskInfo;
public interface Handler { public interface Handler {

@ -1,11 +1,13 @@
package com.java3y.austin.handler; package com.java3y.austin.handler;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.java3y.austin.dao.SmsRecordDao; import com.java3y.austin.dao.SmsRecordDao;
import com.java3y.austin.domain.MessageTemplate;
import com.java3y.austin.domain.SmsRecord; import com.java3y.austin.domain.SmsRecord;
import com.java3y.austin.pojo.SmsParam; import com.java3y.austin.domain.SmsParam;
import com.java3y.austin.pojo.TaskInfo; import com.java3y.austin.domain.TaskInfo;
import com.java3y.austin.dto.ContentModel;
import com.java3y.austin.dto.SmsContentModel;
import com.java3y.austin.script.SmsScript; import com.java3y.austin.script.SmsScript;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -28,9 +30,18 @@ public class SmsHandler implements Handler {
@Override @Override
public boolean doHandler(TaskInfo taskInfo) { public boolean doHandler(TaskInfo taskInfo) {
SmsContentModel smsContentModel = (SmsContentModel) taskInfo.getContentModel();
String resultContent;
if (StrUtil.isNotBlank(smsContentModel.getUrl())) {
resultContent = smsContentModel.getContent() + " " + smsContentModel.getUrl();
} else {
resultContent = smsContentModel.getContent();
}
SmsParam smsParam = SmsParam.builder() SmsParam smsParam = SmsParam.builder()
.phones(taskInfo.getReceiver()) .phones(taskInfo.getReceiver())
.content(taskInfo.getContent()) .content(resultContent)
.messageTemplateId(taskInfo.getMessageTemplateId()) .messageTemplateId(taskInfo.getMessageTemplateId())
.supplierId(10) .supplierId(10)
.supplierName("腾讯云通知类消息渠道").build(); .supplierName("腾讯云通知类消息渠道").build();

@ -1,7 +1,7 @@
package com.java3y.austin.script; package com.java3y.austin.script;
import com.java3y.austin.domain.SmsRecord; import com.java3y.austin.domain.SmsRecord;
import com.java3y.austin.pojo.SmsParam; import com.java3y.austin.domain.SmsParam;
import java.util.List; import java.util.List;

@ -3,12 +3,11 @@ package com.java3y.austin.script;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;
import com.java3y.austin.domain.SmsRecord; import com.java3y.austin.domain.SmsRecord;
import com.java3y.austin.enums.SmsStatus; import com.java3y.austin.enums.SmsStatus;
import com.java3y.austin.pojo.SmsParam; import com.java3y.austin.domain.SmsParam;
import com.tencentcloudapi.common.Credential; import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException; import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile; import com.tencentcloudapi.common.profile.ClientProfile;
@ -73,7 +72,7 @@ public class TencentSmsScript implements SmsScript {
return assembleSmsRecord(smsParam,response); return assembleSmsRecord(smsParam,response);
} catch (TencentCloudSDKException e) { } catch (Exception e) {
log.error("send tencent sms fail!{},params:{}", log.error("send tencent sms fail!{},params:{}",
Throwables.getStackTraceAsString(e), JSON.toJSONString(smsParam)); Throwables.getStackTraceAsString(e), JSON.toJSONString(smsParam));
return null; return null;

@ -1,17 +1,131 @@
package com.java3y.austin.action; package com.java3y.austin.action;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Throwables;
import com.java3y.austin.constant.AustinConstant;
import com.java3y.austin.dto.ContentModel;
import com.java3y.austin.dto.SmsContentModel;
import com.java3y.austin.enums.ChannelType;
import com.java3y.austin.enums.RespStatusEnum;
import com.java3y.austin.dao.MessageTemplateDao;
import com.java3y.austin.domain.MessageParam;
import com.java3y.austin.domain.MessageTemplate;
import com.java3y.austin.domain.SendTaskModel;
import com.java3y.austin.pipeline.BusinessProcess; import com.java3y.austin.pipeline.BusinessProcess;
import com.java3y.austin.pipeline.ProcessContext; import com.java3y.austin.pipeline.ProcessContext;
import com.java3y.austin.domain.TaskInfo;
import com.java3y.austin.utils.ContentHolderUtil;
import com.java3y.austin.utils.TaskInfoUtils;
import com.java3y.austin.vo.BasicResultVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import java.lang.reflect.Field;
import java.util.*;
/** /**
* @author 3y * @author 3y
* @date 2021/11/22 * @date 2021/11/22
* @description * @description
*/ */
@Slf4j
public class AssembleAction implements BusinessProcess { public class AssembleAction implements BusinessProcess {
@Autowired
private MessageTemplateDao messageTemplateDao;
@Override @Override
public void process(ProcessContext context) { public void process(ProcessContext context) {
SendTaskModel sendTaskModel = (SendTaskModel) context.getProcessModel();
Long messageTemplateId = sendTaskModel.getMessageTemplateId();
try {
Optional<MessageTemplate> messageTemplate = messageTemplateDao.findById(messageTemplateId);
if (!messageTemplate.isPresent() || messageTemplate.get().getIsDeleted().equals(AustinConstant.TRUE)) {
context.setNeedBreak(true).setResponse(BasicResultVO.fail(RespStatusEnum.TEMPLATE_NOT_FOUND));
return;
}
List<TaskInfo> taskInfos = assembleTaskInfo(sendTaskModel, messageTemplate.get());
sendTaskModel.setTaskInfo(taskInfos);
} catch (Exception e) {
context.setNeedBreak(true).setResponse(BasicResultVO.fail(RespStatusEnum.SERVICE_ERROR));
log.error("assemble task fail! templateId:{}, e:{}", messageTemplateId, Throwables.getStackTraceAsString(e));
}
}
/**
* TaskInfo
*
* @param sendTaskModel
* @param messageTemplate
*/
private List<TaskInfo> assembleTaskInfo(SendTaskModel sendTaskModel, MessageTemplate messageTemplate) {
List<MessageParam> messageParamList = sendTaskModel.getMessageParamList();
List<TaskInfo> taskInfoList = new ArrayList<>();
for (MessageParam messageParam : messageParamList) {
TaskInfo taskInfo = TaskInfo.builder()
.messageTemplateId(messageTemplate.getId())
.businessId(TaskInfoUtils.generateBusinessId(messageTemplate.getId(), messageTemplate.getTemplateType()))
.receiver(new HashSet<>(Arrays.asList(messageParam.getReceiver().split(String.valueOf(StrUtil.C_COMMA)))))
.idType(messageTemplate.getIdType())
.sendChannel(messageTemplate.getSendChannel())
.templateType(messageTemplate.getTemplateType())
.msgType(messageTemplate.getMsgType())
.sendAccount(messageTemplate.getSendAccount())
.contentModel(getContentModelValue(messageTemplate, messageParam))
.deduplicationTime(messageTemplate.getDeduplicationTime())
.isNightShield(messageTemplate.getIsNightShield()).build();
taskInfoList.add(taskInfo);
}
return taskInfoList;
}
/**
* contentModel,
*/
private static ContentModel getContentModelValue(MessageTemplate messageTemplate, MessageParam messageParam) {
Integer sendChannel = messageTemplate.getSendChannel();
Map<String, String> variables = messageParam.getVariables();
JSONObject jsonObject = JSON.parseObject(messageTemplate.getMsgContent());
Class contentModelClass = ChannelType.getChanelModelClassByCode(sendChannel);
/**
*
*/
Field[] fields = ReflectUtil.getFields(contentModelClass);
ContentModel contentModel = (ContentModel) ReflectUtil.newInstance(contentModelClass);
for (Field field : fields) {
String originValue = jsonObject.getString(field.getName());
if (StrUtil.isNotBlank(originValue)) {
String resultValue = ContentHolderUtil.replacePlaceHolder(originValue, variables);
ReflectUtil.setFieldValue(contentModel, field, resultValue);
}
}
return contentModel;
}
public static void main(String[] args) {
MessageTemplate messageTemplate = MessageTemplate.builder().sendChannel(ChannelType.SMS.getCode()).msgContent("{\"url\":\"www.baidu.com/{$urlParam}\",\"content\":\"{$contentValue}\"}").build();
HashMap<String, String> map = new HashMap<>();
map.put("urlParam", "2222");
map.put("contentValue", "3333");
MessageParam messageParam = new MessageParam().setVariables(map);
ContentModel contentModelValue = getContentModelValue(messageTemplate, messageParam);
System.out.println(JSON.toJSONString(contentModelValue));
} }
} }

@ -1,17 +0,0 @@
package com.java3y.austin.action;
import com.java3y.austin.domain.SendTaskModel;
import com.java3y.austin.pipeline.BusinessProcess;
import com.java3y.austin.pipeline.ProcessContext;
/**
* @author 3y
* @date 2021/11/22
* @description
*/
public class ParamAction implements BusinessProcess {
@Override
public void process(ProcessContext context) {
SendTaskModel sendTaskModel = (SendTaskModel) context.getProcessModel();
}
}

@ -0,0 +1,34 @@
package com.java3y.austin.action;
import cn.hutool.core.collection.CollUtil;
import com.java3y.austin.enums.RespStatusEnum;
import com.java3y.austin.domain.MessageParam;
import com.java3y.austin.domain.SendTaskModel;
import com.java3y.austin.pipeline.BusinessProcess;
import com.java3y.austin.pipeline.ProcessContext;
import com.java3y.austin.vo.BasicResultVO;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
/**
* @author 3y
* @date 2021/11/22
* @description
*/
@Slf4j
public class PreParamAction implements BusinessProcess {
@Override
public void process(ProcessContext context) {
SendTaskModel sendTaskModel = (SendTaskModel) context.getProcessModel();
Long messageTemplateId = sendTaskModel.getMessageTemplateId();
List<MessageParam> messageParamList = sendTaskModel.getMessageParamList();
if (messageTemplateId == null || CollUtil.isEmpty(messageParamList)) {
context.setNeedBreak(true);
context.setResponse(BasicResultVO.fail(RespStatusEnum.CLIENT_BAD_PARAMETERS));
}
}
}

@ -0,0 +1,42 @@
package com.java3y.austin.action;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.google.common.base.Throwables;
import com.java3y.austin.domain.SendTaskModel;
import com.java3y.austin.domain.TaskInfo;
import com.java3y.austin.enums.RespStatusEnum;
import com.java3y.austin.pipeline.BusinessProcess;
import com.java3y.austin.pipeline.ProcessContext;
import com.java3y.austin.pipeline.ProcessModel;
import com.java3y.austin.vo.BasicResultVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.kafka.core.KafkaTemplate;
/**
* @author 3y
* MQ
*/
@Slf4j
public class SendMqAction implements BusinessProcess {
@Autowired
private KafkaTemplate kafkaTemplate;
@Value("${austin.topic.name}")
private String topicName;
@Override
public void process(ProcessContext context) {
SendTaskModel sendTaskModel = (SendTaskModel) context.getProcessModel();
try {
kafkaTemplate.send(topicName, JSON.toJSONString(sendTaskModel.getTaskInfo(),
new SerializerFeature[] {SerializerFeature.WriteClassName}));
} catch (Exception e) {
context.setNeedBreak(true).setResponse(BasicResultVO.fail(RespStatusEnum.SERVICE_ERROR));
log.error("send kafka fail! e:{}", Throwables.getStackTraceAsString(e));
}
}
}

@ -0,0 +1,84 @@
package com.java3y.austin.config;
import com.java3y.austin.action.AssembleAction;
import com.java3y.austin.action.PreParamAction;
import com.java3y.austin.action.SendMqAction;
import com.java3y.austin.enums.BusinessCode;
import com.java3y.austin.pipeline.BusinessProcess;
import com.java3y.austin.pipeline.ProcessController;
import com.java3y.austin.pipeline.ProcessTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class PipelineConfig {
/**
*
* 1.
* 2.
* 3. MQ
* @return
*/
@Bean("commonSendTemplate")
public ProcessTemplate commonSendTemplate() {
ProcessTemplate processTemplate = new ProcessTemplate();
ArrayList<BusinessProcess> processList = new ArrayList<>();
processList.add(preParamAction());
processList.add(assembleAction());
processList.add(sendMqAction());
processTemplate.setProcessList(processList);
return processTemplate;
}
/**
* pipeline
*
* BusinessCodeProcessTemplate
* @return
*/
@Bean
public ProcessController processController() {
ProcessController processController = new ProcessController();
Map<String, ProcessTemplate> templateConfig = new HashMap<>();
templateConfig.put(BusinessCode.COMMON_SEND.getCode(), commonSendTemplate());
processController.setTemplateConfig(templateConfig);
return processController;
}
/**
* Action
* @return
*/
@Bean
public AssembleAction assembleAction() {
return new AssembleAction();
}
/**
* Action
* @return
*/
@Bean
public PreParamAction preParamAction() {
return new PreParamAction();
}
/**
* MQAction
* @return
*/
@Bean
public SendMqAction sendMqAction() {
return new SendMqAction();
}
}

@ -1,12 +1,10 @@
package com.java3y.austin.domain; package com.java3y.austin.domain;
import com.java3y.austin.pipeline.ProcessModel; import com.java3y.austin.pipeline.ProcessModel;
import com.java3y.austin.pojo.TaskInfo;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Builder; import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.util.List; import java.util.List;
@ -21,27 +19,20 @@ import java.util.List;
@Builder @Builder
public class SendTaskModel implements ProcessModel { public class SendTaskModel implements ProcessModel {
/** /**
* 10:single 20:batch * Id
*/ */
private int requestType; private Long messageTemplateId;
/** /**
* single *
*/
private MessageParam messageParam;
/**
* batch
*/ */
private List<MessageParam> messageParamList; private List<MessageParam> messageParamList;
/** /**
* *
*/ */
private TaskInfo taskInfo; private List<TaskInfo> taskInfo;
} }

@ -4,14 +4,14 @@ import com.java3y.austin.domain.BatchSendRequest;
import com.java3y.austin.domain.SendRequest; import com.java3y.austin.domain.SendRequest;
import com.java3y.austin.domain.SendResponse; import com.java3y.austin.domain.SendResponse;
import com.java3y.austin.domain.SendTaskModel; import com.java3y.austin.domain.SendTaskModel;
import com.java3y.austin.enums.RequestType;
import com.java3y.austin.pipeline.ProcessContext; import com.java3y.austin.pipeline.ProcessContext;
import com.java3y.austin.pipeline.ProcessController; import com.java3y.austin.pipeline.ProcessController;
import com.java3y.austin.pojo.TaskInfo;
import com.java3y.austin.vo.BasicResultVO; import com.java3y.austin.vo.BasicResultVO;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.Arrays;
/** /**
* *
* @author 3y * @author 3y
@ -26,14 +26,15 @@ public class SendServiceImpl implements SendService {
public SendResponse send(SendRequest sendRequest) { public SendResponse send(SendRequest sendRequest) {
SendTaskModel sendTaskModel = SendTaskModel.builder() SendTaskModel sendTaskModel = SendTaskModel.builder()
.requestType(RequestType.SINGLE.getCode()) .messageTemplateId(sendRequest.getMessageTemplateId())
.messageParam(sendRequest.getMessageParam()) .messageParamList(Arrays.asList(sendRequest.getMessageParam()))
.taskInfo(TaskInfo.builder().messageTemplateId(sendRequest.getMessageTemplateId()).build())
.build(); .build();
ProcessContext context = ProcessContext.builder() ProcessContext context = ProcessContext.builder()
.code(sendRequest.getCode()) .code(sendRequest.getCode())
.processModel(sendTaskModel).build(); .processModel(sendTaskModel)
.needBreak(false)
.response(BasicResultVO.success()).build();
ProcessContext process = processController.process(context); ProcessContext process = processController.process(context);
@ -43,14 +44,15 @@ public class SendServiceImpl implements SendService {
@Override @Override
public SendResponse batchSend(BatchSendRequest batchSendRequest) { public SendResponse batchSend(BatchSendRequest batchSendRequest) {
SendTaskModel sendTaskModel = SendTaskModel.builder() SendTaskModel sendTaskModel = SendTaskModel.builder()
.requestType(RequestType.BATCH.getCode()) .messageTemplateId(batchSendRequest.getMessageTemplateId())
.messageParamList(batchSendRequest.getMessageParamList()) .messageParamList(batchSendRequest.getMessageParamList())
.taskInfo(TaskInfo.builder().messageTemplateId(batchSendRequest.getMessageTemplateId()).build())
.build(); .build();
ProcessContext context = ProcessContext.builder() ProcessContext context = ProcessContext.builder()
.code(batchSendRequest.getCode()) .code(batchSendRequest.getCode())
.processModel(sendTaskModel).build(); .processModel(sendTaskModel)
.needBreak(false)
.response(BasicResultVO.success()).build();
ProcessContext process = processController.process(context); ProcessContext process = processController.process(context);

@ -18,18 +18,21 @@ public class BatchSendRequest {
/** /**
* *
* , BusinessCode
*/ */
private String code; private String code;
/** /**
* Id * Id
*
*/ */
private Long messageTemplateId; private Long messageTemplateId;
/** /**
* *
*
*/ */
private List<MessageParam> messageParamList; private List<MessageParam> messageParamList;

@ -16,16 +16,19 @@ public class MessageParam {
/** /**
* @Description: * @Description:
* , * ,
*
*/ */
private String receiver; private String receiver;
/** /**
* @Description: * @Description:
*
*/ */
private Map<String, String> variables; private Map<String, String> variables;
/** /**
* @Description: * @Description:
*
*/ */
private Map<String,String> extra; private Map<String,String> extra;
} }

@ -15,7 +15,7 @@ public enum BusinessCode {
COMMON_SEND("send", "普通发送"), COMMON_SEND("send", "普通发送"),
RECALL_SEND("recall", "撤回消息"); RECALL("recall", "撤回消息");
/** code 关联着责任链的模板 */ /** code 关联着责任链的模板 */

@ -52,6 +52,11 @@
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId> <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
</dependencies> </dependencies>
</project> </project>

@ -5,15 +5,18 @@ import lombok.AllArgsConstructor;
import lombok.Builder; import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
/** /**
* *
*
* @author 3y * @author 3y
*/ */
@Data @Data
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
@Builder @Builder
@Accessors(chain = true)
public class ProcessContext { public class ProcessContext {
/** /**
@ -29,11 +32,11 @@ public class ProcessContext {
/** /**
* *
*/ */
private Boolean needBreak = false; private Boolean needBreak;
/** /**
* *
*/ */
BasicResultVO response = BasicResultVO.success(); BasicResultVO response;
} }

@ -3,9 +3,11 @@ package com.java3y.austin.pipeline;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.java3y.austin.constant.RespStatusEnum; import com.java3y.austin.enums.RespStatusEnum;
import com.java3y.austin.vo.BasicResultVO; import com.java3y.austin.vo.BasicResultVO;
import lombok.Data;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.Nullable;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -16,6 +18,7 @@ import java.util.Map;
* @author 3y * @author 3y
*/ */
@Slf4j @Slf4j
@Data
public class ProcessController { public class ProcessController {
/** /**
@ -32,49 +35,57 @@ public class ProcessController {
*/ */
public ProcessContext process(ProcessContext context) { public ProcessContext process(ProcessContext context) {
/**
*
*/
if (!preCheck(context)) {
return context;
}
/**
*
*/
List<BusinessProcess> processList = templateConfig.get(context.getCode()).getProcessList();
for (BusinessProcess businessProcess : processList) {
businessProcess.process(context);
if (context.getNeedBreak()) {
break;
}
}
return context;
}
private Boolean preCheck(ProcessContext context) {
// 上下文 // 上下文
if (context == null) { if (context == null) {
context.setResponse(BasicResultVO.fail(RespStatusEnum.CONTEXT_IS_NULL)); context.setResponse(BasicResultVO.fail(RespStatusEnum.CONTEXT_IS_NULL));
return context; return false;
} }
//业务代码 // 业务代码
String businessCode = context.getCode(); String businessCode = context.getCode();
if (StrUtil.isBlank(businessCode)) { if (StrUtil.isBlank(businessCode)) {
context.setResponse(BasicResultVO.fail(RespStatusEnum.BUSINESS_CODE_IS_NULL)); context.setResponse(BasicResultVO.fail(RespStatusEnum.BUSINESS_CODE_IS_NULL));
return context; return false;
} }
// 执行模板 // 执行模板
ProcessTemplate processTemplate = templateConfig.get(businessCode); ProcessTemplate processTemplate = templateConfig.get(businessCode);
if (processTemplate == null) { if (processTemplate == null) {
context.setResponse(BasicResultVO.fail(RespStatusEnum.PROCESS_TEMPLATE_IS_NULL)); context.setResponse(BasicResultVO.fail(RespStatusEnum.PROCESS_TEMPLATE_IS_NULL));
return context; return false;
} }
// 执行模板列表 // 执行模板列表
List<BusinessProcess> processList = processTemplate.getProcessList(); List<BusinessProcess> processList = processTemplate.getProcessList();
if (CollUtil.isEmpty(processList)) { if (CollUtil.isEmpty(processList)) {
context.setResponse(BasicResultVO.fail(RespStatusEnum.PROCESS_LIST_IS_NULL)); context.setResponse(BasicResultVO.fail(RespStatusEnum.PROCESS_LIST_IS_NULL));
return context; return false;
} }
//遍历某个流程节点,出现异常往外抛 return true;
for (BusinessProcess businessProcess : processList) {
businessProcess.process(context);
if (context.getNeedBreak()) {
break;
}
}
return context;
} }
public Map<String, ProcessTemplate> getTemplateConfig() {
return templateConfig;
}
public void setTemplateConfig(Map<String, ProcessTemplate> templateConfig) {
this.templateConfig = templateConfig;
}
} }

@ -0,0 +1,59 @@
package com.java3y.austin.utils;
import org.springframework.context.expression.MapAccessor;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.util.PropertyPlaceholderHelper;
import java.text.MessageFormat;
import java.util.Map;
/**
* @author 3y
*
*
* austin{$var}
*/
public class ContentHolderUtil {
// 占位符前缀
private static final String PLACE_HOLDER_PREFIX = "{$";
// 占位符后缀
private static final String PLACE_HOLDER_ENDFIX = "}";
private static final StandardEvaluationContext evalutionContext;
private static PropertyPlaceholderHelper propertyPlaceholderHelper = new PropertyPlaceholderHelper(
PLACE_HOLDER_PREFIX, PLACE_HOLDER_ENDFIX);
static {
evalutionContext = new StandardEvaluationContext();
evalutionContext.addPropertyAccessor(new MapAccessor());
}
public static String replacePlaceHolder(final String template, final Map<String, String> paramMap) {
String replacedPushContent = propertyPlaceholderHelper.replacePlaceholders(template,
new CustomPlaceholderResolver(paramMap));
return replacedPushContent;
}
private static class CustomPlaceholderResolver implements PropertyPlaceholderHelper.PlaceholderResolver {
private Map<String, String> paramMap;
public CustomPlaceholderResolver(Map<String, String> paramMap) {
super();
this.paramMap = paramMap;
}
@Override
public String resolvePlaceholder(String placeholderName) {
String value = paramMap.get(placeholderName);
if (null == value) {
String errorStr = MessageFormat.format("template:{} require param:{},but not exist! paramMap:{}",
placeholderName, paramMap.toString());
throw new IllegalArgumentException(errorStr);
}
return value;
}
}
}

@ -0,0 +1,26 @@
package com.java3y.austin.utils;
import cn.hutool.core.date.DateUtil;
import java.util.Date;
/**
* URL
*
* @author 3y
*/
public class TaskInfoUtils {
private static int TYPE_FLAG = 1000000;
/**
* BusinessId
* +ID+
* (16)
*/
public static Long generateBusinessId(Long templateId, Integer templateType) {
Integer today = Integer.valueOf(DateUtil.format(new Date(), "yyyyMMdd"));
return Long.valueOf(String.format("%d%s", templateType * TYPE_FLAG + templateId, today));
}
}

@ -22,9 +22,16 @@
<version>0.0.1-SNAPSHOT</version> <version>0.0.1-SNAPSHOT</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.kafka</groupId> <groupId>com.java3y.austin</groupId>
<artifactId>spring-kafka</artifactId> <artifactId>austin-service-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency> </dependency>
<dependency>
<groupId>com.java3y.austin</groupId>
<artifactId>austin-service-api-impl</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies> </dependencies>
<build> <build>

@ -1,19 +1,7 @@
package com.java3y.austin; package com.java3y.austin;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.java3y.austin.dao.MessageTemplateDao;
import com.java3y.austin.domain.MessageTemplate;
import com.java3y.austin.pojo.SmsParam;
import com.java3y.austin.script.TencentSmsScript;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Arrays;
import java.util.HashSet;
@SpringBootApplication @SpringBootApplication

@ -1,24 +1,24 @@
package com.java3y.austin.controller; //package com.java3y.austin.controller;
//
import com.java3y.austin.kafkatest.UserLogProducer; //import com.java3y.austin.kafkatest.UserLogProducer;
import org.springframework.beans.factory.annotation.Autowired; //import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping; //import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController; //import org.springframework.web.bind.annotation.RestController;
//
@RestController //@RestController
public class KafkaTestController { //public class KafkaTestController {
//
@Autowired // @Autowired
private UserLogProducer userLogProducer; // private UserLogProducer userLogProducer;
//
/** // /**
* test insert // * test insert
*/ // */
@GetMapping("/kafka/insert") // @GetMapping("/kafka/insert")
public String insert(String userId) { // public String insert(String userId) {
userLogProducer.sendLog(userId); // userLogProducer.sendLog(userId);
//
return null; // return null;
} // }
//
} //}

@ -1,15 +1,17 @@
package com.java3y.austin.controller; package com.java3y.austin.controller;
import com.java3y.austin.handler.SmsHandler; import com.java3y.austin.domain.MessageParam;
import com.java3y.austin.pojo.TaskInfo; import com.java3y.austin.domain.SendRequest;
import java.util.Collections; import com.java3y.austin.domain.SendResponse;
import java.util.HashSet; import com.java3y.austin.enums.BusinessCode;
import com.java3y.austin.service.SendService;
import com.java3y.austin.vo.BasicResultVO;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
/** /**
* @author * @author
*/ */
@ -17,29 +19,33 @@ import org.springframework.web.bind.annotation.RestController;
@RestController @RestController
public class SendController { public class SendController {
@Autowired @Autowired
private SmsHandler smsHandler; private SendService sendService;
@GetMapping("/sendSmsV2")
public SendResponse sendSmsV2(String phone) {
/** /**
* *
* @param phone * messageTemplate Id 1
* @return BasicResultVO * {"auditStatus":10,"auditor":"yyyyyyz","created":1636978066,"creator":"yyyyc","deduplicationTime":1,"expectPushTime":"0","flowId":"yyyy","id":1,"idType":20,"isDeleted":0,"isNightShield":0,"msgContent":"{\"content\":\"{$contentValue}\"}","msgStatus":10,"msgType":10,"name":"test短信","proposer":"yyyy22","sendAccount":66,"sendChannel":30,"team":"yyyt","templateType":10,"updated":1636978066,"updator":"yyyyu"}
*
*/ */
@GetMapping("/sendSms")
public BasicResultVO<Void> sendSms(String phone, String content, Long messageTemplateId) {
TaskInfo taskInfo = TaskInfo.builder().receiver(new HashSet<>( // 文案参数
Collections.singletonList(phone))) Map<String, String> variables = new HashMap<>();
.content(content) variables.put("contentValue", "6666");
.messageTemplateId(messageTemplateId)
.build();
if (smsHandler.doHandler(taskInfo)) { MessageParam messageParam = new MessageParam().setReceiver(phone).setVariables(variables);
return BasicResultVO.success("发送信息成功");
} // ID为1的消息模板
SendRequest sendRequest = new SendRequest().setCode(BusinessCode.COMMON_SEND.getCode())
.setMessageTemplateId(1L)
.setMessageParam(messageParam);
SendResponse response = sendService.send(sendRequest);
return BasicResultVO.fail(); return response;
} }
} }

@ -39,3 +39,7 @@ spring:
reset: earliest reset: earliest
# tomcat / HikariPool(数据库连接池 配置) TODO # tomcat / HikariPool(数据库连接池 配置) TODO
# 消息topicName TODO
austin:
topic:
name: austin
Loading…
Cancel
Save