使用责任链模式优化处理流程
目录
使用责任链模式优化处理流程
场景:需要定时任务扫描隐患整改统计信息表,对超时未处理的事件发送通知短信,流程图如下:
由上图可知,当不满足过滤条件才会进行下一次判断,所以可通过责任链模式来处理业务
定义处理的handle抽象类 StatisticsHandle
public abstract class StatisticsHandle {
public PotentialSafetyHazardStatisticsHandle nextHandle;
public void setNext(PotentialSafetyHazardStatisticsHandle nextHandle){
this.nextHandle = nextHandle;
}
public abstract void handle(PotentialSafetyHazardStatisticsBO statistics);
protected Boolean compareDate(Date beforeDate){
Date nowDate = new Date();
String proValue = PropertyReaderUtils.getProValue("statistics.over.time");
if(proValue != null) {
int overTime = Integer.parseInt(proValue);
Date addHour = DateUtil.addHour(beforeDate, overTime);
return addHour.before(nowDate);
}
return null;
}
protected AlarmInfoVo getAlarmInfo(PotentialSafetyHazardStatisticsBO statistics){
if(statistics == null){
return null;
}
if(statistics.getAlarmInfo() != null){
return statistics.getAlarmInfo();
}
// todo 查询数据库
return null;
}
protected void sendSms(String phone, Map<String, String> paramMap){
// todo
}
}
实现类
AlarmDealWithHandleImpl
@Slf4j
@Service
@RequiredArgsConstructor
public class AlarmDealWithHandleImpl extends StatisticsHandle {
private final UasAuthService uasAuthService;
private final PotentialSafetyHazardStatisticsMapper potentialSafetyHazardStatisticsMapper;
/**
*
* @param statistics
*/
@Override
public void handle(PotentialSafetyHazardStatisticsBO statistics) {
if(statistics == null){
return;
}
// 判断报警处理是否为未处理
if(statistics.getAlarmInfoDealWithYn() == 0){
// 在判断报警时间到现在是否已经超过设定的阈值
if(this.compareDate(statistics.getCreateTime())){
// 发送短信
// 查询安全总监手机号
List<AlarmHandlePersonVo> personVoList = uasAuthService.queryDirectorUserList(statistics.getOrgId().toString());
if(CollectionUtils.isNotEmpty(personVoList)){
Map<String, String> paramMap = new HashMap<>();
AlarmInfoVo alarmInfo = this.getAlarmInfo(statistics);
if(alarmInfo != null) {
paramMap.put("content", alarmInfo.getAlarmName() + "隐患");
for (AlarmHandlePersonVo personVo : personVoList) {
this.sendSms(personVo.getPhoneNumber(), paramMap);
}
// 将报警处理字段设置为1
statistics.setAlarmInfoDealWithYn(1);
potentialSafetyHazardStatisticsMapper.updateByPrimaryKeySelective(statistics);
}else{
log.info("alarmInfo is null");
return;
}
}else{
log.info("security director list is empty");
}
}else{
log.info("the preset threshold has not been exceeded");
return;
}
}
// 交给下一个handle处理
if(this.nextHandle != null){
this.nextHandle.handle(statistics);
}
}
}
potentialConfirmHandleImpl
@Slf4j
@Service
@RequiredArgsConstructor
public class potentialConfirmHandleImpl extends StatisticsHandle {
private final PotentialSafetyHazardStatisticsMapper potentialSafetyHazardStatisticsMapper;
private final PotentialSafetyHazardMapper potentialSafetyHazardMapper;
@Override
public void handle(PotentialSafetyHazardStatisticsBO statistics) {
if(statistics.getPotentialSafetyHazardId() == null){
return;
}
if(statistics.getPotentialConfirmYn() == 0){
// 判断是否逾期为确认
if(this.compareDate(statistics.getPotentialConfirmTime())){
// 发送短信 提醒整改责任人
PotentialSafetyHazard potentialSafetyHazard = potentialSafetyHazardMapper.selectByPrimaryKey(statistics.getPotentialSafetyHazardId());
if(potentialSafetyHazard != null && potentialSafetyHazard.getPicPhoneNumber() != null){
AlarmInfoVo alarmInfo = this.getAlarmInfo(statistics);
Map<String,String> paramMap = new HashMap<>();
if(alarmInfo != null){
paramMap.put("content", alarmInfo.getAlarmName() + "隐患需要整改确认");
this.sendSms(potentialSafetyHazard.getPicPhoneNumber(), paramMap);
}
}
// 修改确认的值
statistics.setPotentialConfirmYn(1);
potentialSafetyHazardStatisticsMapper.updateByPrimaryKeySelective(statistics);
}
}
if(this.nextHandle != null){
this.nextHandle.handle(statistics);
}
}
}
RectificationHandleImpl
@Slf4j
@Service
@RequiredArgsConstructor
public class RectificationHandleImpl extends PotentialSafetyHazardStatisticsHandle {
private final PotentialSafetyHazardMapper potentialSafetyHazardMapper;
private final PotentialSafetyHazardStatisticsMapper potentialSafetyHazardStatisticsMapper;
private final UasAuthService uasAuthService;
@Override
public void handle(PotentialSafetyHazardStatisticsBO statistics) {
if(statistics.getRectificationYn() == 0){
PotentialSafetyHazard potentialSafetyHazard = potentialSafetyHazardMapper.selectByPrimaryKey(statistics.getPotentialSafetyHazardId());
if(potentialSafetyHazard != null){
// 获取当前时间
LocalDateTime nowTime= LocalDateTime.now();
// 获取整改期限
LocalDateTime fixDeadLine = potentialSafetyHazard.getFixDeadLine();
log.info("PotentialSafetyHazard fixDeadLine: {}", fixDeadLine);
if(fixDeadLine != null && fixDeadLine.isBefore(nowTime)){
// 获取监理电话列表
List<AlarmHandlePersonVo> personVoList = uasAuthService.querySupervisionUserList(statistics.getOrgId().toString());
if(CollectionUtils.isNotEmpty(personVoList)){
AlarmInfoVo alarmInfo = this.getAlarmInfo(statistics);
// 发送短信
if(alarmInfo != null){
Map<String, String> paramMap = new HashMap<>();
paramMap.put("content", alarmInfo.getAlarmName() + "隐患,已超过期限");
personVoList.forEach(item -> this.sendSms(item.getPhoneNumber(), paramMap));
}
}
}
// 修改整改字段为1
statistics.setRectificationYn(1);
potentialSafetyHazardStatisticsMapper.updateByPrimaryKeySelective(statistics);
}
}
if(this.nextHandle != null){
this.nextHandle.handle(statistics);
}
}
}
创建枚举类
StatisticsHandleEnum
@Getter
public enum StatisticsHandleEnum {
ALARM_DEAL_WITH(1, AlarmDealWithHandleImpl.class, 2, null),
POTENTIAL_CONFIRM(2, potentialConfirmHandleImpl.class, 3, 1),
RECTIFICATION(3, RectificationHandleImpl.class, null, 2)
;
private Integer id;
private Class<? extends StatisticsHandle> className;
private Integer nextId;
private Integer preId;
StatisticsHandleEnum(Integer id, Class<? extends StatisticsHandle> className, Integer nextId, Integer preId) {
this.id = id;
this.className = className;
this.nextId = nextId;
this.preId = preId;
}
}
创建工厂类
StatisticsHandleFactory
public class PotentialStatisticsHandleFactory {
private static Map<Integer, StatisticsHandleEnum> map = new HashMap<>();
static{
for(StatisticsHandleEnum handleEnum: StatisticsHandleEnum.values()){
map.put(handleEnum.getId(), handleEnum);
}
}
public StatisticsHandle buildHandle(){
// 1. 获取第一处理者 那么那个是第一个处理者呢 preId == null 的就是第一个handler
StatisticsHandleEnum firstEnum = this.getFirstEnum();
if(firstEnum != null){
StatisticsHandle firstHandle = newHandler(firstEnum);
if(firstHandle == null){
return null;
}
setNextHandler(firstEnum, firstHandle);
return firstHandle;
}
return null;
}
private void setNextHandler(StatisticsHandleEnum handleEnum, StatisticsHandle handle) {
if(handleEnum != null && handle != null){
Integer nextId = handleEnum.getNextId();
StatisticsHandleEnum nextHandleEnum = this.getEnumById(nextId);
StatisticsHandle nextHandle = newHandler(nextHandleEnum);
setNextHandler(nextHandleEnum, nextHandle);
}
}
/**
* 反射实体化具体的处理者
* @param handleEnum
* @return
*/
private static StatisticsHandle newHandler(StatisticsHandleEnum handleEnum){
if(handleEnum == null){
return null;
}
return SpringApplicationContextUtil.getBean(handleEnum.getClassName());
}
public StatisticsHandleEnum getEnumById(Integer id) {
if(id == null){
return null;
}
return map.get(id);
}
public StatisticsHandleEnum getFirstEnum() {
for(StatisticsHandleEnum entity: map.values()){
if(entity.getPreId() == null){
return entity;
}
}
return null;
}
}
业务BO类
PotentialSafetyHazardStatisticsBO
PotentialSafetyHazardStatistics :实体类
@Data
public class PotentialSafetyHazardStatisticsBO extends PotentialSafetyHazardStatistics {
private AlarmInfoVo alarmInfo;
}
SpringApplicationContextUtil
@Configuration
public class SpringApplicationContextUtil implements ApplicationContextAware {
@Getter
private static ApplicationContext context;
public static Object getBean(String beanName) {
return context == null ? null : context.getBean(beanName);
}
public static <T> T getBean(Class<T> beanClass) {
return context == null ? null : context.getBean(beanClass);
}
public static String[] getBeanDefinitionNames() {
return context == null ? null : context.getBeanDefinitionNames();
}
@Override
public void setApplicationContext(ApplicationContext context) throws BeansException {
SpringApplicationContextUtil.context = context;
}
}
定时任务
@Component
@Slf4j
@RequiredArgsConstructor
public class PotentialSafetyHazardStatisticsScheduled {
private final PotentialSafetyHazardStatisticsMapper potentialSafetyHazardStatisticsMapper;
private final PotentialStatisticsHandleFactory potentialStatisticsHandleFactory;
@Scheduled(cron = "0 0/5 * * * ?")
public void scanTableSendSms(){
PotentialSafetyHazardStatisticsHandle statisticsHandle = potentialStatisticsHandleFactory.buildHandle();
Date startTime = new Date();
List<PotentialSafetyHazardStatistics> list = potentialSafetyHazardStatisticsMapper.list(null, null, startTime);
Optional.ofNullable(list).orElse(new ArrayList<>()).forEach(item -> {
PotentialSafetyHazardStatisticsBO target = new PotentialSafetyHazardStatisticsBO();
BeanUtils.copyProperties(item, target);
statisticsHandle.handle(target);
});
}
}