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

SpringBoot項目啟動過程動態(tài)修改接口請求路徑的解決方案

 更新時間:2024年10月10日 09:19:16   作者:codest  
在SpringBoot服務(wù)整合過程中,遇到了多個服務(wù)中相同RequestMapping路徑導(dǎo)致的啟動問題,解決方案是通過修改RequestMappingHandlerMapping類的getMappingForMethod方法,本文給大家介紹SpringBoot修改接口請求路徑的解決方案,感興趣的朋友一起看看吧

背景

最近遇到一個技術(shù)需求,需要對其他多個已有的服務(wù)進行整合打包為一個整體的服務(wù),項目啟動過程發(fā)現(xiàn)一個問題,在controller層多個服務(wù)之間存在相同的RequestMapping接口請求路徑,導(dǎo)致服務(wù)無法啟動。

目前的接口定義規(guī)范為:/服務(wù)名(context-path)/接口版本號/模塊名/接口名

例如通過用戶Id查詢用戶信息的接口,在統(tǒng)一認證服務(wù)和用戶管理服務(wù)有如下接口定義

統(tǒng)一認證服務(wù):/sso/v1.0/user/get/{id}

用戶管理服務(wù):/user/v1.0/user/get/{id}

當我們把統(tǒng)一認證服務(wù)和用戶管理服務(wù)進行整合為一個服務(wù)時,/v1.0/user/get/{id}請求路徑發(fā)生重復(fù),導(dǎo)致服務(wù)無法啟動。

解決方案

為了解決服務(wù)之間接口定義沖突的問題,我們準備對接口的請求路徑進行動態(tài)修改,主要是通過controller類所在的包路徑進行服務(wù)名的識別,并加入到接口請求路徑的最前面。

舉個栗子:

統(tǒng)一認證服務(wù)controller層偽代碼如下:

package cn.codest.sso.web;
@RestController
@Api(tags = "統(tǒng)一認證服務(wù)")
@RequestMapping("/v1.0/user")
@RequiredArgsConstructor
public class SSOController {
    private final UserService userService;
    @GetMapping("/get/{id}")
    @ApiOperation(value = "用戶查詢", httpMethod = "GET", notes = "用戶查詢")
    public SwaggerResultUtil getById(String id){
        return SwaggerResultUtil.resultSuccess(userService.get(id));
    }
}

通過重載RequestMappingHandlerMapping類的getMappingForMethod方法,實現(xiàn)在項目啟動過程中注冊/v1.0/user/get/{id}接口時,識別package的路徑cn.codest.sso.web提取業(yè)務(wù)標識sso,修改接口注冊地址為/sso/v1.0/user/get/{id},具體代碼如下:

@Slf4j
@Configuration
@Order(Ordered.HIGHEST_PRECEDENCE)
public class PackagePathRequestMappingHandler extends RequestMappingHandlerMapping {
    private static final String PACKAGE_PREFIX = "cn.codest";
    private static final String SERVICE_PREFIX = "service";
    private static final String PROVIDER_PREFIX = "providerD";
    /**
     * 包名對應(yīng)的服務(wù)名緩存類
     */
    private final LinkedHashMap<String, String> services = new LinkedHashMap<>(8);
    @Override
    protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
        // 判斷當前注冊的controller接口屬于業(yè)務(wù)層controller,部分中間件例如swagger也會進行接口注冊
        if (!StringUtils.startsWith(handlerType.getName(), PACKAGE_PREFIX)
                || !AnnotatedElementUtils.hasAnnotation(method, RequestMapping.class)
                || AnnotatedElementUtils.hasAnnotation(handlerType, FeignClient.class)) {
            return super.getMappingForMethod(method, handlerType);
        }
        try {
            // 構(gòu)造RequestMapping對象
            RequestMappingInfo mapping = super.getMappingForMethod(method, handlerType);
            // 根據(jù)包路徑獲取服務(wù)名
            String serviceName = getServiceName(handlerType.getName());
            if (StringUtils.isBlank(serviceName)) {
                return mapping;
            }
            // 增加服務(wù)名前綴
            return RequestMappingInfo.paths(serviceName).build().combine(mapping);
        } catch (Exception e) {
            log.error("重寫RequestMapping請求路徑時發(fā)生錯誤[class: {}, method: {}]", handlerType.getName(), method.getName(), e);
            throw e;
        }
    }
    protected String getServiceName(String className) {
        // 分割類限定名
        String[] packages = className.split("\\.");
        // 判斷包路徑長度
        if (packages.length > 3) {
            // 獲取子產(chǎn)品包名
            String serviceName = packages[2];
            // 讀取緩存
            if (services.containsKey(serviceName)) {
                return services.get(serviceName);
            } else if (StringUtils.startsWith(serviceName, SERVICE_PREFIX)) {  // service服務(wù)
                services.put(serviceName, serviceName.replace(SERVICE_PREFIX, StringUtils.EMPTY));
            } else if (StringUtils.startsWith(serviceName, PROVIDER_PREFIX.toLowerCase())) {    // provider服務(wù)
                services.put(serviceName, serviceName.replace(PROVIDER_PREFIX.toLowerCase(), PROVIDER_PREFIX));
            }
            return services.get(serviceName);
        }
        return StringUtils.EMPTY;
    }
}

注冊自定義RequestMappingHandler,項目使用的SpringBoot版本為2.0.x,不同版本注冊方式不同,可以自行查閱官方文檔。

public class CustomWebMvcConfig implements WebMvcRegistrations {
    @Override
    public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
        RequestMappingHandlerMapping handlerMapping = new PackagePathRequestMappingHandler();
        handlerMapping.setOrder(Ordered.HIGHEST_PRECEDENCE);
        return handlerMapping;
    }
}

到此這篇關(guān)于SpringBoot項目啟動過程動態(tài)修改接口請求路徑的文章就介紹到這了,更多相關(guān)SpringBoot動態(tài)修改接口請求路徑內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 使用HTTPclient保持長連接

    使用HTTPclient保持長連接

    這篇文章主要介紹了使用HTTPclient保持長連接,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • Java數(shù)據(jù)結(jié)構(gòu)之HashMap和HashSet

    Java數(shù)據(jù)結(jié)構(gòu)之HashMap和HashSet

    這篇文章主要介紹了HashMap和HashSet,什么是哈希表以及HashMap的部分源碼解讀,想了解更多的小伙伴,可以參考閱讀本文
    2023-03-03
  • Windows本地安裝啟動Nacos過程

    Windows本地安裝啟動Nacos過程

    本文介紹了如何下載、配置和啟動Nacos,包括下載Nacos、配置單機模式、配置數(shù)據(jù)庫和啟動Nacos等步驟
    2026-01-01
  • java類和對象原理與用法分析

    java類和對象原理與用法分析

    這篇文章主要介紹了java類和對象原理與用法,結(jié)合實例形式分析了java類和對象的相關(guān)概念、功能、原理、使用技巧與操作注意事項,需要的朋友可以參考下
    2020-02-02
  • Spring內(nèi)部bean和級聯(lián)屬性用法詳解

    Spring內(nèi)部bean和級聯(lián)屬性用法詳解

    這篇文章主要介紹了Java內(nèi)部bean和級聯(lián)屬性用法詳解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-10-10
  • spring-boot項目啟動遲緩異常排查解決記錄

    spring-boot項目啟動遲緩異常排查解決記錄

    這篇文章主要為大家介紹了spring-boot項目啟動遲緩異常排查解決記錄,突然在本地啟動不起來了,表象特征就是在本地IDEA上運行時,進程卡住也不退出,應(yīng)用啟動時加載相關(guān)組件的日志也不輸出
    2022-02-02
  • 詳談Java幾種線程池類型介紹及使用方法

    詳談Java幾種線程池類型介紹及使用方法

    下面小編就為大家?guī)硪黄斦凧ava幾種線程池類型介紹及使用方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-03-03
  • 每日六道java新手入門面試題,通往自由的道路--線程池

    每日六道java新手入門面試題,通往自由的道路--線程池

    這篇文章主要為大家分享了最有價值的6道線程池面試題,涵蓋內(nèi)容全面,包括數(shù)據(jù)結(jié)構(gòu)和算法相關(guān)的題目、經(jīng)典面試編程題等,對hashCode方法的設(shè)計、垃圾收集的堆和代進行剖析,感興趣的小伙伴們可以參考一下
    2021-06-06
  • SpringMVC Cron定時器Demo常見問題解決方案

    SpringMVC Cron定時器Demo常見問題解決方案

    這篇文章主要介紹了SpringMVC Cron定時器Demo常見問題解決方案,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-11-11
  • 一文詳解gRPC快速整合SpringCloud

    一文詳解gRPC快速整合SpringCloud

    這篇文章主要為大家介紹gRPC快速整合SpringCloud的實現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-03-03

最新評論

漯河市| 缙云县| 石柱| 洛宁县| 囊谦县| 台东市| 新野县| 志丹县| 盐山县| 台中县| 临泽县| 永善县| 武威市| 红安县| 芜湖市| 陵川县| 卓资县| 赞皇县| 体育| 连山| 射洪县| 丽水市| 红桥区| 建始县| 南宫市| 德庆县| 东台市| 三门峡市| 合江县| 庆安县| 龙陵县| 崇义县| 青海省| 蒙城县| 拉萨市| 股票| 寿宁县| 万宁市| 民丰县| 明星| 呼和浩特市|