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

Spring中的@CrossOrigin注冊處理方法源碼解析

 更新時間:2023年12月02日 10:54:28   作者:securitit  
這篇文章主要介紹了Spring中的@CrossOrigin注冊處理方法源碼解析,@CrossOrigin是基于@RequestMapping,@RequestMapping注釋方法掃描注冊的起點是equestMappingHandlerMapping.afterPropertiesSet(),需要的朋友可以參考下

前言

@CrossOrigin源碼解析主要分為兩個階段:

① @CrossOrigin注釋的方法掃描注冊。

② 請求匹配@CrossOrigin注釋的方法。

本文針對第①階段從源碼角度進(jìn)行解析,關(guān)于第②階段請參照《Spring 注解面面通 之 @CrossOrigin 處理請求源碼解析》。

注意:@CrossOrigin是基于@RequestMapping,@RequestMapping注釋方法掃描注冊的起點是RequestMappingHandlerMapping.afterPropertiesSet()。

@CrossOrigin注釋方法掃描注冊

@CrossOrigin注釋方法掃描注冊流程

在這里插入圖片描述

1) RequestMappingHandlerMapping.afterPropertiesSet()、AbstractHandlerMethodMapping.afterPropertiesSet()、AbstractHandlerMethodMapping.initHandlerMethods()、AbstractHandlerMethodMapping.detectHandlerMethods(...)、AbstractHandlerMethodMapping.registerHandlerMethod(...)方法。

2) AbstractHandlerMethodMapping.MappingRegistry.register(...)方法。

AbstractHandlerMethodMapping.MappingRegistry.register(...)方法里開始初始化CORS的配置,并以方法粒度將其注冊到corsLookup中,corsLookup是CORS應(yīng)用的關(guān)鍵。

/**
 * 進(jìn)行映射注冊.
 */
public void register(T mapping, Object handler, Method method) {
    // 首先,獲取寫入鎖.
    this.readWriteLock.writeLock().lock();
    try {
        // 創(chuàng)建HandlerMethod.
        HandlerMethod handlerMethod = createHandlerMethod(handler, method);
        // 驗證映射唯一性.
        assertUniqueMethodMapping(handlerMethod, mapping);
        if (logger.isInfoEnabled()) {
            logger.info("Mapped \"" + mapping + "\" onto " + handlerMethod);
        }
        this.mappingLookup.put(mapping, handlerMethod);
        // 搜索直接URL.
        List<String> directUrls = getDirectUrls(mapping);
        for (String url : directUrls) {
            this.urlLookup.add(url, mapping);
        }
        // 解析name,并設(shè)置映射名稱.
        String name = null;
        if (getNamingStrategy() != null) {
            name = getNamingStrategy().getName(handlerMethod, mapping);
            addMappingName(name, handlerMethod);
        }
        // 初始化CORS配置.
        CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping);
        if (corsConfig != null) {
            this.corsLookup.put(handlerMethod, corsConfig);
        }
        this.registry.put(mapping, new MappingRegistration<>(mapping, handlerMethod, directUrls, name));
    }
    finally {
        // 釋放寫入鎖.
        this.readWriteLock.writeLock().unlock();
    }
}

3) RequestMappingHandlerMapping.initCorsConfiguration(...)方法。

① 取得當(dāng)前解析方法所屬類的類型。

② 在類級別和方法級別分別查找@CrossOrigin注解。

③ 若類級別和方法級別不存在@CrossOrigin注解,則跳過此部分處理邏輯。

④ 初始化CorsConfiguration配置對象。

⑤ 首先更新類級別@CrossOrigin注解信息到CorsConfiguration配置對象,其次更新方法級別@CrossOrigin注解信息到CorsConfiguration配置對象。兩者之間是可以簡單理解為合集關(guān)系,在類級別@CrossOrigin注解信息基礎(chǔ)上,填加方法級別@CrossOrigin注解信息。

⑥ 若@CrossOrigin注解未標(biāo)注允許的HTTP方法,則以@RequestMapping注解標(biāo)注的HTTP方法作為允許的HTTP方法。

⑦ 調(diào)用config.applyPermitDefaultValues()為未初始化的配置設(shè)置默認(rèn)值。

/**
 * 初始化CORS配置.
 */
