亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

搜索

使用Java函數(shù)式接口抽象分頁(yè)Feign API調(diào)用

DDD
發(fā)布: 2025-10-16 11:50:01
原創(chuàng)
719人瀏覽過(guò)

使用Java函數(shù)式接口抽象分頁(yè)Feign API調(diào)用

本文探討了如何通過(guò)java函數(shù)式接口和泛型,優(yōu)雅地解決feign api分頁(yè)調(diào)用中參數(shù)多樣性導(dǎo)致的重復(fù)代碼問(wèn)題。通過(guò)引入統(tǒng)一的`pagingapi`接口和靜態(tài)工廠方法,我們能夠以描述性的方式綁定不同數(shù)量的參數(shù),從而實(shí)現(xiàn)對(duì)各類分頁(yè)api的通用化處理和數(shù)據(jù)抽取,顯著減少了樣板代碼,并提升了代碼的可維護(hù)性和可讀性。

在微服務(wù)架構(gòu)中,F(xiàn)eign作為聲明式HTTP客戶端,極大地簡(jiǎn)化了服務(wù)間調(diào)用。然而,當(dāng)需要處理大量支持分頁(yè)的Feign API時(shí),如果這些API的入?yún)⒊朔猪?yè)信息(頁(yè)碼和大?。┩膺€包含不同數(shù)量的其他業(yè)務(wù)參數(shù),就可能導(dǎo)致大量的樣板代碼。例如,一個(gè)API可能只帶一個(gè)業(yè)務(wù)參數(shù),而另一個(gè)可能帶兩個(gè),這使得為每個(gè)API編寫通用的分頁(yè)數(shù)據(jù)抽取邏輯變得復(fù)雜且冗余。

問(wèn)題描述與傳統(tǒng)方法的局限

假設(shè)我們有一個(gè)通用的分頁(yè)數(shù)據(jù)抽取服務(wù),其核心邏輯是根據(jù)給定的分頁(yè)API接口,從第一頁(yè)開始逐頁(yè)獲取數(shù)據(jù)直到所有數(shù)據(jù)被抽取完畢。最初的實(shí)現(xiàn)可能類似于以下結(jié)構(gòu):

// 核心抽取邏輯(簡(jiǎn)化版)
public <T> List<BaseFeignResult<T>> drainFeignPageableCall(PagedCall<T> feignCall) {
    // ... 調(diào)用 feignCall.call(0, 10) 獲取第一頁(yè)
    // ... 遞歸或循環(huán)調(diào)用獲取后續(xù)頁(yè)面
    return null; // 實(shí)際返回所有頁(yè)面的數(shù)據(jù)
}

// 抽象分頁(yè)API調(diào)用的接口
public interface PagedCall<T> {
    BaseFeignResult<T> call(int p, int s);
}

// 針對(duì)單參數(shù)API的實(shí)現(xiàn)
public static class SingleParamPageableCall<T> implements PagedCall<T> {
    SingleParamPagingApi<T> fun;
    String param;

    public SingleParamPageableCall(SingleParamPagingApi<T> fun, String param) {
        this.fun = fun;
        this.param = param;
    }

    @Override
    public BaseFeignResult<T> call(int p, int s) {
        // 包裝實(shí)際的Feign調(diào)用
        return BaseFeignResult.<T>builder()
                .resp(fun.callFeignApi(param, p, s))
                .build();
    }
}

// 針對(duì)單參數(shù)的Feign接口定義
public interface SingleParamPagingApi<T> {
    ResponseEntity<IVDPagedResponseOf<T>> callFeignApi(String arg, int page, int size) throws RuntimeException;
}

// 示例調(diào)用
drainFeignPageableCall(new BaseService.SingleParamPageableCall<GetOrderInfoDto>(ordersFeignClient::getOrdersBySampleIds, "34596"));
登錄后復(fù)制

這種方法的問(wèn)題在于,每當(dāng)遇到一個(gè)具有不同數(shù)量業(yè)務(wù)參數(shù)的分頁(yè)API時(shí)(例如,兩個(gè)參數(shù)、三個(gè)參數(shù)),我們就需要為它定義一個(gè)新的接口(如TwoParamPagingApi)和一個(gè)新的PagedCall實(shí)現(xiàn)類(如TwoParamPageableCall),這導(dǎo)致了大量的樣板代碼和類型膨脹,難以維護(hù)。我們期望的是一種更具描述性、更函數(shù)式的實(shí)現(xiàn)方式,能夠?qū)?shù)映射到方法調(diào)用的過(guò)程抽象化,而無(wú)需定義繁重的中間對(duì)象。

