造个轮子-任务调度执行小框架-任务执行器代理实现

前言

不知道为啥,今天好像学不进去,没办法,那就继续编码吧。那么今天的话,加更一篇文章,那就是咱们这个任务执行器的实现。先前我们是实现到了这个部分,那么现在的话,我们实现的是这个部分。(ps:文末看到项目地址):
在这里插入图片描述

蓝色部分的内容,当然这个是完整的执行器,因此对于生命周期也会进行实现,不过在这里的话,发现先前的这个生命周期实在是冗余了,所以的话砍掉了部分内容,这部分主要是在这里:
在这里插入图片描述

这里的内容进行了简化,所以的话,使用起来看起来就没有那么吓人了。同样的这里还提供了这个简单实现的Handler,如果你需要高度定制化,那就直接实现这个接口,不要的话就继承这个handler类就可以了。当然在这个里面其实也没干啥:
在这里插入图片描述

执行器代理

okey,那么我们来看到我们的一个今天的内容吧,我们昨天的话是实现了这个,创建这个清单模板。那么接下来我们要做的就是通过这个清单模板,去创建代理执行对象,然后通过这个代理执行对象,去完成这个对应的操作。所以这里的话其实还是分为两个部分。

  1. 通过任务清单模板,去创建代理对象
  2. 在代理对象的基础上,我们去实现这一的一个周期
    当然现在的话,我们实现的是这个代理对象。

代理对象

ok,我们先来看到我们的代理对象。
在这里的话我们有两个代理对象:
在这里插入图片描述

任务清单代理对象

首先的话,是我们的任务清单代理对象:

package com.huterox.todoscheduler.core.execute.proxy;





import com.huterox.todoscheduler.core.enumType.TodoListElementType;
import com.huterox.todoscheduler.core.enumType.TodoListStateType;
import com.huterox.todoscheduler.core.wapper.ListStateWrapper;
import com.huterox.todoscheduler.handler.*;

import java.io.Serializable;
import java.util.Comparator;
import java.util.Map;
import java.util.TreeMap;


/**
 * 任务清单对象,这里记录的是基本的清单对象信息,
 * */
public class TodoListExBean implements Serializable {

    //任务清单类型
    public TodoListElementType todoListElementType;



    //任务清单的名字
    public String todoListName;


    //当前的状态,当然服务宕机恢复任务的时候,这个是一个很重要的凭证
    public TodoListStateType todoListStateType;

    //任务清单的状态信息
    private ListStateWrapper stateWrapper;

    //执行的次数,因为有失败重新执行的东东
    private int exTimes;




    /*
    * 因为几个清单可能服务同一个用户,所以按照这个再给你分个类
    * 对于ClsId相同的清单是顺序执行的,所以这个是最小颗粒度的操作
    * */
    public String ClsId;
    TodoListErrorHandler todoListErrorHandler;
    TodoListAfterHandler todoListAfterHandler;
    TodoListBeforeCreateHandler todoListCreateCheckHandler;


    private final Comparator<Integer> keyComparator = new Comparator<Integer>() {
        @Override
        public int compare(Integer key1, Integer key2) {
            // 根据键的大小进行比较
            return key1.compareTo(key2);
        }
    };
    //对应执行的方法链路
    private final Map<Integer, TodoItemExBean> sortedMap = new TreeMap<>(keyComparator);

    public TodoListExBean() {
    }

    public TodoListExBean(TodoListElementType todoListElementType, String todoListName, TodoListErrorHandler todoListErrorHandler, TodoListAfterHandler todoListAfterHandler, TodoListBeforeCreateHandler todoListCreateCheckHandler) {
        this.todoListElementType = todoListElementType;
        this.todoListName = todoListName;
        this.todoListErrorHandler = todoListErrorHandler;
        this.todoListAfterHandler = todoListAfterHandler;
        this.todoListCreateCheckHandler = todoListCreateCheckHandler;
    }


    @Override
    public String toString() {
        return "The TodoList name is:"+this.todoListName;
    }

