欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java子線程調(diào)用RequestContextHolder.getRequestAttributes()方法問(wèn)題詳解

 更新時(shí)間:2022年09月27日 09:43:51   作者:ypp91zr  
這篇文章主要介紹了Java子線程調(diào)用RequestContextHolder.getRequestAttributes()方法問(wèn)題處理,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

相信很多開(kāi)發(fā)過(guò)程中都用過(guò)RequestContextHolder.getRequestAttributes(),沒(méi)錯(cuò),我也經(jīng)常用,但今天出現(xiàn)了問(wèn)題,獲取到的實(shí)例是空的

原因是因?yàn)槲倚麻_(kāi)了一個(gè)子線程,在子線程調(diào)用了RequestContextHolder.getRequestAttributes()。實(shí)際獲取到的是空的

然后查看了源碼

ThreadLocal獲取。一個(gè)請(qǐng)求到達(dá)容器后,Spring會(huì)把該請(qǐng)求Request實(shí)例通過(guò)setRequestAttributes方法 把Request實(shí)例放入該請(qǐng)求線程內(nèi)ThreadLocalMap中,然后就可以通過(guò)靜態(tài)方法取到。原理就是ThreadLocal,但ThreadLocal不能讓子線程繼承ThreadLocalMap信息,可以使用InherbritableThreadLocal實(shí)現(xiàn)子線程信息傳遞。

Spring Boot 默認(rèn)使用ThreadLocal把Request設(shè)置進(jìn)請(qǐng)求線程中,這樣如果在請(qǐng)求方法里面另起一個(gè)子線程然后再通過(guò)getRequestAttributes方法獲取,是獲取不到的

如果想要在子線程獲取,設(shè)置inheritable=true即可,但我一直沒(méi)找到在哪里可以設(shè)置,于是自己就寫(xiě)了個(gè)工具類(lèi)來(lái)讓子線程獲取,思路是自定義一個(gè)注解,攔截注解,將父線程的ServletRequestAttributes給InheritableThreadLocal,然后在子線程即可獲取

package com.shinedata.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestInheritableThread {
}

AOP

package com.shinedata.aop;
import com.shinedata.util.context.RequestHolder;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.ServletRequestAttributes;
@Aspect
@Component
public class RequestHolderAspect {
    @Before("@annotation(com.shinedata.annotation.RequestInheritableThread)")
    public void doBefore(JoinPoint joinPoint) {
        ServletRequestAttributes servletRequestAttributes = RequestHolder.getServletRequestAttributes();
        RequestHolder.setServletRequestAttributes(servletRequestAttributes);
    }
    @After("@annotation(com.shinedata.annotation.RequestInheritableThread)")
    public void doAfter(JoinPoint joinPoint) {
        RequestHolder.removeServletRequestAttributes();
    }
}

工具類(lèi)

package com.shinedata.util.context;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
/**
 * @ClassName RequestHolder
 * @Author yupanpan
 */
public class RequestHolder {
    private static final Logger logger = LoggerFactory.getLogger(RequestHolder.class);
    public static final String GET = "GET";
    public static final String POST = "POST";
    public static final String UTF8 = "UTF-8";
    public static InheritableThreadLocal<ServletRequestAttributes> servletRequestAttributesInheritableThreadLocal= new InheritableThreadLocal();
    public static HttpServletRequest getRequest() {
        return getServletRequestAttributes().getRequest();
    }
    public static HttpServletResponse getResponse() {
        return getServletRequestAttributes().getResponse();
    }
    public static ServletRequestAttributes setServletRequestAttributes(ServletRequestAttributes servletRequestAttributes) {
        servletRequestAttributesInheritableThreadLocal.set(servletRequestAttributes);
        return servletRequestAttributes;
    }
    public static void removeServletRequestAttributes() {
        servletRequestAttributesInheritableThreadLocal.remove();
    }
    public static ServletRequestAttributes getServletRequestAttributes() {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
        if(requestAttributes==null){
            requestAttributes=servletRequestAttributesInheritableThreadLocal.get();
        }
        return requestAttributes;
    }
}

需要在子線程獲取ServletRequestAttributes使用的時(shí)候在父方法貼個(gè)注解@RequestInheritableThread就行了,父方法里面即使開(kāi)子線程,子線程里面也能獲取ServletRequestAttributes

補(bǔ)充第二種解決辦法,在開(kāi)啟新線程之前,將RequestAttributes對(duì)象設(shè)置為子線程共享

