最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

解決Springboot中@Async注解獲取不到上下文信息問(wèn)題

 更新時(shí)間:2024年01月15日 11:49:46   作者:飛翔的佩奇  
實(shí)際開(kāi)發(fā)中我們經(jīng)常需要通過(guò)spring上下文獲取一些配置信息,本文主要介紹了解決Springboot中@Async注解獲取不到上下文信息問(wèn)題,具有一定的參考價(jià)值,感興趣的可以了解一下

問(wèn)題描述

springboot項(xiàng)目中,需要使用到異步調(diào)用某個(gè)方法,此時(shí) 第一個(gè)想到的就是 @Async 注解,但是 發(fā)現(xiàn) 方法執(zhí)行報(bào)錯(cuò)了,具體報(bào)錯(cuò)如下:

java.lang.NullPointerException
    at com.ruoyi.common.utils.ServletUtils.getRequest(ServletUtils.java:56)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:782)
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:717)
    at org.springframework.web.client.RestTemplate.postForObject(RestTemplate.java:443)
    at com.ruoyi.web.ecs.service.impl.EcsCollectOperateServiceImpl.collect(EcsCollectOperateServiceImpl.java:42)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:90)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
    at java.lang.reflect.Method.invoke(Method.java:508)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.aop.interceptor.AsyncExecutionInterceptor.lambda$invoke$0(AsyncExecutionInterceptor.java:115)
    at java.util.concurrent.FutureTask.run(FutureTask.java:277)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1160)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
    at java.lang.Thread.run(Thread.java:825)

上面日志有點(diǎn)多,其實(shí)核心就是這一部分日志:

java.lang.NullPointerException
    at com.ruoyi.common.utils.ServletUtils.getRequest(ServletUtils.java:56)

這塊邏輯就是,使用spring底層提供的獲取上下文信息的方法。
所以說(shuō)明 獲取不到上下文信息,結(jié)果導(dǎo)致報(bào)錯(cuò)

解決辦法

  • 對(duì)自定義的配置類 進(jìn)行改造,原來(lái)的配置類是這樣的:
import java.lang.reflect.Method;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

@Configuration
@EnableAsync
public class AsyncConfiguration {

	private static final Logger logger = LoggerFactory.getLogger(AsyncConfiguration.class);

	@Bean(name = "taskExecutor")
	public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();

        // 核心線程數(shù):線程池創(chuàng)建時(shí)候初始化的線程數(shù)
        taskExecutor.setCorePoolSize(10);

        // 最大線程數(shù):線程池最大的線程數(shù),只有在緩沖隊(duì)列滿了之后才會(huì)申請(qǐng)超過(guò)核心線程數(shù)的線程
        taskExecutor.setMaxPoolSize(20);

        // 緩沖隊(duì)列:用來(lái)緩沖執(zhí)行任務(wù)的隊(duì)列
        taskExecutor.setQueueCapacity(50);

        // 允許線程的空閑時(shí)間60秒:當(dāng)超過(guò)了核心線程之外的線程在空閑時(shí)間到達(dá)之后會(huì)被銷毀
        taskExecutor.setKeepAliveSeconds(60);

        // 線程池名的前綴:設(shè)置好了之后可以方便我們定位處理任務(wù)所在的線程池
        taskExecutor.setThreadNamePrefix("HiTask-");

        // 緩沖隊(duì)列滿了之后的拒絕策略:由調(diào)用線程處理(一般是主線程)
        //taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());
        taskExecutor.initialize();

        return taskExecutor;
    }



	class MyAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {

		@Override
		public void handleUncaughtException(Throwable throwable, Method method, Object... objects) {
			logger.error("MethodName={},Throwable={}",method.getName(),throwable.toString());
		}
	}
}
  • 改造之后:
import java.lang.reflect.Method;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

@Configuration
@EnableAsync
public class AsyncConfiguration {

	private static final Logger logger = LoggerFactory.getLogger(AsyncConfiguration.class);