    public int getExTimes() {
        return exTimes;
    }

    public void setExTimes(int exTimes) {
        this.exTimes = exTimes;
    }

    public TodoListExBean(String todoListName) {
        this.todoListName = todoListName;
    }

    public TodoListStateType getTodoListStateType() {
        return todoListStateType;
    }





    public void setTodoListStateType(TodoListStateType todoListStateType) {
        this.todoListStateType = todoListStateType;
    }




    public ListStateWrapper getStateWrapper() {
        return stateWrapper;
    }



    public void setStateWrapper(ListStateWrapper stateWrapper) {
        this.stateWrapper = stateWrapper;
    }



    public Comparator<Integer> getKeyComparator() {
        return keyComparator;
    }


    public Map<Integer, TodoItemExBean> getSortedMap() {
        return sortedMap;
    }

    public TodoListExBean(String todoListName, String clsId) {
        this.todoListName = todoListName;
        ClsId = clsId;
    }

    public TodoListElementType getTodoListElementType() {
        return todoListElementType;
    }

    public void setTodoListElementType(TodoListElementType todoListElementType) {
        this.todoListElementType = todoListElementType;
    }

    public String getTodoListName() {
        return todoListName;
    }

    public String getClsId() {
        return ClsId;
    }

    public void setClsId(String clsId) {
        ClsId = clsId;
    }

    public void setTodoListName(String todoListName) {
        this.todoListName = todoListName;
    }

    public TodoListErrorHandler getTodoListErrorHandler() {
        return todoListErrorHandler;
    }

    public void setTodoListErrorHandler(TodoListErrorHandler todoListErrorHandler) {
        this.todoListErrorHandler = todoListErrorHandler;
    }

    public TodoListAfterHandler getTodoListAfterHandler() {
        return todoListAfterHandler;
    }

    public void setTodoListAfterHandler(TodoListAfterHandler todoListAfterHandler) {
        this.todoListAfterHandler = todoListAfterHandler;
    }

    public TodoListBeforeCreateHandler getTodoListCreateCheckHandler() {
        return todoListCreateCheckHandler;
    }

    public void setTodoListCreateCheckHandler(TodoListBeforeCreateHandler todoListCreateCheckHandler) {
        this.todoListCreateCheckHandler = todoListCreateCheckHandler;
    }


}

任务清单执项对象

然后的话,是我们的一个任务清单的执行项:

package com.huterox.todoscheduler.core.execute.proxy;






import com.huterox.todoscheduler.core.enumType.TodoItemElementType;

import com.huterox.todoscheduler.core.enumType.TodoItemStateType;
import com.huterox.todoscheduler.core.wapper.ItemStateWrapper;
import com.huterox.todoscheduler.handler.*;

import java.io.Serializable;
import java.lang.reflect.Method;


/**
 * 任务清单对应的Item,这里记录的是这个Item基本的信息
 * */
public class TodoItemExBean implements Serializable {

    //任务清单项类型
    public TodoItemElementType todoItemElementType;

    //任务执行顺序
    public int order;

    //这是第几个清单的方法
    private int idx;


    //实例对象
    private Object wrapperInstance;
    //对应的class
    private Class<?> wrapperClass;
    //对应的方法
    private Method wrapperMethod;


    //当前的状态,当然服务宕机恢复任务的时候,这个是一个很重要的凭证
    public TodoItemStateType todoItemStateType;

    TodoItemBeforeCreateHandler todoItemCreateHandler;
    TodoItemAfterRunningHandler todoItemAfterRunningHandler;
    TodoItemBeforeRunningHandler todoItemBeforeRunningHandler;
    TodoItemErrorHandler todoItemErrorHandler;

    private ItemStateWrapper stateWrapper;

    public TodoItemExBean() {
        //初始化的时候就进行创建
        this.stateWrapper = new ItemStateWrapper();
    }

    public TodoItemExBean(int order) {
        this.order = order;
    }

    public ItemStateWrapper getStateWrapper() {
        return stateWrapper;
    }

