使用函数式接口对代码简化,完成代码重复性使用

2023-12-23 21:40:19

📚简介

???????因为公司的使用Xxl-Job作为任务调度平台,其中我们大部分的报表查询数据量太大,字段又多,实时查询效率太低,等待时长也久,我们只能把常用的数据进行定时任务处理,每几分钟自动运行程序跑对应报表的Sql插入缓存表中,页面端在通过缓存表进行渲染,使用这点有个不好之处就是有个定时任务的执行时间差,关于订单业绩相关的我们任务设置的时间就短,尽量不影响使用者.
???????所以这个时间我们需要传递查询指定时间范围内,或者是不指定时间而是指定运行前多少天的数据进行重跑处理.最终参数定义了常用的三个参数

{
    "beginTime":"",
    "endTime":"",
    "beforeDays":"10"
}

xxl-job 的参数接收类

在这里插入图片描述

💨优化前原代码:

伪代码:缓存定时任务

/**
 * @Author itmei
 * @Date 2023/12/22 20:48
 * @description: 任务处理器
 * @Title: CacheTaskHandle
 * @Package com.itmei.xxl.task
 */
@Component
public class CacheTaskHandle {
    @XxlJob("bxCacheTableTask")
    public ReturnT<String> bxCacheTableTask() throws Exception {
        long start = System.currentTimeMillis();
        //获取xxl-job调度传递过来的数据
        String param = XxlJobHelper.getJobParam();
        XxlJobHelper.log("###### Job参数 ######\n{}",param);
        XxlJobParam jobParam;
        if (ObjectUtil.isNotEmpty(param)) {
            jobParam = JSONUtil.toBean(param, XxlJobParam.class);
        } else {
            jobParam = new XxlJobParam();
        }
        DateTime beginTime;
        DateTime endTime;
        if (ObjectUtil.isEmpty(jobParam.getBeginTime()) || ObjectUtil.isEmpty(jobParam.getEndTime())) {
            DateTime startDateTime;
            DateTime endDateTime = DateUtil.date();
            Integer beforeDays = jobParam.getBeforeDays();
            if (ObjectUtil.isEmpty(beforeDays)) {
                //默认开始时间是当前时间向之前偏移46天
                startDateTime = DateUtil.offsetDay(new Date(), -46);
            } else {
                startDateTime = DateUtil.offsetDay(new Date(), -Integer.valueOf(beforeDays));
            }
            beginTime = DateUtil.beginOfDay(startDateTime);
            endTime = DateUtil.endOfDay(endDateTime);
        } else {
            //处理时间范围
            beginTime = DateUtil.beginOfDay(jobParam.getBeginTime());
            endTime = DateUtil.endOfDay(jobParam.getEndTime());
        }
        bxCacheHandle(beginTime,endTime);
        long end = System.currentTimeMillis();
        XxlJobHelper.log("###### Job执行完成,耗时: {} 秒 ######",(end-start)/1000);
        return ReturnT.SUCCESS;
    }
    @XxlJob("bwmCacheTableTask")
    public ReturnT<String> bwmCacheTableTask() throws Exception {
        long start = System.currentTimeMillis();
        //获取xxl-job调度传递过来的数据
        String param = XxlJobHelper.getJobParam();
        XxlJobHelper.log("###### Job参数 ######\n{}",param);
        XxlJobParam jobParam;
        if (ObjectUtil.isNotEmpty(param)) {
            jobParam = JSONUtil.toBean(param, XxlJobParam.class);
        } else {
            jobParam = new XxlJobParam();
        }
        DateTime beginTime;
        DateTime endTime;
        if (ObjectUtil.isEmpty(jobParam.getBeginTime()) || ObjectUtil.isEmpty(jobParam.getEndTime())) {
            DateTime startDateTime;
            DateTime endDateTime = DateUtil.date();
            Integer beforeDays = jobParam.getBeforeDays();
            if (ObjectUtil.isEmpty(beforeDays)) {
                //默认开始时间是当前时间向之前偏移46天
                startDateTime = DateUtil.offsetDay(new Date(), -46);
            } else {
                startDateTime = DateUtil.offsetDay(new Date(), -Integer.valueOf(beforeDays));
            }
            beginTime = DateUtil.beginOfDay(startDateTime);
            endTime = DateUtil.endOfDay(endDateTime);
        } else {
            //处理时间范围
            beginTime = DateUtil.beginOfDay(jobParam.getBeginTime());
            endTime = DateUtil.endOfDay(jobParam.getEndTime());
        }
        bwmCacheHandle(beginTime,endTime);
        long end = System.currentTimeMillis();
        XxlJobHelper.log("###### Job执行完成,耗时: {} 秒 ######",(end-start)/1000);
        return ReturnT.SUCCESS;
    }

    public void bxCacheHandle(Date startTime, Date endTime) {
        /**
         * 伪代码,不能泄密,单纯打印看效果
         */
        XxlJobHelper.log("{}       {}-{} {}       ", "bxCacheTableTask",startTime.toString(),endTime.toString(),"查询缓存数据...");
        XxlJobHelper.log("{}       插入数据         ", "bxCacheTableTask");
    }
    public void bwmCacheHandle(Date startTime, Date endTime) {
        /**
         * 伪代码,不能泄密,单纯打印看效果
         */
        XxlJobHelper.log("{}       {}-{} {}       ", "bwmCacheTableTask",startTime.toString(),endTime.toString(),"查询缓存数据...");
        XxlJobHelper.log("{}       插入数据         ", "bwmCacheTableTask");
    }
}

在这里插入图片描述

