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 包装返回 AsyncResult 是 Future 接口的子类,所以也可以通过 future.get() 获取返回值的时候捕获 ExcecutionException。

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


作者:有帮助请找ADC

来源链接:

https://blog.csdn.net/weixin_38361347/article/details/101170795

87948c9421e5e5e4f5550678c57706a5.png

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SpringBoot异步方法是指在SpringBoot项目中使用异步处理的方法。在SpringBoot中,可以通过使用注解@EnableAsync来开启Spring异步支持。[1]然而,在Spring Boot项目中不能使用@EnableWebMvc来开启异步处理,因为它会使Spring Boot的AutoConfigure部分功能失效。 在Java中,异步处理可以使用Thread/Runnable、Callable/Future等方式实现。在Servlet 2.5中,可以使用Tomcat的CometProcessor、Jetty的Continuations等方式实现异步处理。而在Servlet 3.0中,可以使用asyncSupported、AsyncContext等方式实现异步处理。而在Spring MVC中,可以使用@Async、AsyncTaskExecutor等方式实现异步处理。在Spring Boot中,基本上还是使用Spring MVC的@Async注解来实现异步处理。 要开启Spring异步支持,可以在@Configuration配置类中使用@EnableAsync注解。例如: @Configuration @EnableAsync public class SpringAsyncConfig { } 这样就可以在SpringBoot项目中使用异步方法了。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [SpringBoot异步方法捕捉异常详解](https://download.csdn.net/download/weixin_38689338/12746339)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [SpringBoot异步调用方法](https://blog.csdn.net/paladinzh/article/details/89478362)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值