    public void setStateWrapper(ItemStateWrapper stateWrapper) {
        this.stateWrapper = stateWrapper;
    }


    public Object getWrapperInstance() {
        return wrapperInstance;
    }

    public void setWrapperInstance(Object wrapperInstance) {
        this.wrapperInstance = wrapperInstance;
    }

    public Class<?> getWrapperClass() {
        return wrapperClass;
    }

    public void setWrapperClass(Class<?> wrapperClass) {
        this.wrapperClass = wrapperClass;
    }

    public Method getWrapperMethod() {
        return wrapperMethod;
    }


    public void setWrapperMethod(Method wrapperMethod) {
        this.wrapperMethod = wrapperMethod;
    }

    public TodoItemStateType getTodoItemStateType() {
        return todoItemStateType;
    }


    public void setTodoItemStateType(TodoItemStateType todoItemStateType) {
        this.todoItemStateType = todoItemStateType;
    }




    public int getIdx() {
        return idx;
    }



    public void setIdx(int idx) {
        this.idx = idx;
    }




    @Override
    public String toString() {
        return "the order is "+this.order;
    }

    public TodoItemExBean(TodoItemElementType todoItemElementType, int order, TodoItemBeforeCreateHandler todoItemCreateHandler, TodoItemAfterRunningHandler todoItemAfterRunningHandler, TodoItemBeforeRunningHandler todoItemBeforeRunningHandler, TodoItemErrorHandler todoItemErrorHandler) {
        this.todoItemElementType = todoItemElementType;
        this.order = order;
        this.todoItemCreateHandler = todoItemCreateHandler;
        this.todoItemAfterRunningHandler = todoItemAfterRunningHandler;
        this.todoItemBeforeRunningHandler = todoItemBeforeRunningHandler;
        this.todoItemErrorHandler = todoItemErrorHandler;
    }

    public TodoItemElementType getTodoItemElementType() {
        return todoItemElementType;
    }

    public void setTodoItemElementType(TodoItemElementType todoItemElementType) {
        this.todoItemElementType = todoItemElementType;
    }


    public int getOrder() {
        return order;
    }

    public void setOrder(int order) {
        this.order = order;
    }

    public TodoItemBeforeCreateHandler getTodoItemCreateHandler() {
        return todoItemCreateHandler;
    }

    public void setTodoItemCreateHandler(TodoItemBeforeCreateHandler todoItemCreateHandler) {
        this.todoItemCreateHandler = todoItemCreateHandler;
    }

    public TodoItemAfterRunningHandler getTodoItemAfterRunningHandler() {
        return todoItemAfterRunningHandler;
    }

    public void setTodoItemAfterRunningHandler(TodoItemAfterRunningHandler todoItemAfterRunningHandler) {
        this.todoItemAfterRunningHandler = todoItemAfterRunningHandler;
    }

    public TodoItemBeforeRunningHandler getTodoItemBeforeRunningHandler() {
        return todoItemBeforeRunningHandler;
    }

    public void setTodoItemBeforeRunningHandler(TodoItemBeforeRunningHandler todoItemBeforeRunningHandler) {
        this.todoItemBeforeRunningHandler = todoItemBeforeRunningHandler;
    }

    public TodoItemErrorHandler getTodoItemErrorHandler() {
        return todoItemErrorHandler;
    }

    public void setTodoItemErrorHandler(TodoItemErrorHandler todoItemErrorHandler) {
        this.todoItemErrorHandler = todoItemErrorHandler;
    }

}

处理handler对象

然后在这里的话,可以看到这里还有很多Handler,这个东西,就是我们一开始看到的东西,因为我们接下来要实现一个完整的代理执行周期,因此我们必须拿到这些东西。然后进行执行。这里的话我们可以先看到我们的一个执行:在这里插入图片描述

所以的话,这里要注意,我们为什么这里有那么多Handler。

状态对象