	@Bean(name = "taskExecutor")
	public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();

        // 核心線程數(shù):線程池創(chuàng)建時(shí)候初始化的線程數(shù)
        taskExecutor.setCorePoolSize(10);

        // 最大線程數(shù):線程池最大的線程數(shù),只有在緩沖隊(duì)列滿了之后才會(huì)申請(qǐng)超過(guò)核心線程數(shù)的線程
        taskExecutor.setMaxPoolSize(20);

        // 緩沖隊(duì)列:用來(lái)緩沖執(zhí)行任務(wù)的隊(duì)列
        taskExecutor.setQueueCapacity(50);

        // 允許線程的空閑時(shí)間60秒:當(dāng)超過(guò)了核心線程之外的線程在空閑時(shí)間到達(dá)之后會(huì)被銷毀
        taskExecutor.setKeepAliveSeconds(60);

        // 線程池名的前綴:設(shè)置好了之后可以方便我們定位處理任務(wù)所在的線程池
        taskExecutor.setThreadNamePrefix("HiTask-");

        // 緩沖隊(duì)列滿了之后的拒絕策略:由調(diào)用線程處理(一般是主線程)
        //taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());
        taskExecutor.initialize();

        //解決使用@Async注解,獲取不到上下文信息的問(wèn)題
        taskExecutor.setTaskDecorator(runnable -> {
            RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
            return ()->{
                try {
                    // 我們set 進(jìn)去 ,其實(shí)是一個(gè)ThreadLocal維護(hù)的.
                    RequestContextHolder.setRequestAttributes(requestAttributes);
                    runnable.run();
                } finally {
                    // 最后記得釋放內(nèi)存
                    RequestContextHolder.resetRequestAttributes();
                }
            };

        });

        return taskExecutor;
    }



	class MyAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {

		@Override
		public void handleUncaughtException(Throwable throwable, Method method, Object... objects) {
			logger.error("MethodName={},Throwable={}",method.getName(),throwable.toString());
		}
	}
}

總結(jié)

解決使用@Async注解,獲取不到上下文信息的問(wèn)題,只需要增加這一段代碼即可

 taskExecutor.setTaskDecorator(runnable -> {
            RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
            return ()->{
                try {
                    // 我們set 進(jìn)去 ,其實(shí)是一個(gè)ThreadLocal維護(hù)的.
                    RequestContextHolder.setRequestAttributes(requestAttributes);
                    runnable.run();
                } finally {
                    // 最后記得釋放內(nèi)存
                    RequestContextHolder.resetRequestAttributes();
                }
            };

        });

額外補(bǔ)充一點(diǎn)

如果使用 @Async注解,發(fā)現(xiàn)沒(méi)有生效,那有可能 你沒(méi)有加 @EnableAsync 注解。
@EnableAsync注解表示 開(kāi)啟異步任務(wù),可以寫(xiě)在springboot的啟動(dòng)類上,也可以寫(xiě)在 配置類上