@Override
protected CorsConfiguration initCorsConfiguration(Object handler, Method method, RequestMappingInfo mappingInfo) {
    // 創(chuàng)建HandlerMethod.
    HandlerMethod handlerMethod = createHandlerMethod(handler, method);
    // 獲取方法所屬類型.
    Class<?> beanType = handlerMethod.getBeanType();
    // 查找類級別注釋.
    CrossOrigin typeAnnotation = AnnotatedElementUtils.findMergedAnnotation(beanType, CrossOrigin.class);
    // 查找方法級別注釋.
    CrossOrigin methodAnnotation = AnnotatedElementUtils.findMergedAnnotation(method, CrossOrigin.class);
    // 類和方法級別無注釋,跳過處理.
    if (typeAnnotation == null && methodAnnotation == null) {
        return null;
    }
    // 初始化配置.
    CorsConfiguration config = new CorsConfiguration();
    // 更新類級別@CrossOrigin注解配置.
    updateCorsConfig(config, typeAnnotation);
    // 更新方法級別@CrossOrigin注解配置.    
    updateCorsConfig(config, methodAnnotation);
    // 若@CrossOrigin未標(biāo)準(zhǔn)HTTP方法,則以@RequestMapping標(biāo)準(zhǔn)HTTP方法為準(zhǔn).
    if (CollectionUtils.isEmpty(config.getAllowedMethods())) {
        for (RequestMethod allowedMethod : mappingInfo.getMethodsCondition().getMethods()) {
            config.addAllowedMethod(allowedMethod.name());
        }
    }
    // 為未初始化的配置設(shè)置默認(rèn)值.
    return config.applyPermitDefaultValues();
}

4) RequestMappingHandlerMapping.updateCorsConfig(...)方法。

① 解析@CrossOrigin注解的origins屬性到CorsConfiguration配置。

?② 解析@CrossOrigin注解的methods屬性到CorsConfiguration配置。

③ 解析@CrossOrigin注解的allowedHeaders屬性到CorsConfiguration配置。

④ 解析@CrossOrigin注解的exposedHeaders屬性到CorsConfiguration配置。

⑤ 解析@CrossOrigin注解的allowCredentials屬性到CorsConfiguration配置。allowCredentials的有效值為true或false。

⑥ 當(dāng)CorsConfiguration配置未設(shè)置maxAge且@CrossOrigin注解的maxAge屬性為大于0的有效值時,解析@CrossOrigin注解的maxAge屬性到CorsConfiguration配置。

/**
 * 更新CORS配置.
 */
private void updateCorsConfig(CorsConfiguration config, @Nullable CrossOrigin annotation) {
    // 注解為空,跳過處理.
    if (annotation == null) {
        return;
    }
    // 解析@CrossOrigin.origins屬性到配置.
    for (String origin : annotation.origins()) {
        config.addAllowedOrigin(resolveCorsAnnotationValue(origin));
    }
    // 解析@CrossOrigin.methods屬性到配置.
    for (RequestMethod method : annotation.methods()) {
        config.addAllowedMethod(method.name());
    }
    // 解析@CrossOrigin.allowedHeaders屬性到配置.
    for (String header : annotation.allowedHeaders()) {
        config.addAllowedHeader(resolveCorsAnnotationValue(header));
    }
    // 解析@CrossOrigin.exposedHeaders屬性到配置.
    for (String header : annotation.exposedHeaders()) {
        config.addExposedHeader(resolveCorsAnnotationValue(header));
    }
    // 解析@CrossOrigin.allowCredentials屬性到配置.
    String allowCredentials = resolveCorsAnnotationValue(annotation.allowCredentials());
    if ("true".equalsIgnoreCase(allowCredentials)) {
        config.setAllowCredentials(true);
    }
    else if ("false".equalsIgnoreCase(allowCredentials)) {
        config.setAllowCredentials(false);
    }
    else if (!allowCredentials.isEmpty()) {
        throw new IllegalStateException("@CrossOrigin's allowCredentials value must be \"true\", \"false\", " +
                                        "or an empty string (\"\"): current value is [" + allowCredentials + "]");
    }
    // 解析@CrossOrigin.maxAge屬性到配置.
    if (annotation.maxAge() >= 0 && config.getMaxAge() == null) {
        config.setMaxAge(annotation.maxAge());
    }
}

5) CorsConfiguration.applyPermitDefaultValues()方法。

?① 若CorsConfiguration配置的allowedOrigins屬性尚未設(shè)置時,則設(shè)置所有源均允許。

② 若CorsConfiguration配置的allowedMethods屬性尚未設(shè)置時,則設(shè)置所有源均允許。

③ 若CorsConfiguration配置的allowedHeaders、resolvedMethods屬性尚未設(shè)置時,則設(shè)置所有頭均允許。

?④ 若CorsConfiguration配置的maxAge屬性尚未設(shè)置時,則設(shè)置為1800秒(30分鐘)。

/**
 * 默認(rèn)情況下,新建的CorsConfiguration不允許任何跨源請求,必須填加相應(yīng)配置以允許請求.
 * 
 * 使用這個方法為未初始化的配置打開默認(rèn)的跨域設(shè)置,包括:GET、HEAD、POST.
 * 但是請注意,此方法不會覆蓋任何已設(shè)置的現(xiàn)有值.
 *
 * 如果尚未設(shè)置,則應(yīng)用以下默認(rèn)值:
 *	允許所有源.
 *	允許簡單HTTP方法:GET、HEAD、POST.
 *  允許所有HTTP頭.
 *  設(shè)置最大使用時間1800秒(30分鐘).
 */
public CorsConfiguration applyPermitDefaultValues() {
    // 若未設(shè)置允許源,則設(shè)置所有源均允許.
    if (this.allowedOrigins == null) {
        this.allowedOrigins = DEFAULT_PERMIT_ALL;
    }
    // 若未設(shè)置允許方法,則設(shè)置允許GET、HEAD、POST.
    if (this.allowedMethods == null) {
        this.allowedMethods = DEFAULT_PERMIT_METHODS;
        this.resolvedMethods = DEFAULT_PERMIT_METHODS
            .stream().map(HttpMethod::resolve).collect(Collectors.toList());
    }
    // 若未設(shè)置允許頭,則設(shè)置所有頭均允許.
    if (this.allowedHeaders == null) {
        this.allowedHeaders = DEFAULT_PERMIT_ALL;
    }
    // 若未設(shè)置最大使用時間,則設(shè)置為1800秒(30分鐘).
    if (this.maxAge == null) {
        this.maxAge = 1800L;
    }
    return this;
}

總結(jié)

正如文中所說,@CrossOrigin解析的目的,即是將解析后的配置注冊到AbstractHandlerMethodMapping.MappingRegistry.corsLookup屬性中,以便webmvc模塊處理請求使用。

?源碼解析基于spring-framework-5.0.5.RELEASE版本源碼。

到此這篇關(guān)于Spring中的@CrossOrigin注冊處理方法源碼解析的文章就介紹到這了,更多相關(guān)@CrossOrigin注冊處理方法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot2 JPA解決懶加載異常的問題

    SpringBoot2 JPA解決懶加載異常的問題

    這篇文章主要介紹了SpringBoot2 JPA解決懶加載異常的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-01-01
  • Spring?Security?核心過濾器鏈講解

    Spring?Security?核心過濾器鏈講解

    這篇文章主要介紹了Spring?Security?核心過濾器鏈,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • java配置context.xml文件的方法圖解

    java配置context.xml文件的方法圖解

    這篇文章主要介紹了java配置context.xml文件的方法圖解,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2018-02-02
  • SpringBoot反射的基本應(yīng)用全解析

    SpringBoot反射的基本應(yīng)用全解析

    反射是Java的核心特性之一,允許在運行時檢查或修改類、方法、字段的行為,SpringBoot作為基于Spring框架的快速開發(fā)工具,廣泛利用反射實現(xiàn)依賴注入、動態(tài)代理等功能,本文給大家介紹SpringBoot反射應(yīng)用全解析,感興趣的朋友跟隨小編一起看看吧
    2025-09-09
  • java導(dǎo)出csv格式文件的方法

    java導(dǎo)出csv格式文件的方法

    這篇文章主要為大家詳細(xì)介紹了java導(dǎo)出csv格式文件的方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-12-12
  • 重寫hashCode()和equals()方法詳細(xì)介紹

    重寫hashCode()和equals()方法詳細(xì)介紹

    這篇文章主要介紹了重寫hashCode()和equals()方法詳細(xì)介紹,涉及重寫equals()方法,重寫hashCode()方法,重寫equals()而不重寫hashCode()的風(fēng)險等相關(guān)內(nèi)容的介紹,具有一定借鑒價值,需要的朋友可以參考下
    2018-01-01
  • Java響應(yīng)式編程Mono接口詳解

    Java響應(yīng)式編程Mono接口詳解

    這篇文章主要介紹了Java中的Mono接口,Mono是Project?Reactor響應(yīng)式編程庫中的核心接口之一,代表一個異步的、可能包含零個或一個元素的流,在響應(yīng)式編程范式中,Mono專門用于處理那些預(yù)期最多只有一個結(jié)果的異步操作,需要的朋友可以參考下
    2026-02-02
  • Java中線程的基本方法使用技巧

    Java中線程的基本方法使用技巧

    這篇文章主要介紹了Java中線程的基本方法使用技巧,需要的朋友可以參考下
    2017-09-09
  • Java中的Set集合源碼詳細(xì)解讀

    Java中的Set集合源碼詳細(xì)解讀

    這篇文章主要介紹了Java中的Set集合源碼詳細(xì)解讀,Set注重獨一無二的性質(zhì),該體系集合用于存儲無序(存入和取出的順序不一定相同)元素, 值不能重復(fù),需要的朋友可以參考下
    2023-11-11
  • java中金額元轉(zhuǎn)萬元工具類的實例

    java中金額元轉(zhuǎn)萬元工具類的實例

    這篇文章主要介紹了java中金額元轉(zhuǎn)萬元工具類的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02

最新評論

六枝特区| 漯河市| 横山县| 都江堰市| 临澧县| 南皮县| 英德市| 临清市| 靖边县| 偏关县| 沾化县| 札达县| 密云县| 莆田市| 寿阳县| 叶城县| 大洼县| 正镶白旗| 湖北省| 铁力市| 昌图县| 曲周县| 商南县| 临沧市| 台中县| 丹棱县| 肇源县| 洛川县| 晋城| 田林县| 清新县| 利川市| 淅川县| 卢龙县| 从化市| 恭城| 孙吴县| 三亚市| 开平市| 连云港市| 海安县|