job設計

俺就不起網名發表於2018-09-12

目錄

一、介面類

二、定義基礎job類

三、定義分頁批量處理job

四、job例子


在quartz和elastic job中,都是定義一個介面,然後執行execute方法。面對單條資料和多條資料,我們可以進行不同的設計。

本設計是主要運用到了類的繼承,在介面中定義execute方法,然後用抽象類去繼承,最後讓實現類去執行具體的邏輯。子類重寫了父類的方法,如果子類呼叫該方法,執行的是子類的方法,不會執行父類該方法。

一、介面類

首先定義一個介面類,模仿如elastic job 的介面,當定時任務到時,會執行該介面的execute方法

/**
 * 假設該類為job框架的介面
 * 當定時任務啟動時,呼叫該介面方法
 */
public interface Job {
    /**
     * 執行作業
     *
     * @param context 分片上下文資訊
     */
    void execute(Map<String, Object> context);
}

二、定義基礎job類

對應一個抽象基礎類,可以處理單條資料的job。可以在介面實現方法中處理一些公共資訊,然後在定義一個抽象的execute()方法,讓子類去實現它做具體的不同job業務邏輯實現。

/**
 * 基礎job,不分頁
 * protected修飾的變數,子類和同一包下都可以訪問
 */
public abstract class BaseJob implements Job {

    private Logger log = Logger.getLogger(BaseJob.class);
    protected String jobName = this.getClass().getName();
    protected static final int BATCH_COUNT = 100;//批處理條數

    @Override
    public void execute(Map<String, Object> context) {
        log.info("job start,job name is :" + context.get("jobName"));
        execute();
        log.info("job end,job name is :" + context.get("jobName"));
    }

    protected abstract void execute();//定義成子類可以訪問到

}

三、定義分頁批量處理job

1、一共有多少資料條資料?如果資料特別大是需要分頁進行處理的,如果資料小可以作為一個集合來進行處理
2、具體執行每一條的資料處理方法可以在子類中重寫;

/**
 * 分頁處理資料的job
 */
public abstract class BatchJob<T> extends BaseJob {
    private Logger log = Logger.getLogger(BaseJob.class);

    @Override
    public void execute() {
        int rows = getTotalCount();
        int pages = getPages(rows);
        if (pages == 0) {//如果沒有重寫getTotalCount()方法,pages則為0,那麼就當直接一次請求查詢解決
            pages = 1;
        }
        log.info("job :" + jobName + ", pages is " + pages);
        for (int i = 0; i < pages; i++) {
            List<T> dataList = fetchList(getBatchCount());
            if (dataList.isEmpty()) {
                return;
            }
            processList(dataList);
        }
        afterExecute();
    }

    //待處理資料總條數
    protected int getTotalCount() {
        return 0;
    }

    //獲取到總的分頁數
    protected int getPages(int rows) {
        int batchCount = getBatchCount();
        int mod = rows % batchCount;
        if (mod == 0) {
            return rows / batchCount;
        }
        return rows / batchCount + 1;
    }

    //獲取批處理條數
    protected int getBatchCount() {
        return BATCH_COUNT;
    }

    //獲取待處理資料
    protected abstract List<T> fetchList(int batchCount);

    //批量處理資料
    protected void processList(List<T> dataList) {
        if (dataList.isEmpty()) {
            return;
        }
        for (T item : dataList) {
            try {
                process(item);
            } catch (Exception e) {
                log.error("Job " + jobName + " : run Exception e", e);
                errProcess(item, e);
            }
        }
    }

    //處理單條資料
    protected void process(T item) {
    }

    //錯誤處理
    protected void errProcess(T item, Exception e) {
    }

    //任務處理完之後進行回撥
    protected void afterExecute(){}
}

四、job例子

/**
 * 當資料並不多時,可以直接在job裡呼叫execute方法在service層進行處理
 */
public class BaseJobExample extends BaseJob{

    @Override
    protected void execute() {
        //呼叫service層方法
        System.out.println("BaseJobTest execute");
    }

}
/**
 * 子類重寫父類的方法,執行時根據子類物件會執行子類的方法
 * <p>
 * 這裡沒有進行分頁查詢了,如果資料量大,需要分頁進行查詢時,
 * 可以重寫getTotalCount()/getBatchCount()方法進行分頁處理
 */
public class BatchJobExample extends BatchJob<Person> {
    @Override
    protected List fetchList(int batchCount) {
        Person person1 = new Person();
        Person person2 = new Person();
        Person person3 = new Person();
        return asList(person1, person2, person3);
    }

    @Override
    protected void processList(List<Person> dataList) {
        for (Person person : dataList) {
            System.out.println(person);
        }
    }
    
}
public class JobTest {
    @Test
    public void test() {
        Job baseJob = new BaseJobExample();
        Map<String, Object> context1 = new HashMap<String, Object>();
        context1.put("jobName", "baseJobTest");
        Job batchJob = new BatchJobExample();
        Map<String, Object> context2 = new HashMap<String, Object>();
        context2.put("jobName", "batchJobTest");
        baseJob.execute(context1);
        batchJob.execute(context2);
    }
}

執行結果如下

INFO  2018-09-12 20:52:40: [demo05.BaseJob.(19)execute] - job start,job name is :baseJobTest
BaseJobTest execute
INFO  2018-09-12 20:52:40: [demo05.BaseJob.(21)execute] - job end,job name is :baseJobTest
INFO  2018-09-12 20:52:40: [demo05.BaseJob.(19)execute] - job start,job name is :batchJobTest
INFO  2018-09-12 20:52:40: [demo05.BaseJob.(20)execute] - job :demo05.BatchJobExample, pages is 1

demo02.bean.Person@3cd1f1c8
demo02.bean.Person@3a4afd8d
demo02.bean.Person@1996cd68
INFO  2018-09-12 20:52:40: [demo05.BaseJob.(21)execute] - job end,job name is :batchJobTest

 

 

 

 

 

相關文章