使用函數(shù)式接口實(shí)現(xiàn)參數(shù)綁定與抽象

Java 8引入的函數(shù)式接口為解決這類問(wèn)題提供了強(qiáng)大的工具。我們可以通過(guò)定義不同參數(shù)數(shù)量的函數(shù)式接口,并在一個(gè)統(tǒng)一的接口中提供靜態(tài)工廠方法來(lái)綁定這些參數(shù),從而將復(fù)雜的API簽名轉(zhuǎn)換為一個(gè)只接受分頁(yè)參數(shù)的簡(jiǎn)單接口。

立即學(xué)習(xí)Java免費(fèi)學(xué)習(xí)筆記(深入)”;

核心接口定義

首先,我們定義針對(duì)不同參數(shù)數(shù)量的原始Feign API調(diào)用的函數(shù)式接口。這里以一個(gè)參數(shù)和兩個(gè)參數(shù)為例:

// 針對(duì)一個(gè)業(yè)務(wù)參數(shù)的Feign API接口
public interface PagingApi1<T, A0> {
    ResponseEntity<IVDPagedResponseOf<T>> callFeignApi(A0 arg0, int page, int size) throws RuntimeException;
}

// 針對(duì)兩個(gè)業(yè)務(wù)參數(shù)的Feign API接口
public interface PagingApi2<T, A0, A1> {
    ResponseEntity<IVDPagedResponseOf<T>> callFeignApi(A0 arg0, A1 arg1, int page, int size) throws RuntimeException;
}
登錄后復(fù)制

接下來(lái),定義一個(gè)統(tǒng)一的PagingApi接口,它只關(guān)心分頁(yè)參數(shù)(頁(yè)碼和大小),并提供靜態(tài)工廠方法來(lái)“適配”上述不同參數(shù)數(shù)量的原始API。

// 統(tǒng)一的分頁(yè)API接口,只接受頁(yè)碼和大小
public interface PagingApi<T> {
    // 靜態(tài)工廠方法:綁定一個(gè)業(yè)務(wù)參數(shù)
    static <T, A0> PagingApi<T> of(PagingApi1<T, A0> api, A0 arg0) {
        return (p, s) -> api.callFeignApi(arg0, p, s);
    }

    // 靜態(tài)工廠方法:綁定兩個(gè)業(yè)務(wù)參數(shù)
    static <T, A0, A1> PagingApi<T> of(PagingApi2<T, A0, A1> api, A0 arg0, A1 arg1) {
        return (p, s) -> api.callFeignApi(arg0, arg1, p, s);
    }

    // 實(shí)際執(zhí)行Feign API調(diào)用的方法
    ResponseEntity<IVDPagedResponseOf<T>> callFeignApi(int page, int size) throws RuntimeException;
}
登錄后復(fù)制

通過(guò)PagingApi.of()方法,我們可以將一個(gè)具有多個(gè)參數(shù)的Feign方法引用(如ordersFeignClient::getOrdersBySampleIds)和其固定的業(yè)務(wù)參數(shù)綁定起來(lái),生成一個(gè)只接受頁(yè)碼和大小的PagingApi實(shí)例。這實(shí)現(xiàn)了參數(shù)的“柯里化”或部分應(yīng)用。

通用PageableCall實(shí)現(xiàn)

有了統(tǒng)一的PagingApi,我們的PagedCall接口的實(shí)現(xiàn)也變得極其簡(jiǎn)潔:

SpeakingPass-打造你的專屬雅思口語(yǔ)語(yǔ)料
SpeakingPass-打造你的專屬雅思口語(yǔ)語(yǔ)料

使用chatGPT幫你快速備考雅思口語(yǔ),提升分?jǐn)?shù)

SpeakingPass-打造你的專屬雅思口語(yǔ)語(yǔ)料25
查看詳情 SpeakingPass-打造你的專屬雅思口語(yǔ)語(yǔ)料
// 通用的 PageableCall 實(shí)現(xiàn)
public static class PageableCall<T> implements PagedCall<T> {
    PagingApi<T> fun; // 現(xiàn)在它只依賴于統(tǒng)一的 PagingApi