???????这些代码都是复用的,除了bxCacheHandle(beginTime,endTime);是处理对应缓存表的逻辑代码,当我需要创建新的缓存表时,我都会把上面的代码复制下来修改@XxlJob("执行名称"),在把bxCacheHandle(beginTime,endTime);修改成对应缓存表查询处理的逻辑,而且他们共同点就是传入的参数都是开始时间和结束时间,并且没有返回值,那么我们就可以使用BiConsumer<T, U>函数式接口来解决.

在这里插入图片描述

???????其实除了时间范围内进行查询,我们还有用到按照传入的时间范围,在按照一天一天维度进行查询,这样的效果就是有些报表一次性查询范围30天会比较久,而且数据库的压力也会提升,我们就需要按照模式去选择,一次性查询一个月还是一个月分30次一天一天的去查询数据.

?? 函数编程简化

我们创建一个专门处理时间查询的类

/**
 * @Author itmei
 * @Date 2023/12/23 14:27
 * @description: 时间范围处理
 * @Title: DateQueryHandle
 * @Package com.itmei.xxl.task
 */
public class DateQueryHandle {

       /**
     * 执行
     * @param syncLogic 是一个函数式接口 BiConsumer<Date, Date> 的实例,用于执行具体的逻辑。该函数式接口接受两个 Date 类型的参数,分别表示开始时间和结束时间
     * @param queryType true 一天一天查询 , false 日期区间查询
     */
    public static void execute(BiConsumer<Date,Date> syncLogic,Boolean queryType){
        long start = System.currentTimeMillis();
        //获取xxl-job调度传递过来的数据
        String param = XxlJobHelper.getJobParam();
        XxlJobHelper.log("###### Job参数 ######\n{}",param);
        XxlJobParam jobParam;
        if (ObjectUtil.isNotEmpty(param)) {
            jobParam = JSONUtil.toBean(param, XxlJobParam.class);
        } else {
            jobParam = new XxlJobParam();
        }
        DateTime beginTime;
        DateTime endTime;
        if (ObjectUtil.isEmpty(jobParam.getBeginTime()) || ObjectUtil.isEmpty(jobParam.getEndTime())) {
            DateTime startDateTime;
            DateTime endDateTime = DateUtil.date();
            Integer beforeDays = jobParam.getBeforeDays();
            if (ObjectUtil.isEmpty(beforeDays)) {
                //默认开始时间是当前时间向之前偏移46天
                startDateTime = DateUtil.offsetDay(new Date(), -46);
            } else {
                startDateTime = DateUtil.offsetDay(new Date(), -Integer.valueOf(beforeDays));
            }
            beginTime = DateUtil.beginOfDay(startDateTime);
            endTime = DateUtil.endOfDay(endDateTime);
        } else {
            //处理时间范围
            beginTime = DateUtil.beginOfDay(jobParam.getBeginTime());
            endTime = DateUtil.endOfDay(jobParam.getEndTime());
        }
        if (queryType) {
            // 按天查询
            long days = DateUtil.between(beginTime, endTime, DateUnit.DAY);
            for (int i = 0; i <= days; i++) {
                DateTime dateTime = DateUtil.offsetDay(beginTime, i);
                DateTime begin = DateUtil.beginOfDay(dateTime);
                DateTime end = DateUtil.endOfDay(dateTime);
                //调用传入的函数式接口实例的方法来执行具体的逻辑
                syncLogic.accept(begin, end);
            }
        } else {
            //调用传入的函数式接口实例的方法来执行具体的逻辑
            syncLogic.accept(beginTime, endTime);
        }
        long end = System.currentTimeMillis();
        XxlJobHelper.log("###### Job执行完成,耗时: {} 秒 ######",(end-start)/1000);
    }

    /**
     * 执行
     * @param syncLogic
     */
    public static void execute(BiConsumer<Date,Date> syncLogic){
        //重载方法 使用时间范围内的查询
        execute(syncLogic,false);
    }
}

🎄 JDK自带的函数式接口

???????唯一不一样的是使用了 JDK 1.8 中函数式接口BiConsumer,这个接口默认可以传递2个参数.除了这个JDK 1.8 中还提供了这些常用的函数式接口:

Consumer<T>:接受一个输入参数 T,没有返回值。
Supplier<T>:不接受任何输入参数,返回一个结果 T。
Function<T, R>:接受一个输入参数 T,返回一个结果 R。
Predicate<T>:接受一个输入参数 T,返回一个布尔值。
UnaryOperator<T>:接受一个输入参数 T,返回一个结果 T,输入类型和返回类型相同。
BinaryOperator<T>:接受两个输入参数 T,返回一个结果 T,输入类型和返回类型相同。
BiConsumer<T, U>:接受两个输入参数 T 和 U,没有返回值。
BiFunction<T, U, R>:接受两个输入参数 T 和 U,返回一个结果 R。
BiPredicate<T, U>:接受两个输入参数 T 和 U,返回一个布尔值。

???????由于我们简化的代码中并没有返回值,而且需要传入2个参数,这样我们就选择了BiConsumer<T, U>做为本次使用到的函数式接口.

? 改造调用方式

🎊 时间范围执行

我们改造bwmCacheTableTask代码,改成函数式接口方式调用

在这里插入图片描述

运行结果

在这里插入图片描述
在这里插入图片描述

改造后,我们只需要一行代码就可以,完成了代码的复用性

在这里插入图片描述

改造后的运行结果和改造前运行结果是一样的,这样是不是代码就更简化

在这里插入图片描述

🎉时间范围每天执行

改造bxCacheTableTask代码为,时间范围内,一天一天的执行效果

在这里插入图片描述

执行效果

在这里插入图片描述

按照时间范围内,进行一天一天查询

在这里插入图片描述

文章来源:https://blog.csdn.net/qq_45502336/article/details/135160661
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。