前言
一个设想:当多个定时定时执行同一个方法是,我们可以通过参数传递进行日志打印,但是我们通知是通过aop切面实现 如何通过把参数传递到aop切面是我们问题
一个思想:参数springMvc 请求的参数传递我们定义我们自己的参数注解解决问题
只有一个定时任务执行的方法时的策略 定时任务通知-自定义注解+aop切面
编码逻辑
定义注解
//定义类型对应的枚举值 可作为注解的默认值
public enum TaskWeChatCrmEnum {
testEnum("testEnum","testEnum", "sub","code"),
testEnum1("testEnum1","testEnum1", "sub1","code1"),
defaultValue("default","default", "default","default"),
;
private final String code;
private final String taskName;
private final String subTaskName;
private final String crmDictCode;
}
//方法注解
@Target({ElementType.METHOD})
//这种类型的Annotations将被JVM保留,所以他们能在运行时被JVM或其他使用反射机制的代码所读取和使用.
@Retention(RetentionPolicy.RUNTIME)
@Documented
//注解表明制作javadoc时,是否将注解信息加入文档。如果注解在声明时使用了@Documented,则在制作javadoc时注解信息会加入javadoc。
public @interface TaskWeChatCrm {
TaskWeChatCrmEnum taskWeChatCrmEnum();
// 方法名称
String taskName() default "";
// 子方法名
String subTaskName() default "";
//crm通知的code
String crmDictCode() default "";
}
//参数注解
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
//注解表明制作javadoc时,是否将注解信息加入文档。如果注解在声明时使用了@Documented,则在制作javadoc时注解信息会加入javadoc。
public @interface TaskWeChatCrmParam {
}
使用
@RestController()
@RequestMapping(value ="task" )
public class TaskController {
@Autowired
ITaskService taskService;
@RequestMapping(value = "/baseFutureAnnotationTask",method = RequestMethod.GET)
public Map<String, Long> baseFutureAnnotationTask(@RequestParam String type) {
return taskService.baseFutureAnnotationTask(10,type);
}
}
@TaskWeChatCrm(taskWeChatCrmEnum = TaskWeChatCrmEnum.testEnum)
@Override
public Map<String, Long> baseFutureAnnotationTask(int i, @TaskWeChatCrmParam String type) {
int pageSize = 1000;
Long index = 0L;
List<Long> dataList = List.of();
Map<String, Long> map = Maps.newConcurrentMap();
for (Integer pageNum = 1; pageNum <= 10; pageNum++) {
try {
dataList = getBaseList(index, pageSize);
} catch (Exception e) {
log.error("getBaseList error", e);
}
if (CollectionUtils.isEmpty(dataList)) {
break;
}
Map<String, Long> listResult = baseFutureTaskList(dataList);
add(map, listResult);
//添加定时任务游标
index = dataList.get(dataList.size() - 1);
log.info("定时任务 {} 当前页数 {} 当前页数 {} 推送当前游标 {}", "baseFutureTask", pageNum, dataList.size(), index);
}
return map;
}
AOP拦截
@Slf4j
@Aspect
@Component
public class TaskWeChatCrmAopAspect {
private static final String DICT_CODE = "timeTask_weChat_crm";
@Data
class TaskWeChatCrmDomain {
private String taskName;
private String subTaskName;
private String crmDictCode;
}
@Before("@annotation(taskWeChatCrm)")
public void doBefore(JoinPoint joinPoint,TaskWeChatCrm taskWeChatCrm){
TaskWeChatCrmDomain taskWeChatCrmDomain = getTaskWeChatCrmDomain(joinPoint, taskWeChatCrm);
// 继续执行原方法
log.info("{} 定时任务执行方法 {} 参数 {}", taskWeChatCrm.taskName() , joinPoint.getSignature().getName() ,JSONUtil.toJsonStr(joinPoint.getArgs()));
}
//参数注解>方法注解 注解上 参数值 > 枚举值
private TaskWeChatCrmDomain getTaskWeChatCrmDomain(JoinPoint joinPoint, TaskWeChatCrm taskWeChatCrm) {
TaskWeChatCrmDomain taskWeChatCrmDomain = new TaskWeChatCrmDomain();
TaskWeChatCrmEnum taskWeChatCrmEnum = taskWeChatCrm.taskWeChatCrmEnum();
fillTaskWeChatCrmDomain(taskWeChatCrmEnum,taskWeChatCrmDomain);
if(StringUtils.isNotBlank(taskWeChatCrm.taskName())){
taskWeChatCrmDomain.setTaskName( taskWeChatCrm.taskName());
}
if(StringUtils.isNotBlank(taskWeChatCrm.subTaskName())){
taskWeChatCrmDomain.setSubTaskName( taskWeChatCrm.subTaskName());
}
if(StringUtils.isNotBlank(taskWeChatCrm.crmDictCode())){
taskWeChatCrmDomain.setCrmDictCode( taskWeChatCrm.crmDictCode());
}
TaskWeChatCrmEnum taskWeChatCrmEnumByTaskWeChatCrmParam = getTaskWeChatCrmEnumByTaskWeChatCrmParam(joinPoint, taskWeChatCrmDomain);
fillTaskWeChatCrmDomain(taskWeChatCrmEnumByTaskWeChatCrmParam,taskWeChatCrmDomain);
return taskWeChatCrmDomain;
}
private TaskWeChatCrmEnum getTaskWeChatCrmEnumByTaskWeChatCrmParam(JoinPoint joinPoint, TaskWeChatCrmDomain taskWeChatCrmDomain) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
// 获取方法参数注解
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
if(ArrayUtils.isEmpty(parameterAnnotations)){
return null;
}
// 获取方法参数的实际值
Object actualValue = null;
Object[] args = joinPoint.getArgs();
for (int i = 0; i < parameterAnnotations.length; i++) {
for (Annotation annotation : parameterAnnotations[i]) {
if (annotation instanceof TaskWeChatCrmParam) {
// 找到参数上的注解
TaskWeChatCrmParam myParamAnnotation = (TaskWeChatCrmParam) annotation;
actualValue = args[i];
}
}
}
if(Objects.isNull(actualValue)){
return null;
}
TaskWeChatCrmEnum taskWeChatCrmEnum = null;
if(actualValue instanceof String){
String code = actualValue.toString();
return TaskWeChatCrmEnum.getByCode(code);
}
if(actualValue instanceof TaskWeChatCrmEnum){
return (TaskWeChatCrmEnum) actualValue;
}
return null;
}
private void fillTaskWeChatCrmDomain(TaskWeChatCrmEnum taskWeChatCrmEnum, TaskWeChatCrmDomain taskWeChatCrmDomain) {
if(Objects.isNull(taskWeChatCrmEnum)){
return;
}
taskWeChatCrmDomain.setTaskName(taskWeChatCrmEnum.getTaskName());
taskWeChatCrmDomain.setSubTaskName(taskWeChatCrmEnum.getSubTaskName());
taskWeChatCrmDomain.setCrmDictCode(taskWeChatCrmEnum.getCrmDictCode());
}
}
此程序增强了对注解方法参数的处理
- 注意点1: 参数注解>方法注解 ,注解上参数值 > 枚举值