    public PageableCall(PagingApi<T> fun) {
        this.fun = fun;
    }

    @Override
    public BaseFeignResult<T> call(int p, int s) {
        BaseFeignResult.BaseFeignResultBuilder<T> builder = BaseFeignResult.builder();
        try {
            builder.resp(fun.callFeignApi(p, s)); // 直接調(diào)用統(tǒng)一接口
        } catch (RuntimeException e) {
            builder.excp(e);
        }
        return builder.build();
    }
}
登錄后復(fù)制

這里的BaseFeignResult和IVDPagedResponseOf是根據(jù)原始問(wèn)題上下文假設(shè)的數(shù)據(jù)結(jié)構(gòu),用于封裝Feign調(diào)用的響應(yīng)和異常。

實(shí)際調(diào)用示例

現(xiàn)在,調(diào)用通用的分頁(yè)數(shù)據(jù)抽取服務(wù)變得非常簡(jiǎn)潔和描述性:

// 假設(shè) ordersFeignClient.getOrdersBySampleIds 方法簽名是:
// ResponseEntity<IVDPagedResponseOf<GetOrderInfoDto>> getOrdersBySampleIds(String sampleId, int page, int size);

drainFeignPageableCall(
        new PageableCall<GetOrderInfoDto>(
                PagingApi.of(ordersFeignClient::getOrdersBySampleIds, "34596")
        )
);
登錄后復(fù)制

通過(guò)PagingApi.of(ordersFeignClient::getOrdersBySampleIds, "34596"),我們以函數(shù)式的方式描述了如何將"34596"這個(gè)參數(shù)綁定到getOrdersBySampleIds方法上,從而生成了一個(gè)新的PagingApi實(shí)例,這個(gè)實(shí)例在內(nèi)部已經(jīng)“記住”了"34596"這個(gè)參數(shù),后續(xù)調(diào)用時(shí)只需提供頁(yè)碼和大小即可。

進(jìn)一步優(yōu)化與注意事項(xiàng)

  1. 接口合并: PagingApi和PagedCall在功能上非常相似,都可以進(jìn)一步合并為一個(gè)接口,例如直接讓PagingApi實(shí)現(xiàn)PagedCall的功能,或者將PagingApi作為PagedCall的唯一接口。

    // 合并 PagingApi 和 PagedCall
    public interface PagingApi<T> {
        // 靜態(tài)工廠方法不變
        static <T, A0> PagingApi<T> of(PagingApi1<T, A0> api, A0 arg0) {
            return (p, s) -> api.callFeignApi(arg0, p, s);
        }
        // ... 其他 of 方法
    
        // 原始的 callFeignApi 方法,現(xiàn)在可以作為 PagedCall 的實(shí)現(xiàn)
        ResponseEntity<IVDPagedResponseOf<T>> callFeignApi(int page, int size) throws RuntimeException;
    
        // 包裝成 BaseFeignResult 的方法,可以直接在 PagingApi 內(nèi)部實(shí)現(xiàn)
        default BaseFeignResult<T> call(int p, int s) {
            BaseFeignResult.BaseFeignResultBuilder<T> builder = BaseFeignResult.builder();
            try {
                builder.resp(callFeignApi(p, s));
            } catch (RuntimeException e) {
                builder.excp(e);
            }
            return builder.build();
        }
    }
    
    // 此時(shí) drainFeignPageableCall 的簽名可以變?yōu)椋?// public <T> List<BaseFeignResult<T>> drainFeignPageableCall(PagingApi<T> feignCall) { ... }
    
    // 調(diào)用方式簡(jiǎn)化為:
    // drainFeignPageableCall(PagingApi.of(ordersFeignClient::getOrdersBySampleIds, "34596"));
    登錄后復(fù)制
  2. 避免遞歸調(diào)用: 在drainFeignPageableCall方法中,原始的遞歸實(shí)現(xiàn)雖然具有函數(shù)式風(fēng)格,但在Java中可能導(dǎo)致溢出(StackOverflowError),尤其是在處理大量頁(yè)面時(shí)。更健壯的做法是使用迭代(for或while循環(huán))來(lái)替代遞歸。

    // 迭代實(shí)現(xiàn)的 drainFeignPageableCall 示例
    public <T> List<BaseFeignResult<T>> drainFeignPageableCall(PagingApi<T> feignCall, int pageSize) {
        List<BaseFeignResult<T>> allResults = new ArrayList<>();
        int page = 0;
        boolean hasMore = true;
    
        while (hasMore) {
            BaseFeignResult<T> currentPageResult = feignCall.call(page, pageSize);
            allResults.add(currentPageResult);
    
            // 假設(shè) IVDPagedResponseOf 有一個(gè) getTotalPages 或 getContent() 方法
            // 這里需要根據(jù)實(shí)際的 IVDPagedResponseOf 結(jié)構(gòu)來(lái)判斷是否還有下一頁(yè)
            // 簡(jiǎn)單示例:如果當(dāng)前頁(yè)返回的數(shù)據(jù)量小于 pageSize,則認(rèn)為沒有更多數(shù)據(jù)了
            // 更準(zhǔn)確的判斷應(yīng)基于 totalElements 或 totalPages
            if (currentPageResult.resp != null && currentPageResult.resp.getBody() != null) {
                List<T> data = currentPageResult.resp.getBody().getData();
                if (data == null || data.size() < pageSize) {
                    hasMore = false;
                }
            } else {
                // 處理異常或空響應(yīng)情況
                hasMore = false;
            }
            page++;
        }
        return allResults;
    }
    登錄后復(fù)制

    請(qǐng)注意,上述迭代邏輯中的currentPageResult.resp.getBody().getData().size() < pageSize是一個(gè)簡(jiǎn)化的判斷邏輯。在實(shí)際應(yīng)用中,更準(zhǔn)確的做法是依賴分頁(yè)響應(yīng)體中提供的totalElements、totalPages或last等字段來(lái)判斷是否還有更多數(shù)據(jù)。

