SpringBoot异步方法捕捉异常详解

网友投稿 553 2022-12-26


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

* @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 包装返回

AsyncResult是Future接口的子类,所以也可以通过future.get()获取返回值的时候捕获ExcecutionException。

@Async

public Future asyncMethod() {

try {

Thread.sleep(5000);

return new AsyncResult("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 {

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做了标注,是可以实现事务控制的目的。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:在线开发接口测试工具(软件测试接口工具)
下一篇:Java利用策略模式优化过多if else代码
相关文章

 发表评论

暂时没有评论,来抢沙发吧~