springBoot的定时器应该这样写

公司的结算模块业务线概括:需要一个定时任务去监测符合结算条件的数据,然后进行各个用户的分账。

springBoot的定时器应该这样写

这里使用到了springBoot 集成的定时器 Spring Task ,为了数据安全,也更高效,使用到了多线程执行。

首先创建一个初始化线程的类

(图1)

@Configuration

public class ScheduleConfig implements SchedulingConfigurer, AsyncConfigurer {

@Override

public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {

TaskScheduler taskScheduler = taskScheduler();

scheduledTaskRegistrar.setTaskScheduler(taskScheduler);

}

/**

* 初始化线程池

* @return

*/

@Bean(destroyMethod = "shutdown")//通知关闭线程池

public ThreadPoolTaskScheduler taskScheduler() {

ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();

scheduler.setPoolSize(5);

// 设置线程名前缀

scheduler.setThreadNamePrefix("task-");

// 等待所有线程执行完

scheduler.setWaitForTasksToCompleteOnShutdown(true);

return scheduler;

}

/**

* 异步任务

* @return

*/

@Override

public Executor getAsyncExecutor() {

Executor executor = taskScheduler();

return executor;

}

/**

* 异常处理

* @return

*/

@Override

public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {

return new SimpleAsyncUncaughtExceptionHandler();

}

初始化5个线程来处理业务。

这里我们可以简单的看一下源码,为什么要初始化线程的数量

因为(图1)实现了SchedulingConfigurer 这个类,(图2) SchedulingConfigurer 类并没有对线程数量进行约束,所以我们为了提高业务处理量,我们手动创建线程数量来处理数据。我们只需图1 重写 SchedulingConfigurer 里的 configureTasks 方法,就可以完成创建线程数量。

(图2)

package org.springframework.scheduling.annotation;

import org.springframework.scheduling.config.ScheduledTaskRegistrar;

@FunctionalInterface

public interface SchedulingConfigurer {

void configureTasks(ScheduledTaskRegistrar var1);

}

创建一个 DynamicScheduledTask 类 实现 SchedulingConfigurer 我们就可以重写线程类了。

@Configuration

@EnableScheduling

public class DynamicScheduledTask implements SchedulingConfigurer {

// 定时器执行频率,半小时一次 0 0/30 * * * ?

private static final String DEFAULT_CRON = "0 0/5 * * * ?";//五分钟执行一次

private String cron = DEFAULT_CRON;

@Override

public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {

scheduledTaskRegistrar.addTriggerTask(new Runnable() {

@Override

public void run() {

doBiz();

}

}, new Trigger() {

@Override

public Date nextExecutionTime(TriggerContext triggerContext) {

// 定时任务触发,可修改定时任务的执行周期

CronTrigger trigger = new CronTrigger(cron);

Date nextExecDate = trigger.nextExecutionTime(triggerContext);

return nextExecDate;

}

});

}

/**

* 定时器执行方法

*/

public void doBiz() {

}

public String getCron() {

return cron;

}

public void setCron(String cron) {

this.cron = cron;

}

}

好奇的童鞋可以点进去看一下源码,大概理解其思想,是有帮助的。

下面我们开始编写业务类,就是处理结算数据的代码模块

package com.example.fuxing.taskConfig;

public class test {

/**

* 扫描子订单表下订单状态值为4的数据,进行结算分账

*/

@Component

@Service

@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)

public class ScanOrderTask extends DynamicScheduledTask {

@Resource

TimerService timerService;

private Logger log = LoggerFactory.getLogger(this.getClass());

public void doBiz() {

try {

DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

log.info("定时器开始执行" + sdf.format(new Date()) + "秒");

List<fxordermedia> fxOrderMedia = timerService.runTimer();/<fxordermedia>

if (null != fxOrderMedia && fxOrderMedia.size() != 0) {

//执行代理商及平台分成

selectFxOrderMedia("");

}

} catch (Exception e) {

throw new ResponseJsonException(FXErrorCode.Error, e.getMessage());

}

}

/**

* 查询订单的信息

*

* @param mediaOrdercode

* @return

*/

FxOrderMedia selectFxOrderMedia(String mediaOrdercode) {

//查询订单的信息

FxOrderMedia fxOrderMedia = timerService.selectFxOrderMedia(mediaOrdercode);

JSONObject json = JSONObject.fromObject(fxOrderMedia);

log.info("------所要结算的订单信息-------" + json.toString());

//判断此订单是否为代理商下的订单

if (!StringUtils.isEmpty(fxOrderMedia.getAgentcode()) && fxOrderMedia.getCommissionRatio() != new BigDecimal(0)) {

//代理商分成

Map<string> returnDate = agencyShare(fxOrderMedia);/<string>

if ("false".equals(returnDate.get("return").toString())) {

throw new ResponseJsonException(FXErrorCode.Error, "代理商分成失败!");

}

}

//如果不是代理商用户

Map<string> map = platformDivision(fxOrderMedia);/<string>

if ("false".equals(map.get("return").toString())) {

throw new ResponseJsonException(FXErrorCode.Error, "平台分成失败!");

}

return fxOrderMedia;

}

/**

* 代理商分成业务

*/

private Map<string> agencyShare(FxOrderMedia fxOrderMedia) {/<string>

//分账A

return null;

}

/**

* 平台分成业务

*/

private Map<string> platformDivision(FxOrderMedia fxOrderMedia) {/<string>

//分账B

return null;

}

}

}

如有不对,请其指出,希望我们在前进的道路上互帮互助。


分享到:


相關文章: