/**
* 描述 : 抽象定时任务器模板.
*
* <p>说明:
* 1. 使用「模板方法模式」
* 1.1 定义操作的流程,并将流程中的某些步骤延迟到子类中进行实现,使得子类在不改变操作流程的前提下,即可重新定义该操作的某些特定步骤
* 1.2 当一个操作的流程较为复杂,可分为多个步骤,且对于不同的操作实现类,流程步骤相同,只有部分特定步骤才需要自定义,此时可以考虑使用模板模式
* </p>
* 2. JDK源码案例参考「联想记忆」
* java.util.HashMap#putVal(int, java.lang.Object, java.lang.Object, boolean, boolean)
* 在HashMap的putVal方法中,存在afterNodeInsertion(evict);代码,该方法用于子类进行重写
* void afterNodeInsertion(boolean evict) { }
*
* <p>
* LinkedHashMap继承于HashMap,在调用父类的put方法时,会调用自身实现afterNodeInsertion的实际逻辑
* java.util.LinkedHashMap#afterNodeInsertion(boolean)
* </p>
*
* @param <T> 定时任务逻辑结果返回泛型
* @author :
* @version :
* @date :
*/
@Slf4j
public abstract class AbstractJobHandlerTemplate<T> {
/**
* 任务参数数组.
*/
private String[] paramsArray;
/**
* 定时任务处理.
*
* <p>说明:
* 1. final修饰,确保子类不会修改操作流程
*
* @param params 任务参数
* @return 处理结果
*/
public final ReturnT<String> processJob(String params) {
// 1. 进行参数校验
ReturnT<String> verifyResult = preVerify(params);
if (ReturnT.FAIL_CODE == verifyResult.getCode()) {
return verifyResult;
}
// 2. 子类实际定时任务逻辑
ResponseResult<T> responseResult = doJobHandle(paramsArray);
// 3. 定时任务后置处理
return postHandle(responseResult);
}
/**
* 各个子类实际执行定时任务的逻辑.
*
* <p>说明:
* 1. 支持使用多参数的场景
* 2. 任务参数数组可直接使用
*
* @param paramsArray 任务参数数组
* @return 定时任务执行结果
*/
protected abstract ResponseResult<T> doJobHandle(String[] paramsArray);
/**
* 子类回调校验方法.
*
* <p>说明:
* 1. 子类可重写该回调校验方法,从而实现除非必要参数校验外,自行去对参数进行校验
* 2. 不重写,默认返回ReturnT.SUCCESS
*
* @param paramsArray 任务参数数组
* @return 校验结果
*/
protected ReturnT<String> callbackVerify(String[] paramsArray) {
return ReturnT.SUCCESS;
}
/**
* 定时任务后置处理.
*
* @param responseResult 定时任务执行结果
* @return 结果返回
*/
protected ReturnT<String> postHandle(ResponseResult<T> responseResult) {
if (responseResult.isSuccess()) {
log.info("执行任务成功结束...");
return ReturnT.SUCCESS;
}
log.info("执行任务失败结束: {}", responseResult.getMsg());
return ReturnT.FAIL;
}
/**
* 前置参数校验.
*
* <p>说明:
* 1. 不开放给子类进行实现
* 2. 主要校验是否存在
*
* @param params 任务参数
* @return 校验结果
*/
private ReturnT<String> preVerify(String params) {
// 必要参数校验
if (StringUtils.isBlank(params)) {
log.info("执行任务失败结束: 请传递必要参数用户Id");
return ReturnT.FAIL;
}
MockHandler mockHandler = ApplicationContextUtils.getBean(MockHandler.class);
paramsArray = params.split(",");
// 默认第一个参数为userId
log.info("执行任务开始: {}", params);
boolean isNotSuccess = !mockHandler.mockLogin(paramsArray[0]);
if (isNotSuccess) {
log.info("执行任务失败结束: 登录失败");
return ReturnT.FAIL;
}
// 子类可重写该回调校验方法,从而实现除非必要参数校验外,自行去对参数进行校验
return callbackVerify(paramsArray);
}
}