到此這篇關(guān)于解決Springboot中@Async注解獲取不到上下文信息問(wèn)題的文章就介紹到這了,更多相關(guān)Springboot @Async獲取上下文內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • springboot3 使用 jasypt 加密配置文件的使用步驟

    springboot3 使用 jasypt 加密配置文件的使用步驟

    在SpringBoot項(xiàng)目中,使用Jasypt加密配置文件可以有效保護(hù)敏感信息,首先,需添加Jasypt依賴并配置加密密碼,可在application.properties或通過(guò)啟動(dòng)參數(shù)、環(huán)境變量設(shè)置,本文介紹了Jasypt的配置步驟及使用方法,幫助開(kāi)發(fā)者保護(hù)應(yīng)用配置信息
    2024-11-11
  • 如何使用Gradle實(shí)現(xiàn)類似Maven的profiles功能

    如何使用Gradle實(shí)現(xiàn)類似Maven的profiles功能

    這篇文章主要介紹了如何使用Gradle實(shí)現(xiàn)類似Maven的profiles功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2024-06-06
  • Java Shutdown Hook場(chǎng)景使用及源碼分析

    Java Shutdown Hook場(chǎng)景使用及源碼分析

    shutdown hook 就是一個(gè)簡(jiǎn)單的已初始化但是未啟動(dòng)的線程,本文詳細(xì)的介紹了Java Shutdown Hook場(chǎng)景使用及源碼分析,感興趣的朋友可以參考一下
    2021-06-06
  • 解決feign接口返回泛型設(shè)置屬性為null的問(wèn)題

    解決feign接口返回泛型設(shè)置屬性為null的問(wèn)題

    這篇文章主要介紹了解決feign接口返回泛型設(shè)置屬性為null的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • Spring應(yīng)用中使用acutator/refresh刷新屬性不生效的問(wèn)題分析及解決

    Spring應(yīng)用中使用acutator/refresh刷新屬性不生效的問(wèn)題分析及解決

    在Spring應(yīng)用收到/actuator/refresh的POST請(qǐng)求后,標(biāo)注了@RefreshScope以及@ConfiguratioinProperties的bean會(huì)被Spring容器重新加載,但是,在實(shí)際應(yīng)用中,并沒(méi)有按照預(yù)期被Spring容器加載,本文將討論導(dǎo)致這種未按預(yù)期刷新的一種原因,感興趣的朋友可以參考下
    2024-01-01
  • mybatis plus in方法使用說(shuō)明

    mybatis plus in方法使用說(shuō)明

    這篇文章主要介紹了mybatis plus in方法使用說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-11-11
  • JAVA語(yǔ)法糖原理你知道嗎

    JAVA語(yǔ)法糖原理你知道嗎

    語(yǔ)法糖(Syntactic sugar),也叫做糖衣語(yǔ)法,是英國(guó)科學(xué)家發(fā)明的一個(gè)術(shù)語(yǔ),通常來(lái)說(shuō)使用語(yǔ)法糖能夠增加程序的可讀性,從而減少程序代碼出錯(cuò)的機(jī)會(huì).這篇文章主要介紹了Java 中的語(yǔ)法糖知識(shí),需要的朋友可以參考下
    2021-09-09
  • springboot項(xiàng)目實(shí)現(xiàn)斷點(diǎn)續(xù)傳功能

    springboot項(xiàng)目實(shí)現(xiàn)斷點(diǎn)續(xù)傳功能

    這篇文章主要介紹了springboot項(xiàng)目實(shí)現(xiàn)斷點(diǎn)續(xù)傳,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-08-08
  • jdk8的datetime時(shí)間函數(shù)使用示例

    jdk8的datetime時(shí)間函數(shù)使用示例

    這篇文章主要介紹了jdk8的datetime時(shí)間函數(shù)使用示例,需要的朋友可以參考下
    2014-03-03
  • java easyUI實(shí)現(xiàn)自定義網(wǎng)格視圖實(shí)例代碼

    java easyUI實(shí)現(xiàn)自定義網(wǎng)格視圖實(shí)例代碼

    這篇文章主要給大家介紹了關(guān)于java easyUI實(shí)現(xiàn)自定義網(wǎng)格視圖的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2018-10-10

最新評(píng)論

新竹市| 桃园市| 康定县| 锦州市| 广州市| 苍溪县| 沅陵县| 兴义市| 阳西县| 大宁县| 舟曲县| 临澧县| 和静县| 玉环县| 马山县| 新源县| 阳高县| 崇仁县| 石阡县| 玉门市| 浮山县| 东丰县| 华坪县| 宁河县| 塔河县| 芜湖县| 武宁县| 吉安市| 霍山县| 颍上县| 阜宁县| 平度市| 巨野县| 崇左市| 贵溪市| 建平县| 东丽区| 宜兰市| 凤山县| 太仆寺旗| 西峡县|