diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/config/AsyncConfig.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/config/AsyncConfig.java new file mode 100644 index 00000000..02b18d04 --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/config/AsyncConfig.java @@ -0,0 +1,93 @@ +package com.ruoyi.common.core.config; + +import cn.hutool.core.util.ArrayUtil; +import com.ruoyi.common.core.exception.ServiceException; +import com.ruoyi.common.core.utils.SpringUtils; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.concurrent.BasicThreadFactory; +import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.AsyncConfigurerSupport; +import org.springframework.scheduling.annotation.EnableAsync; + +import java.util.Arrays; +import java.util.concurrent.*; + +/** + * 异步配置 + * + * @author Lion Li + */ +@Slf4j +@EnableAsync +@Configuration +public class AsyncConfig extends AsyncConfigurerSupport { + + private static final int CORE_POOL_SIZE = 10; + + /** + * 执行周期性或定时任务 + */ + @Bean(name = "scheduledExecutorService") + public ScheduledExecutorService scheduledExecutorService() { + return new ScheduledThreadPoolExecutor(CORE_POOL_SIZE, + new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build(), + new ThreadPoolExecutor.CallerRunsPolicy()) { + @Override + protected void afterExecute(Runnable r, Throwable t) { + super.afterExecute(r, t); + printException(r, t); + } + }; + } + + /** + * 自定义 @Async 注解使用系统线程池 + */ + @Override + public Executor getAsyncExecutor() { + return SpringUtils.getBean("scheduledExecutorService"); + } + + /** + * 异步执行异常处理 + */ + @Override + public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { + return (throwable, method, objects) -> { + throwable.printStackTrace(); + StringBuilder sb = new StringBuilder(); + sb.append("Exception message - ").append(throwable.getMessage()) + .append(", Method name - ").append(method.getName()); + if (ArrayUtil.isNotEmpty(objects)) { + sb.append(", Parameter value - ").append(Arrays.toString(objects)); + } + throw new ServiceException(sb.toString()); + }; + } + + /** + * 打印线程异常信息 + */ + public void printException(Runnable r, Throwable t) { + if (t == null && r instanceof Future) { + try { + Future future = (Future) r; + if (future.isDone()) { + future.get(); + } + } catch (CancellationException ce) { + t = ce; + } catch (ExecutionException ee) { + t = ee.getCause(); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + } + } + if (t != null) { + log.error(t.getMessage(), t); + } + } + +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/resources/META-INF/spring.factories b/ruoyi-common/ruoyi-common-core/src/main/resources/META-INF/spring.factories index 2cceb286..2241e9b8 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/resources/META-INF/spring.factories +++ b/ruoyi-common/ruoyi-common-core/src/main/resources/META-INF/spring.factories @@ -2,6 +2,7 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.ruoyi.common.core.utils.SpringUtils,\ com.ruoyi.common.core.config.ApplicationConfig,\ com.ruoyi.common.core.config.JacksonConfig,\ - com.ruoyi.common.core.config.ValidatorConfig + com.ruoyi.common.core.config.ValidatorConfig,\ + com.ruoyi.common.core.config.AsyncConfig