//開(kāi)啟新線程之前,添加代碼:
ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
RequestContextHolder.setRequestAttributes(sra, true);

到此這篇關(guān)于Java子線程調(diào)用RequestContextHolder.getRequestAttributes()方法問(wèn)題詳解的文章就介紹到這了,更多相關(guān)Java RequestContextHolder.getRequestAttributes()內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • IDEA新建Springboot項(xiàng)目(圖文教程)

    IDEA新建Springboot項(xiàng)目(圖文教程)

    下面小編就為大家?guī)?lái)一篇IDEA新建Springboot項(xiàng)目(圖文教程)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-07-07
  • 詳解java如何處理各種批量數(shù)據(jù)入庫(kù)

    詳解java如何處理各種批量數(shù)據(jù)入庫(kù)

    這篇文章主要為大家詳細(xì)介紹了java如何使用BlockingQueue處理各種批量數(shù)據(jù)入庫(kù),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-11-11
  • Java后臺(tái)返回和處理JSon數(shù)據(jù)的方法步驟

    Java后臺(tái)返回和處理JSon數(shù)據(jù)的方法步驟

    這篇文章主要介紹了Java后臺(tái)返回和處理JSon數(shù)據(jù)的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • 利用Spring插件實(shí)現(xiàn)策略模式的案例詳解

    利用Spring插件實(shí)現(xiàn)策略模式的案例詳解

    Spring插件提供了一種更實(shí)用的插件開(kāi)發(fā)方法,它提供了插件實(shí)現(xiàn)擴(kuò)展核心系統(tǒng)功能的核心靈活性,但當(dāng)然不提供核心OSGi功能,如動(dòng)態(tài)類(lèi)加載或運(yùn)行時(shí)安裝和部署插件,本文就來(lái)聊下如何使用spring插件來(lái)實(shí)現(xiàn)策略模式,需要的朋友可以參考下
    2023-05-05
  • SpringBoot異常處理器的使用與添加員工功能實(shí)現(xiàn)流程介紹

    SpringBoot異常處理器的使用與添加員工功能實(shí)現(xiàn)流程介紹

    設(shè)計(jì)完了登錄與退出功能還只完成了冰山一角,經(jīng)過(guò)測(cè)試發(fā)現(xiàn),我們以u(píng)rl的方式來(lái)訪問(wèn)網(wǎng)站時(shí)可以直接跳過(guò)登陸頁(yè)面進(jìn)入后臺(tái)頁(yè)面,這樣顯然是不合理的,下面我們通過(guò)異常攔截器+boot來(lái)做到訪問(wèn)限制,以及實(shí)現(xiàn)新增員工功能,制作全局異常處理器
    2022-10-10
  • SpringBoot項(xiàng)目運(yùn)行jar包啟動(dòng)的步驟流程解析

    SpringBoot項(xiàng)目運(yùn)行jar包啟動(dòng)的步驟流程解析

    這篇文章主要介紹了SpringBoot項(xiàng)目運(yùn)行jar包啟動(dòng)的步驟流程,本文分步驟通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2020-07-07
  • springmvc如何進(jìn)行異常處理

    springmvc如何進(jìn)行異常處理

    這篇文章主要介紹了springmvc如何進(jìn)行異常處理,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-09-09
  • SpringBoot 防御 CSRF 攻擊的流程及原理解析

    SpringBoot 防御 CSRF 攻擊的流程及原理解析

    CSRF是一種非常常見(jiàn)的Web攻擊方式,其實(shí)是很好防御的,但是由于經(jīng)常被很多開(kāi)發(fā)者忽略,進(jìn)而導(dǎo)致很多網(wǎng)站實(shí)際上都存在 CSRF 攻擊的安全隱患,這篇文章主要介紹了SpringBoot 如何防御 CSRF 攻擊,需要的朋友可以參考下
    2023-05-05
  • Servlet虛擬路徑映射配置詳解

    Servlet虛擬路徑映射配置詳解

    這篇文章主要介紹了Servlet虛擬路徑映射配置詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-02-02
  • Java實(shí)現(xiàn)二叉搜索樹(shù)的插入、刪除功能

    Java實(shí)現(xiàn)二叉搜索樹(shù)的插入、刪除功能

    這篇文章主要介紹了Java實(shí)現(xiàn)二叉搜索樹(shù)的插入、刪除,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-01-01

最新評(píng)論