之后的话,是我们的一个状态,在执行方法的时候,我们可以保持到清单的一个状态,还有每一个清单项的状态,你都可以拿到。那么这里的话,主要是因为这个接口:
在这里插入图片描述
你要实现的方法里面带有这个,然后在后期执行代码的时候,我们会把这个对象给你,你可以看到这个:
在这里插入图片描述

代理工厂

okey,那么接下来就是我们的代理工厂的实现了。
那么同样的,我们当然有两个代理工厂了,一个是关于任务清单的,还有一个是关于任务项的。

任务清单代理工厂

先来看到我们的任务清单代理工厂:

package com.huterox.todoscheduler.core.execute;





import com.huterox.todoscheduler.core.enumType.TodoListStateType;
import com.huterox.todoscheduler.core.execute.proxy.TodoItemExBean;
import com.huterox.todoscheduler.core.execute.proxy.TodoListExBean;
import com.huterox.todoscheduler.core.global.TodoListTemplateMap;
import com.huterox.todoscheduler.core.wapper.TodoItemMethodWrapper;

import com.huterox.todoscheduler.core.wapper.TodoListWrapper;
import com.huterox.todoscheduler.exception.TodoListException;
import com.huterox.todoscheduler.handler.TodoListBeforeCreateHandler;


import java.io.Serializable;
import java.util.Map;

/**
 * 创建真正的任务执行清单对象,
 * 通过这个ToDoListBean的信息来进行创建
 * */

public class TodoListFactory implements Serializable {



    /**
     *   创建可以执行的清单对象,然后对执行器就会执行这个对象,执行的是TodoListExBean
     *   如果返回结果为null,说明连这个清单都没有
     * */


    public static TodoListExBean getInstance(String listName) {
        TodoListExBean todoListExBean = new TodoListExBean();

        if(!TodoListTemplateMap.getInstance().containKey(listName)){
            new TodoListException("未找到任务清单失败:"+listName,-1).printStackTrace();
            todoListExBean.setTodoListStateType(TodoListStateType.CreatFailed);
            return null;
        }
        //先获取到清单的模板
        TodoListWrapper todoListTemplate = TodoListTemplateMap.getInstance().get(listName);

        todoListExBean.setTodoListName(todoListTemplate.getTodoListName());
        todoListExBean.setTodoListAfterHandler(todoListTemplate.getTodoListAfterHandler());
        todoListExBean.setTodoListCreateCheckHandler(todoListTemplate.getTodoListCreateCheckHandler());
        todoListExBean.setTodoListErrorHandler(todoListTemplate.getTodoListErrorHandler());

        //执行创建前的方法
        if(todoListExBean.getTodoListCreateCheckHandler()!=null){
            try {
                TodoListBeforeCreateHandler todoListCreateCheckHandler = todoListExBean.getTodoListCreateCheckHandler();
                //先执行这个获取ClsID的方法
                try {
                    String s = todoListCreateCheckHandler.setCIds();
                    if(!("".equals(s))){
                        todoListExBean.setClsId(s);
                    }else {
                        todoListExBean.setClsId("");
                    }
                }catch (Exception e){
                    e.printStackTrace();
                    todoListExBean.setTodoListStateType(TodoListStateType.CreatFailed);
                    return todoListExBean;
                }
            }catch (Exception exception){
                exception.printStackTrace();
                todoListExBean.setTodoListStateType(TodoListStateType.CreatFailed);
                return todoListExBean;
            }
        }


        //遍历模板,然后将可执行的清单项放在我们的这个TodoListBeanEx的执行项目里面

        Map<Integer, TodoItemExBean> sortedMapEx = todoListExBean.getSortedMap();

        Map<Integer, TodoItemMethodWrapper> sortedMap = todoListTemplate.getSortedMap();
        for(Map.Entry<Integer, TodoItemMethodWrapper> sortedMapEntry:sortedMap.entrySet()){
            TodoItemMethodWrapper mapEntryValue = sortedMapEntry.getValue();
            Integer key = sortedMapEntry.getKey();
            TodoItemExBean instance = TodoItemFactory.getInstance(mapEntryValue,todoListExBean);
            if(instance==null){
                //如果这个清单项创建失败,那也是失败
                return null;
            }
            sortedMapEx.put(key,instance);


        }
        //此时创建完毕,但是这里每一个方法如何执行,也就是清单项是调度器考虑的事情了
        return todoListExBean;
    }
}


