【portal】【设计文档】:定时任务-状态模式使用

需求:定时任务有多个类别,每个类别有多个定时任务,动态配置
原设计:按类别定时任务分类,每个定时任务写在不同的类别类下,添加定时任务cron配置

package com.cloud.project.job;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class TestJob  {


  //时间
  @Scheduled(cron = "0/1 * * * * ?")
  public void test() throws IOException {
    System.out.println(
        "current time :" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "---");
  }
}

缺点:定时任务多起来会有很多cron配置,没有定时任务的统一管理,不能动态配置cron
改造:

  1. 定义一个接口Job,所有定时任务实现Job,
  2. 定义一个Enum存放所有类别,
  3. 定义一个Context上下文,
  4. 定义一个Job执行器从数据库获取所有定时任务统一管理,
    定义一个Map存放所有定时任务实例对象,
    通过设计模式状态模式切换定时任务类,
    通过反射执行对应类对应方法
核心代码
  JobContext jobContext = new JobContext();
  taskMap.get(cronTask.getType()).doAction(jobContext);
  Method method = jobContext.getJob().getClass().getMethod("methodName");
  method.invoke(jobContext.getJob());

详细代码:
抽象类Job:

package com.cloud.project.job;

public interface Job {


  public void doAction(JobContext jobContext);

}

任务枚举TaskEnum:

package com.cloud.project.enums;

import java.util.LinkedList;
import java.util.List;

public enum TaskEnum {
  TEST("测试"),

  private String type;

  private String typeName;

  TaskEnum(String typeName) {
    this.typeName = typeName;
  }

  TaskEnum() {

  }


  public static List<TaskEnum> getTaskEnum() {
    List<TaskEnum> list = new LinkedList<>();
    for (TaskEnum value : TaskEnum.values()) {
      list.add(value);
    }
    return list;
  }
}

上下文状态类JobContext:

package com.cloud.project.job;

import com.cloud.project.pojo.SysCronTask;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class JobContext {

  private Job job;

  public JobContext() {
    job = null;
  }

  // 测试案例
  //  public static Map<String, Job> taskMap=new HashMap<>();
  //
  //  static {
  //    taskMap.put(TaskEnum.TEST.name(), new TestJob());
  //  }
  //
  //  public static void main(String[] args)
  //      throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
  //    Context context=new Context();
  //    List<SysCronTask> list = new ArrayList<>();
  //    SysCronTask task=new SysCronTask();
  //    task.setType("TEST");
  //    list.add(task);
  //    for (SysCronTask cronTask : list) {
  //      taskMap.get(cronTask.getType()).doAction(context);
        ((TestJob) context.getJob()).test();
        ((context.getJob().getClass().getDeclaredMethod()) context.getJob()).test();
  //      Method method=context.getJob().getClass().getMethod("test");
  //      method.invoke(context.getJob());
        for (Method declaredMethod : context.getJob().getClass().getDeclaredMethods()) {
          System.out.println(declaredMethod.getName());
        }
  //
  //    }
  //  }

}

TestJob类:

package com.cloud.project.job;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

@Component
public class TestJob implement Job {


  public void doAction(JobContext jobContext) {
    jobContext.setJob(this);
  }

  //时间
  public void test() throws IOException {
    System.out.println(
        "current time :" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "---");
  }
}

任务执行器TaskCronExecutor:

package com.cloud.project.job;


import com.cloud.project.enums.TaskEnum;
import com.cloud.project.mapper.CronTaskMapper;
import com.cloud.project.pojo.SysCronTask;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;

@Component
@EnableScheduling
public class TaskCronExecutor implements SchedulingConfigurer {

  @Autowired
  private CronTaskMapper cronTaskMapper;

  public static Map<String, Job> taskMap = new HashMap<>();

  TaskCronExecutor(
      TestJob testJob, HolidayJob holidayJob, WorkRestJob workRestJob, WorkJob workJob,
      SceneryJob sceneryJob, LanguageJob languageJob, DealWithJob dealWithJob,
      SystemJob systemJob) {
    taskMap.put(TaskEnum.TEST.name(), testJob);
  }

  @Override
  public void configureTasks(
      ScheduledTaskRegistrar taskRegistrar) {

    List<SysCronTask> list = cronTaskMapper.getCronTasks();
    for (SysCronTask cronTask : list) {
      taskRegistrar.addTriggerTask(
          //1.添加任务内容(Runnable)
          //              () -> System.out.println("执行动态定时任务: " + LocalDateTime.now().toLocalTime()),
          () -> {
            JobContext jobContext = new JobContext();
            taskMap.get(cronTask.getType()).doAction(jobContext);
            try {
              Method method = jobContext.getJob().getClass().getMethod(cronTask.getMethodName());
              method.invoke(jobContext.getJob());
            } catch (InvocationTargetException e) {
              e.printStackTrace();
            } catch (NoSuchMethodException e) {
              e.printStackTrace();
            } catch (IllegalAccessException e) {
              e.printStackTrace();
            }
          },
          //2.设置执行周期(Trigger)
          triggerContext -> {
            //2.1 从数据库获取执行周期 todo
            //2.3 返回执行周期(Date)
            return new CronTrigger(cronTask.getTaskCron()).nextExecutionTime(triggerContext);
          });

    }

  }
}

后续添加任务流程:
如果是添加类别定时任务,

  1. 在TaskEnum添加类别
  2. 在taskMap添加类别对应对象实例,
  3. 在对象类里实现方法,
  4. 数据库配置定时任务完成,
    如果是添加已存在类别定时任务,
    直接按照以上3和4流程执行

使用了枚举,字典,反射,状态模式
状态模式,在此贴图说明

至此完全解决了我们多类多方法代理问题

至此改造完毕!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值