總結(jié)

通過(guò)引入Java的函數(shù)式接口和靜態(tài)工廠方法,我們能夠以高度抽象和描述性的方式處理具有不同參數(shù)簽名的分頁(yè)Feign API。這種方法避免了為每種參數(shù)組合創(chuàng)建大量中間接口和實(shí)現(xiàn)類,顯著減少了樣板代碼,提高了代碼的可讀性和可維護(hù)性。同時(shí),結(jié)合迭代而非遞歸的抽取邏輯,可以構(gòu)建一個(gè)既優(yōu)雅又健壯的通用分頁(yè)數(shù)據(jù)抽取服務(wù)。

以上就是使用Java函數(shù)式接口抽象分頁(yè)Feign API調(diào)用的詳細(xì)內(nèi)容,更多請(qǐng)關(guān)注php中文網(wǎng)其它相關(guān)文章!

最佳 Windows 性能的頂級(jí)免費(fèi)優(yōu)化軟件
最佳 Windows 性能的頂級(jí)免費(fèi)優(yōu)化軟件

每個(gè)人都需要一臺(tái)速度更快、更穩(wěn)定的 PC。隨著時(shí)間的推移,垃圾文件、舊注冊(cè)表數(shù)據(jù)和不必要的后臺(tái)進(jìn)程會(huì)占用資源并降低性能。幸運(yùn)的是,許多工具可以讓 Windows 保持平穩(wěn)運(yùn)行。

下載
來(lái)源:php中文網(wǎng)
本文內(nèi)容由網(wǎng)友自發(fā)貢獻(xiàn),版權(quán)歸原作者所有,本站不承擔(dān)相應(yīng)法律責(zé)任。如您發(fā)現(xiàn)有涉嫌抄襲侵權(quán)的內(nèi)容,請(qǐng)聯(lián)系admin@php.cn
最新問(wèn)題
開源免費(fèi)商場(chǎng)系統(tǒng)廣告
最新下載
更多>
網(wǎng)站特效
網(wǎng)站源碼
網(wǎng)站素材
前端模板
關(guān)于我們 免責(zé)申明 意見反饋 講師合作 廣告合作 最新更新
php中文網(wǎng):公益在線php培訓(xùn),幫助PHP學(xué)習(xí)者快速成長(zhǎng)!
關(guān)注服務(wù)號(hào) 技術(shù)交流群
PHP中文網(wǎng)訂閱號(hào)
每天精選資源文章推送
PHP中文網(wǎng)APP
隨時(shí)隨地碎片化學(xué)習(xí)
PHP中文網(wǎng)抖音號(hào)
發(fā)現(xiàn)有趣的

Copyright 2014-2025 http://ipnx.cn/ All Rights Reserved | php.cn | 湘ICP備2023035733號(hào)