通过这个来创建到我们的清单

清单任务项代理工厂

之后是这个,一个清单里面包含了很多的这个执行项,因为本质上,一个执行项就是一个类方法嘛。

package com.huterox.todoscheduler.core.execute;





import com.huterox.todoscheduler.annotate.*;
import com.huterox.todoscheduler.core.enumType.TodoItemElementType;

import com.huterox.todoscheduler.core.execute.proxy.TodoItemExBean;
import com.huterox.todoscheduler.core.execute.proxy.TodoListExBean;
import com.huterox.todoscheduler.core.wapper.TodoItemMethodWrapper;

import com.huterox.todoscheduler.handler.TodoItemAfterRunningHandler;
import com.huterox.todoscheduler.handler.TodoItemBeforeCreateHandler;
import com.huterox.todoscheduler.handler.TodoItemBeforeRunningHandler;
import com.huterox.todoscheduler.handler.TodoItemErrorHandler;


import java.io.Serializable;
import java.lang.reflect.Method;

/**
 * 负责将方法解析出来
 * */

public class TodoItemFactory implements Serializable {



    //当这个方法返回null的时候,说明创建失败
    public static TodoItemExBean getInstance(TodoItemMethodWrapper todoItemMethodWrapper, TodoListExBean todoListExBean){


        TodoItemExBean todoItemExBean = new TodoItemExBean();
        todoItemExBean.setOrder(todoItemMethodWrapper.getOrder());
        todoItemExBean.setTodoItemElementType(todoItemMethodWrapper.getTodoItemElementType());
        todoItemExBean.setIdx(todoItemMethodWrapper.getIdx());
        todoItemExBean.setWrapperMethod(todoItemMethodWrapper.getWrapperMethod());
        todoItemExBean.setWrapperClass(todoItemMethodWrapper.getWrapperClass());
        todoItemExBean.setWrapperInstance(todoItemMethodWrapper.getWrapperInstance());

        //解析注解
        Method wrapperMethod = todoItemMethodWrapper.getWrapperMethod();
        wrapperMethod.setAccessible(true);
        if(wrapperMethod.isAnnotationPresent(TodoItemBeforeCreate.class)){
            //这个时候要先去执行一下这个初始化创建的代码
            TodoItemBeforeCreate annotationTodoItemBeforeCreate = wrapperMethod.getAnnotation(TodoItemBeforeCreate.class);
            Class<TodoItemBeforeCreateHandler>[] todoItemBeforeCreates = annotationTodoItemBeforeCreate.todoItemBeforeCreates();
            Class<TodoItemBeforeCreateHandler> todoItemBeforeCreateHandlerClass = todoItemBeforeCreates[todoItemExBean.getIdx()];
            try {
                TodoItemBeforeCreateHandler todoItemBeforeCreateHandler = todoItemBeforeCreateHandlerClass.newInstance();
                //把这个状态Wrapper给它,这个时候是直接执行这个家伙
                try {
                    todoItemBeforeCreateHandler.concierge(todoItemExBean.getStateWrapper(),todoListExBean.getStateWrapper());
                }catch (Exception e){
                    //判断一下类型,是属于哪一种,是那种可以跳过执行的清单项
                    if(todoItemExBean.getTodoItemElementType()== TodoItemElementType.CONTINUTEITEM){
                        //继续happy执行往下走继续
                        System.err.println("当前清单项创建失败执行方法:"+wrapperMethod.getName()
                                        +"对应的类为:"+todoItemExBean.getWrapperClass().getName()
                                );
                        e.printStackTrace();
                    }else {
                        //不能继续往下happy了,直接先执行修复
                        try {
                            todoItemBeforeCreateHandler.repair(todoItemExBean.getStateWrapper(),todoListExBean.getStateWrapper());
                        }catch (Exception e1){
                            //连修复都G了,没了
                            e1.printStackTrace();
                        }
                        return null;
                    }
                    //还是必须要强制执行的清单项
                    e.printStackTrace();
                }

            } catch (InstantiationException | IllegalAccessException e) {
                e.printStackTrace();
            }
        }

        if(wrapperMethod.isAnnotationPresent(TodoItemBefore.class)){
            TodoItemBefore annotationTodoItemBefore = wrapperMethod.getAnnotation(TodoItemBefore.class);
            Class<TodoItemBeforeRunningHandler>[] todoItemBeforeRunningHandlerClasses = annotationTodoItemBefore.todoItemBefores();
            Class<TodoItemBeforeRunningHandler> todoItemBeforeRunningHandlerClass = todoItemBeforeRunningHandlerClasses[todoItemExBean.getIdx()];
            TodoItemBeforeRunningHandler todoItemBeforeRunningHandler = null;
            try {
                todoItemBeforeRunningHandler = todoItemBeforeRunningHandlerClass.newInstance();
            } catch (InstantiationException | IllegalAccessException e) {
                e.printStackTrace();
                return null;
            }
            todoItemExBean.setTodoItemBeforeRunningHandler(todoItemBeforeRunningHandler);
        }

        if(wrapperMethod.isAnnotationPresent(TodoItemAfterHandler.class)){
            TodoItemAfterHandler annotationTodoItemAfterHandler = wrapperMethod.
                    getAnnotation(TodoItemAfterHandler.class);

            Class<TodoItemAfterRunningHandler>[] todoItemAfterRunningHandleClasses = annotationTodoItemAfterHandler.
                    todoItemAfterHandlers();



            Class<TodoItemAfterRunningHandler> todoItemAfterRunningHandleClass = todoItemAfterRunningHandleClasses[todoItemExBean.getIdx()];

            TodoItemAfterRunningHandler todoItemAfterRunningHandler = null;
            try {
                todoItemAfterRunningHandler = todoItemAfterRunningHandleClass.newInstance();
            } catch (InstantiationException | IllegalAccessException e) {
                e.printStackTrace();
                return null;
            }
            todoItemExBean.setTodoItemAfterRunningHandler(todoItemAfterRunningHandler);
        }


        if(wrapperMethod.isAnnotationPresent(TodoItemError.class)) {
            TodoItemError annotationTodoItemError = wrapperMethod.getAnnotation(TodoItemError.class);
            Class<TodoItemErrorHandler>[] todoItemErrorHandlerClasses = annotationTodoItemError.todoItemErrors();
            Class<TodoItemErrorHandler> todoItemErrorHandlerClass = todoItemErrorHandlerClasses[todoItemExBean.getIdx()];
            TodoItemErrorHandler todoItemErrorHandler = null;
            try {
                todoItemErrorHandler = todoItemErrorHandlerClass.newInstance();
            } catch (InstantiationException | IllegalAccessException e) {
                e.printStackTrace();
                return null;
            }
            todoItemExBean.setTodoItemErrorHandler(todoItemErrorHandler);
        }

        //此时我们的清单项封装实例化完毕
        return todoItemExBean;
    }
}


总结

那么到这里,我们就完成了这个任务清单的代理实现。当然这里面用到了很多的一些Wrapper类,但是核心就是上面说到的东西。

之后的话,通过差不多天半的开发:我们(团队成员the only one is me) 完成了这个项目的开发,现在的话在写这个开发教程。所以今天的话,大概是有3更。本来是说慢慢做的,但是发现有这个事情,然后每天写一点的话不连贯。重新想的时候好慢,所以没有办法,今天是特意专门拿出一天的时间拿过来开发。因为昨天干到两点,没啥精神,考研的话看不下去。一直有心事,压在身上很不舒服。

然后项目地址:gitee.com/Huterox/hto… 当然这里面还有很多工作要做,只是核心功能做好了。

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYgv3StN' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片