SpringBoot异步方法捕捉异常详解
本文实例为大家分享了SpringBoot异步方法捕捉异常的具体代码,供大家参考,具体内容如下 由于项目中定时器都采用异步执行方式 需要定时监控异步方法执行进度,异常情况 1 执行进度 可以设置是否在执行,内存中添加执行标识即可。 防止多次执行可以通过拦截器对此,标识来判断,防止多次执行定时器 2 异常捕捉 监控异步方法执行是否异常。 1 无返回值 配置AsyncExceptionConfig类,统一处理。 定义异常捕获配置类AsyncExceptionConfig,配置类里面定义SpringAsyncExceptionHandler 方法实现AsyncUncaughtExceptionHandler 接口。 代码如下: package cn.bwjf.config; import cn.bwjf.common.constant.InitServiceIdEnum; import cn.bwjf.common.tools.InitServiceUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.AsyncConfigurer; /** * @description : 异常捕获配置类 * @author : tizzy <br/> * @version : 1.0 * @date 2019/9/21 */ @Configuration @Slf4j public class AsyncExceptionConfig implements AsyncConfigurer { /** * @description : 设置异步方法线程参数 * @author : tizzy * @version : 1.0 */ @Bean @Override public Executor getAsyncExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); //根据自己机器配置 executor.setCorePoolSize(8); executor.setMaxPoolSize(16); executor.setQueueCapacity(64); executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); executor.setThreadNamePrefix("SpringAsyncThread-"); return executor; } @Override public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { return new SpringAsyncExceptionHandler(); } class SpringAsyncExceptionHandler implements AsyncUncaughtExceptionHandler { @Override public void handleUncaughtException(Throwable throwable,Method method,Object... objects) { log.info("------我是Async无返回方法的异常处理方法---------"); //通过反射获取各个初始化方法名字 String methodName = method.getName(); log.info(" 当前异常方法名 == {} ",methodName); //根据方法名字 记录异常 略。。。。 log.info("------我是Async无返回方法的异常处理方法---------"); } } } 2 有返回值 返回值 用 AsyncResult 包装返回 @Async public Future<String> asyncMethod() { try { Thread.sleep(5000); return new AsyncResult<String>("hello world !!!!"); } catch (InterruptedException e) { // } return null; } 调用 try { Future future = service.asyncMethod(); future.get(); } catch (ExecutionException e) { logger.error("exception occurs",e); } catch (InterruptedException e) { logger.error("exception occurs",e); } 什么是 Future类型? Future是对于具体的 Runnable或者 Callable任务的执行结果进行取消、查询是否完成、获取结果的接口。必要时可以通过get方法获取执行结果,该方法会阻塞直到任务返回结果。 它的接口定义如下: public interface Future<V> { boolean cancel(boolean mayInterruptIfRunning); boolean isCancelled(); boolean isDone(); V get() throws InterruptedException,ExecutionException; V get(long timeout,TimeUnit unit) throws InterruptedException,ExecutionException,TimeoutException; } 它声明这样的五个方法: cancel方法用来取消任务,如果取消任务成功则返回true,如果取消任务失败则返回false。参数mayInterruptIfRunning表示是否允许取消正在执行却没有执行完毕的任务,如果设置true,则表示可以取消正在执行过程中的任务。如果任务已经完成,则无论mayInterruptIfRunning为true还是false,此方法肯定返回false,即如果取消已经完成的任务会返回false;如果任务正在执行,若mayInterruptIfRunning设置为true,则返回true,若mayInterruptIfRunning设置为false,则返回false;如果任务还没有执行,则无论mayInterruptIfRunning为true还是false,肯定返回true。 isCancelled方法表示任务是否被取消成功,如果在任务正常完成前被取消成功,则返回 true。 isDone方法表示任务是否已经完成,若任务完成,则返回true; get()方法用来获取执行结果,这个方法会产生阻塞,会一直等到任务执行完毕才返回; get(long timeout,TimeUnit unit)用来获取执行结果,如果在指定时间内,还没获取到结果,就直接返回null。 也就是说Future提供了三种功能: 判断任务是否完成; 能够中断任务; 能够获取任务执行结果。 3 异步方法中事务 @Async调用中的事务处理机制 在@Async标注的方法,同时也适用了@Transactional进行了标注;在其调用数据库操作之时,将无法产生事务管理的控制,原因就在于其是基于异步处理的操作。 正确做法 如何给这些操作添加事务管理呢?可以将需要事务管理操作的方法放置到异步方法内部,在内部被调用的方法上添加@Transactional. 例如: 方法A,使用了@Async/@Transactional来标注,但是无法产生事务控制的目的。 方法B,使用了@Async来标注, B中调用了C、D,C/D分别使用@Transactional做了标注,是可以实现事务控制的目的。 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |