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

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)一認(rèn)證服務(wù)和用戶管理服務(wù)有如下接口定義

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

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

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

解決方案

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

舉個栗子:

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

package cn.codest.sso.web;
@RestController
@Api(tags = "統(tǒng)一認(rèn)證服務(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ù)標(biāo)識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) {
        // 判斷當(dāng)前注冊的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)文章

  • IDEA+GIT使用入門圖文詳解

    IDEA+GIT使用入門圖文詳解

    這篇文章主要介紹了IDEA+GIT使用入門詳解,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-11-11
  • SpringBoot實現(xiàn)自定義啟動器的示例詳解

    SpringBoot實現(xiàn)自定義啟動器的示例詳解

    雖然Spring官方給我們提供了很多的啟動器供我們使用,但有時候我們也會遇到某些特殊場景,這些啟動器滿足不了。這個時候就需要自定義一個啟動器供我們使用,本文為大家介紹了SpringBoot實現(xiàn)自定義啟動器的方法,希望對大家有所幫助
    2023-01-01
  • java并發(fā)編程專題(一)----線程基礎(chǔ)知識

    java并發(fā)編程專題(一)----線程基礎(chǔ)知識

    這篇文章主要介紹了java并發(fā)編程線程的基礎(chǔ)知識,文中講解非常詳細(xì),幫助大家更好的學(xué)習(xí)JAVA并發(fā)編程,感興趣想學(xué)習(xí)JAVA的可以了解下
    2020-06-06
  • SpringBoot實現(xiàn)分布式驗證碼登錄方案小結(jié)

    SpringBoot實現(xiàn)分布式驗證碼登錄方案小結(jié)

    驗證碼登錄作為一種有效的防護手段,可以防止惡意gongji、暴力pojie等,本文主要介紹了SpringBoot實現(xiàn)分布式驗證碼登錄方案小結(jié),具有一定的參考價值,感興趣的可以了解一下
    2024-12-12
  • Spring Aware標(biāo)記接口使用案例解析

    Spring Aware標(biāo)記接口使用案例解析

    這篇文章主要介紹了Spring Aware標(biāo)記接口使用案例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-04-04
  • Maven中exec插件執(zhí)行Java程序的實現(xiàn)

    Maven中exec插件執(zhí)行Java程序的實現(xiàn)

    在Maven項目中,可以使用Maven的插件來執(zhí)行Java程序,本文主要介紹了Maven中exec插件執(zhí)行Java程序的實現(xiàn),具有一定的參考價值,感興趣的可以了解一下
    2023-12-12
  • Java中基于推、拉模式的sentinel規(guī)則持久化詳解

    Java中基于推、拉模式的sentinel規(guī)則持久化詳解

    這篇文章主要介紹了Java中基于推、拉模式的sentinel規(guī)則持久化詳解,推模式是sentinelDashboard?把規(guī)則推給Nacos,Nacos監(jiān)聽規(guī)則的變化推給微服務(wù),拉模式是sentinelDashboard?把規(guī)則直接給微服務(wù),?Nacos定時的同步微服務(wù)端的規(guī)則,需要的朋友可以參考下
    2023-09-09
  • 關(guān)于java中Map的九大問題分析

    關(guān)于java中Map的九大問題分析

    這篇文章主要為大家詳細(xì)分析了關(guān)于java中Map的九大問題,感興趣的小伙伴們可以參考一下
    2016-08-08
  • Spring自動掃描無法掃描jar包中bean的解決方法

    Spring自動掃描無法掃描jar包中bean的解決方法

    在日常開發(fā)中往往會對公共的模塊打包發(fā)布,然后調(diào)用公共包的內(nèi)容。然而,最近對公司的公共模塊進行整理發(fā)布后。spring卻無法掃描到相應(yīng)的bean,下面這篇文章主要給大家介紹了關(guān)于Spring自動掃描時無法掃描jar包中bean的解決方法,需要的朋友可以參考下。
    2017-06-06
  • SpringBoot Maven打包如何根據(jù)環(huán)境排除文件

    SpringBoot Maven打包如何根據(jù)環(huán)境排除文件

    文章介紹了在SpringBoot項目中,根據(jù)不同的環(huán)境(開發(fā)、測試、生產(chǎn))進行JSP文件打包處理的方法,通過配置`pom.xml`文件中的``標(biāo)簽,可以實現(xiàn)開發(fā)環(huán)境保留`index.jsp`文件,測試環(huán)境和生產(chǎn)環(huán)境排除該文件
    2024-12-12

最新評論