成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Java 聲明式 Http 接口對接框架

開發(fā) 前端
與其說的是對接的Http接口,不如說是對接的第三方渠道,UniHttp可支持自定義接口渠道方HttpAPI注解以及一些自定義的對接和交互行為 ,為此擴展了發(fā)送和響應(yīng)和反序列化一個Http請求的各種生命周期鉤子,開發(fā)者可自行去擴展實現(xiàn)。

1、簡介

一個聲明式的Http接口對接框架,能以極快的方式完成對一個第三方Http接口的對接和使用,之后就像調(diào)用本地方法一樣自動去發(fā)起Http請求,不需要開發(fā)者去關(guān)注如何發(fā)送一個請求,如何去傳遞Http請求參數(shù),以及如何對請求結(jié)果進行處理和反序列化,這些框架都幫你一一實現(xiàn)

就像配置 Spring的Controller 那樣簡單,只不過相當于是反向配置而已

該框架更注重于如何保持高內(nèi)聚和可讀性高的代碼情況下與快速第三方渠道接口進行對接和集成,而非像傳統(tǒng)編程式的Http請求客戶端(比如HttpClient、Okhttp)那樣專注于如何去發(fā)送Http請求,雖然底層也是用的Okhttp去發(fā)送請求。

與其說的是對接的Http接口,不如說是對接的第三方渠道,UniHttp可支持自定義接口渠道方HttpAPI注解以及一些自定義的對接和交互行為 ,為此擴展了發(fā)送和響應(yīng)和反序列化一個Http請求的各種生命周期鉤子,開發(fā)者可自行去擴展實現(xiàn)。

2、快速開始

2.1、引入依賴

<dependency>
  <groupId>io.github.burukeyou</groupId>
  <artifactId>uniapi-http</artifactId>
  <version>0.0.4</version>
</dependency>

2.2、對接接口

首先隨便創(chuàng)建一個接口,然后在接口上標記@HttpApi注解,然后指定請求的域名url, 然后就可以在方法上去配置對接哪個接口。

比如下面兩個方法的配置則對接了以下兩個接口

  • GET http://localhost:8080/getUser
  • POST http://localhost:8080/addUser

方法返回值定義成Http響應(yīng)body對應(yīng)的類型即可,默認會使用fastjson反序列化Http響應(yīng)body的值為該類型對象。

@HttpApi(url = "http://localhost:8080")
interface UserHttpApi {
    
   @GetHttpInterface("/getUser")
   BaseRsp<String> getUser(@QueryPar("name") String param,@HeaderPar("userId") Integer id);
    
   @PostHttpInterface("/addUser")
   BaseRsp<Add4DTO> addUser(@BodyJsonPar Add4DTO req);
   
}
  • @QueryPar  表示將參數(shù)值放到Http請求的查詢參數(shù)內(nèi)
  • @HeaderPar   表示將參數(shù)值放到Http請求的請求頭里
  • @BodyJsonPar 表示將參數(shù)值放到Http請求body內(nèi),并且content-type是application/json
1)getUser方法最終構(gòu)建的Http請求報文為
GET http://localhost:8080/getUser?name=param
Header:
    userId: id
2)addUser最終構(gòu)建的Http請求報文為
POST:  http://localhost:8080/addUser 
Header: 
    Content-Type:   application/json
Body:
    {"id":1,"name":"jay"}

2.3、聲明定義的HttpAPI的包掃描路徑

在spring的配置類上使用@UniAPIScan注解標記定義的@HttpAPI的包掃描路徑,會自動為標記了@HttpApi接口生成代理對象并且注入到Spring容器中,之后只需要像使用Spring的其他bean一樣,依賴注入使用即可

@UniAPIScan("com.xxx.demo.api")
@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class,args);
    }
}

2.4、依賴注入使用即可

@Service
class UserAppService {
    
    @Autowired
    private UserHttpApi userHttpApi;
    
    public void doSomething(){
        userHttpApi.getUser("jay",3);
    }
}

3、說明介紹

3.1、@HttpApi注解

用于標記接口上,該接口上的方法會被代理到對應(yīng)的Http請求接口,可指定請求的域名,也可指定自定義的Http代理邏輯等等。

3.2、@HttpInterface注解

用于配置一個接口的參數(shù),包括請求方式、請求路徑、請求頭、請求cookie、請求查詢參數(shù)等等

并且內(nèi)置了以下請求方式的@HttpInterface,不必再每次手動指定請求方式

  • @PostHttpInterface
  • @PutHttpInterface
  • @DeleteHttpInterface
  • @GetHttpInterface
@PostHttpInterface(
    // 請求路徑
    path = "/getUser",
    // 請求頭
    headers = {"clientType:sys-app","userId:99"},
    // url查詢參數(shù) 
    params = {"name=周杰倫","age=1"},
    // url查詢參數(shù)拼接字符串
    paramStr = "a=1&b=2&c=3&d=哈哈&e=%E7%89%9B%E9%80%BC",
    // cookie 字符串
    cookie = "name=1;sessionId=999"
)
BaseRsp<String> getUser();

3.3、@Par注解

以下各種Par后綴的注解,主要用于方法參數(shù)上,用于指定在發(fā)送請求時將參數(shù)值放到Http請求體的哪部分上。

為了方便描述,下文描述的普通值就是表示String,基本類型、基本類型的包裝類型等類型.

簡單復(fù)習(xí)下Http協(xié)議報文

圖片圖片

@QueryPar注解

標記Http請求url的查詢參數(shù)

支持以下方法參數(shù)類型的標記: 普通值、普通值集合、對象、Map

@PostHttpInterface
BaseRsp<String> getUser(@QueryPar("id")  String id,  //  普通值   
                        @QueryPar("ids") List<Integer> idsList, //  普通值集合
                        @QueryPar User user,  // 對象
                        @QueryPar Map<String,Object> map); // Map

如果類型是普通值或者普通值集合需要手動指定參數(shù)名,因為是當成單個查詢參數(shù)傳遞

如果類型是對象或者Map是當成多個查詢參數(shù)傳遞,字段名或者map的key名就是參數(shù)名,字段值或者map的value值就是參數(shù)值。

如果是對象,參數(shù)名默認是字段名,由于用的是fastjson序列化可以用@JSONField指定別名

@PathPar注解

標記Http請求路徑變量參數(shù),僅支持標記普通值類型

@PostHttpInterface("/getUser/{userId}/detail")
BaseRsp<String> getUser(@PathPar("userId")  String id);  //  普通值
@HeaderPar注解

標記Http請求頭參數(shù)

支持以下方法參數(shù)類型:對象、Map、普通值

@PostHttpInterface
BaseRsp<String> getUser(@HeaderPar("id")  String id,  //  普通值   
                        @HeaderPar User user,  // 對象
                        @HeaderPar Map<String,Object> map); // Map

如果類型是普通值類型需要手動指定參數(shù)名,當成單個請求頭參數(shù)傳遞. 如果是對象或者Map當成多個請求頭參數(shù)。

@CookiePar注解

用于標記Http請求的cookie請求頭

支持以下方法參數(shù)類型: Map、Cookie對象、字符串

@PostHttpInterface
BaseRsp<String> getUser(@CookiePar("id")  String cookiePar,  //   普通值 (指定name)當成單個cookie鍵值對處理
                        @CookiePar String cookieString,  //  普通值 (不指定name),當成完整的cookie字符串處理
                        @CookiePar com.burukeyou.uniapi.http.support.Cookie cookieObj,  // 單個Cookie對象 
                        @CookiePar List<com.burukeyou.uniapi.http.support.Cookie> cookieList // Cookie對象列表
                        @CookiePar Map<String,Object> map); // Map

如果類型是字符串時,當指定參數(shù)名時,當成單個cookie鍵值對處理,如果不指定參數(shù)名時當成完整的cookie字符串處理比如a=1;b=2;c=3 這樣

如果是Map當成多個cookie鍵值對處理。

如果類型是內(nèi)置的 com.burukeyou.uniapi.http.support.Cookie對象當成單個cookie鍵值對處理

@BodyJsonPar注解

用于標記Http請求體內(nèi)容為json形式: 對應(yīng)content-type為 application/json

支持以下方法參數(shù)類型: 對象、對象集合、Map、普通值、普通值集合

@PostHttpInterface
BaseRsp<String> getUser(@BodyJsonPar  String id,                //  普通值
                        @BodyJsonPar  String[] id               //  普通值集合
                        @BodyJsonPar List<User> userList,       // 對象集合
                        @BodyJsonPar User user,                  // 對象
                        @BodyJsonPar Map<String,Object> map);    // Map

序列化和反序列化默認用的是fastjson,所以如果想指定別名,可以在字段上標記 @JSONField 注解取別名

@BodyFormPar注解

用于標記Http請求體內(nèi)容為普通表單形式: 對應(yīng)content-type為 application/x-www-form-urlencoded

支持以下方法參數(shù)類型:對象、Map、普通值

@PostHttpInterface
BaseRsp<String> getUser(@BodyFormPar("name") String value,         //  普通值
                        @BodyFormPar User user,                   // 對象
                        @BodyFormPar Map<String,Object> map);    // Map

如果類型是普通值類型需要手動指定參數(shù)名,當成單個請求表單鍵值對傳遞

@BodyMultiPartPar注解

用于標記Http請求體內(nèi)容為復(fù)雜形式: 對應(yīng)content-type為 multipart/form-data

支持以下方法參數(shù)類型: 對象、Map、普通值、File對象

@PostHttpInterface
BaseRsp<String> getUser(@BodyMultiPartPar("name") String value,         //  單個表單文本值
                        @BodyMultiPartPar User user,                   // 對象
                        @BodyMultiPartPar Map<String,Object> map,      // Map
                        @BodyMultiPartPar("userImg") File file);     // 單個表單文件值

如果參數(shù)類型是普通值或者File類型,當成單個表單鍵值對處理,需要手動指定參數(shù)名。

如果參數(shù)類型是對象或者Map,當成多個表單鍵值對處理。如果字段值或者map的value參數(shù)值是File類型,則自動當成是文件表單字段傳遞處理

@BodyBinaryPar注解

用于標記Http請求體內(nèi)容為二進制形式: 對應(yīng)content-type為 application/octet-stream

支持以下方法參數(shù)類型: InputStream、File、InputStreamSource

@PostHttpInterface
BaseRsp<String> getUser(@BodyBinaryPar InputStream value,         
                        @BodyBinaryPar File user,                   
                        @BodyBinaryPar InputStreamSource map);
@ComposePar注解

這個注解本身不是對Http請求內(nèi)容的配置,僅用于標記一個對象,然后會對該對象內(nèi)的所有標記了其他@Par注解的字段進行嵌套解析處理, 目的是減少方法參數(shù)數(shù)量,支持都內(nèi)聚到一起傳遞

支持以下方法參數(shù)類型: 對象

@PostHttpInterface
BaseRsp<String> getUser(@ComposePar UserReq req);

比如UserReq里面的字段可以嵌套標記其他@Par注解,具體支持的標記類型和處理邏輯與前面一致

class UserReq {

    @QueryPar
    private Long id;

    @HeaderPar
    private String name;

    @BodyJsonPar
    private Add4DTO req;

    @CookiePar
    private String cook;
}

3.4、原始的HttpResponse

HttpResponse表示Http請求的原始響應(yīng)對象,如果業(yè)務(wù)需要關(guān)注拿到完整的Http響應(yīng),只需要在方法返回值包裝返回即可。

如下面所示,此時HttpResponse<Add4DTO>里的泛型Add4DTO才是代表接口實際返回的響應(yīng)內(nèi)容,后續(xù)可直接手動獲取

@PostHttpInterface("/user-web/get")
HttpResponse<Add4DTO> get();

通過它我們就可以拿到響應(yīng)的Http狀態(tài)碼、響應(yīng)頭、響應(yīng)cookie等等,當然也可以拿到我們的響應(yīng)body的內(nèi)容通過getBodyResult方法

3.5、處理文件下載接口

對于若是下載文件的類型的接口,可將方法返回值定義為 HttpBinaryResponse、HttpFileResponse、HttpInputStreamResponse 的任意一種,這樣就可以拿到下載后的文件。

  • HttpBinaryResponse: 表示下載的文件內(nèi)容以二進制形式返回,如果是大文件請謹慎處理,因為會存放在內(nèi)存中
  • HttpFileResponse:  表示下載的文件內(nèi)容以File對象返回,這時文件已經(jīng)被下載到了本地磁盤
  • HttpInputStreamResponse: 表示下載的文件內(nèi)容輸入流的形式返回,這時文件其實還沒被下載到客戶端,調(diào)用者可以自行讀取該輸入流進行文件的下載

3.6、HttpApiProcessor 生命周期鉤子

HttpApiProcessor是一個Http請求接口的各種生命周期鉤子,開發(fā)者可以實現(xiàn)它在里面自定義編寫各種對接邏輯。然后可以配置到@HttpApi注解或者@HttpInterface注解上, 然后框架內(nèi)部默認會從SpringContext獲取,獲取不到則手動new一個。

通常一個Http請求需要經(jīng)歷 構(gòu)建請求參數(shù)、發(fā)送Http請求時,Http響應(yīng)后獲取響應(yīng)內(nèi)容、反序列化Http響應(yīng)內(nèi)容成具體對象。

目前提供了4種鉤子,執(zhí)行順序流程如下:

postBeforeHttpMetadata  (請求發(fā)送前)在發(fā)送請求之前,對Http請求體后置處理
           |
           V
postSendingHttpRequest  (請求發(fā)送時)在Http請求發(fā)送時處理
           |
           V
postAfterHttpResponseBodyString  (請求響應(yīng)后)對響應(yīng)body文本字符串進行后置處理
           |
           V
postAfterHttpResponseBodyResult  (請求響應(yīng)后)對響應(yīng)body反序列化后的結(jié)果進行后置處理
           |
           V
postAfterMethodReturnValue  (請求響應(yīng)后)對代理的方法的返回值進行后置處理,類似aop的后置處理
  • postBeforeHttpMetadata: 可在發(fā)送http請求之前對請求體進行二次處理,比如加簽之類
  • postSendHttpRequest:   Http請求發(fā)送時會回調(diào)該方法,可以在該方法執(zhí)行自定義的發(fā)送邏輯或者打印發(fā)送日志
  • postAfterHttpResponseBodyString:  Http請求響應(yīng)后,對響應(yīng)body字符串進行進行后置處理,比如如果是加密數(shù)據(jù)可以進行解密
  • postAfterHttpResponseBodyResult:  Http請求響應(yīng)后,對響應(yīng)body反序列化后的對象進行后置處理,比如填充默認返回值
  • postAfterMethodReturnValue:   Http請求響應(yīng)后,對代理的方法的返回值進行后置處理,類似aop的后置處理
回調(diào)參數(shù)說明:
  • HttpMetadata: 表示此次Http請求的請求體,包含請求url,請求頭、請求方式、請求cookie、請求體、請求參數(shù)等等。
  • HttpApiMethodInvocation: 繼承自MethodInvocation, 表示被代理的方法調(diào)用上下文,可以拿到被代理的類,被代理的方法,被代理的HttpAPI注解、HttpInterface注解等信息

3.7、配置自定義的Http客戶端

默認使用的是Okhttp客戶端,如果要重新配置Okhttp客戶端,注入spring的bean即可,如下

@Configuration
public class CusotmConfiguration {

    @Bean
    public OkHttpClient myOHttpClient(){
        return new OkHttpClient.Builder()
                .readTimeout(50, TimeUnit.SECONDS)
                .writeTimeout(50, TimeUnit.SECONDS)
                .connectTimeout(10, TimeUnit.SECONDS)
                .connectionPool(new ConnectionPool(20,10, TimeUnit.MINUTES))
                .build();
    }
}

4、企業(yè)級渠道對接實戰(zhàn)

案例背景:

假設(shè)現(xiàn)在需要對接一個某天氣服務(wù)的所有接口,需要在請求cookie帶上一個token字段和sessionId字段,這兩個字段的值需要每次接口調(diào)用前先手動調(diào)渠道方的一個特定的接口申請獲取,token值在該接口返回值中返回,sessionId在該接口的響應(yīng)頭中返回。

然后還需要在請求頭上帶上一個sign簽名字段, 該sign簽名字段生成規(guī)則需要用渠道方提供的公鑰對所有請求體和請求參數(shù)進行加簽生成。

然后還需要在每個接口的查詢參數(shù)上都帶上一個渠道方分配的客戶端appId。

4.1、在application.yml中配置對接渠道方的信息

channel:
  mtuan:
    # 請求域名
    url: http://127.0.0.1:8999
    # 分配的渠道appId
    appId: UUU-asd-01
    # 分配的公鑰
    publicKey: fajdkf9492304jklfahqq

4.2、自定義該渠道方的HttpAPI注解

假設(shè)現(xiàn)在對接的是某團,所以自定義注解叫@MTuanHttpApi吧,然后需要在該注解上標記@HttpApi注解,并且需要配置processor字段,需要去自定義實現(xiàn)一個HttpApiProcessor這個具體實現(xiàn)后續(xù)講。

有了這個注解后就可以自定義該注解與對接渠道方相關(guān)的各種字段配置,當然也可以不定義。

注意這里url的字段是使用 @AliasFor(annotation = HttpApi.class),這樣構(gòu)建的HttpMetadata中會默認解析填充要請求體,不標記則也可自行處理。

@Inherited
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@HttpApi(processor = MTuanHttpApiProcessor.class)
public @interface MTuanHttpApi {

    /**
     * 渠道方域名地址
     */
    @AliasFor(annotation = HttpApi.class)
    String url() default "${channel.mtuan.url}";

    /**
     * 渠道方分配的appId
     */
    String appId() default "${channel.mtuan.appId}";
}
@Slf4j
@Component
public class MTuanHttpApiProcessor implements HttpApiProcessor<MTuanHttpApi> {
    
}

注意實現(xiàn)的HttpApiProcessor泛型要指定為剛才定義的注解@MTuanHttpApi類型,因為這個HttpApiProcessor配置到它上面,如果需要通用處理可以定義為Annocation類型

4.3、對接接口

有了@MTuanHttpApi注解之后就可以開始對接接口了,比如假設(shè)有兩個接口要對接。一個就是前面說的獲取令牌的接口。一個是獲取天氣情況的接口。

為什么getToken方法返回值是 HttpResponse,這是UniHttp內(nèi)置的原始Http響應(yīng)對象,方便我們?nèi)ツ玫皆糎ttp響應(yīng)體的一些內(nèi)容(比如響應(yīng)狀態(tài)碼、響應(yīng)cookie)。

其中的泛型BaseRsp才是實際的Http響應(yīng)體反序列化后的內(nèi)容。而getCityWeather方法沒有使用HttpResponse包裝,BaseRsp只是單純Http響應(yīng)體反序列化后的內(nèi)容,這是兩者的區(qū)別。

前面介紹過 HttpResponse,其實大部份接口是不關(guān)注HttpResponse的可以不用去配置。

@MTuanHttpApi
public interface WeatherApi {
    
    /**
     * 根據(jù)城市名獲取天氣情況
     */
    @GetHttpInterface("/getCityByName")
    BaseRsp<WeatherDTO> getCityWeather(@QueryPar("city") String cityName);

    /**
     *  根據(jù)appId和公鑰獲取令牌
     */
    @PostHttpInterface("/getToken")
    HttpResponse<BaseRsp<TokenDTO>> getToken(@HeaderPar("appId") String appId, @HeaderPar("publicKey")String publicKey);

}

4.4、自定義HttpApiProcessor

在之前我們自定義了一個@MTuanHttpApi注解上指定了一個MTuanHttpApiProcessor,接下來我們?nèi)崿F(xiàn)他的具體內(nèi)容為了實現(xiàn)我們案例背景里描述的功能。

@Slf4j
@Component
public class MTuanHttpApiProcessor implements HttpApiProcessor<MTuanHttpApi> {

    /**
     *  渠道方分配的公鑰
     */
    @Value("${channel.mtuan.publicKey}")
    private String publicKey;

    @Value("${channel.mtuan.appId}")
    private String appId;

    @Autowired
    private Environment environment;
    
    @Autowired
    private WeatherApi weatherApi;

    /** 實現(xiàn)-postBeforeHttpMetadata: 發(fā)送Http請求之前會回調(diào)該方法,可對Http請求體的內(nèi)容進行二次處理
     *
     * @param httpMetadata              原來的請求體
     * @param methodInvocation          被代理的方法
     * @return                          新的請求體
     */
    @Override
    public HttpMetadata postBeforeHttpMetadata(HttpMetadata httpMetadata, HttpApiMethodInvocation<MTuanHttpApi> methodInvocation) {
        /**
         * 在查詢參數(shù)中添加提供的appId字段
         */
        // 獲取MTuanHttpApi注解
        MTuanHttpApi apiAnnotation = methodInvocation.getProxyApiAnnotation();

        // 獲取MTuanHttpApi注解的appId,由于該appId是環(huán)境變量所以我們從environment中解析取出來
        String appIdVar = apiAnnotation.appId();
        appIdVar = environment.resolvePlaceholders(appIdVar);

        // 添加到查詢參數(shù)中
        httpMetadata.putQueryParam("appId",appIdVar);

        /**
         *  生成簽名sign字段
         */
        // 獲取所有查詢參數(shù)
        Map<String, Object> queryParam = httpMetadata.getHttpUrl().getQueryParam();

        // 獲取請求體參數(shù)
        HttpBody body = httpMetadata.getBody();

        // 生成簽名
        String signKey = createSignKey(queryParam,body);

        // 將簽名添加到請求頭中
        httpMetadata.putHeader("sign",signKey);

        return httpMetadata;
    }

    private String createSignKey(Map<String, Object> queryParam, HttpBody body) {
        // todo 偽代碼
        // 1、將查詢參數(shù)拼接成字符串
        String queryParamString = queryParam.entrySet()
                .stream().map(e -> e.getKey() + "="+e.getValue())
                .collect(Collectors.joining(";"));

        // 2、將請求體參數(shù)拼接成字符串
        String bodyString = "";
        if (body instanceof HttpBodyJSON){
            // application/json  類型的請求體
            bodyString = body.toStringBody();
        }else if (body instanceof HttpBodyFormData){
            // application/x-www-form-urlencoded 類型的請求體
            bodyString = body.toStringBody();
        }else if (body instanceof HttpBodyMultipart){
            // multipart/form-data 類型的請求體
            bodyString =  body.toStringBody();
        }

        // 使用公鑰publicKey 加密拼接起來
        String sign = publicKey + queryParamString + bodyString;
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            byte[] digest = md.digest(sign.getBytes());
            return new String(digest);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     *  實現(xiàn)-postBeforeHttpMetadata: 發(fā)送Http請求時,可定義發(fā)送請求的行為 或者打印請求和響應(yīng)日志。
     */
    @Override
    public HttpResponse<?> postSendHttpRequest(HttpSender httpSender, HttpMetadata httpMetadata) {
        //  忽略 weatherApi.getToken的方法回調(diào),否則該方法也會回調(diào)此方法會遞歸死循環(huán)。 或者該接口指定自定義的HttpApiProcessor重寫postSendingHttpRequest
        Method getTokenMethod = ReflectionUtils.findMethod(WeatherServiceApi.class, "getToken",String.class,String.class);
        if (getTokenMethod == null || getTokenMethod.equals(methodInvocation.getMethod())){
            return httpSender.sendHttpRequest(httpMetadata);
        }
        
        // 1、動態(tài)獲取token和sessionId
        HttpResponse<String> httpResponse = weatherApi.getToken(appId, publicKey);

        // 從響應(yīng)體獲取令牌token
        String token = httpResponse.getBodyResult();
        // 從響應(yīng)頭中獲取sessionId
        String sessionId = httpResponse.getHeader("sessionId");

        // 把這兩個值放到此次的請求cookie中
        httpMetadata.addCookie(new Cookie("token",token));
        httpMetadata.addCookie(new Cookie("sessionId",sessionId));
        
        log.info("開始發(fā)送Http請求 請求接口:{} 請求體:{}",httpMetadata.getHttpUrl().toUrl(),httpMetadata.toHttpProtocol());

        // 使用框架內(nèi)置工具實現(xiàn)發(fā)送請求
        HttpResponse<?> rsp =  httpSender.sendHttpRequest(httpMetadata);

        log.info("開始發(fā)送Http請求 響應(yīng)結(jié)果:{}",rsp.toHttpProtocol());
        
        return rsp;
    }

    /**
     *  實現(xiàn)-postAfterHttpResponseBodyResult: 反序列化后Http響應(yīng)體的內(nèi)容后回調(diào),可對該結(jié)果進行二次處理返回
     * @param bodyResult                     Http響應(yīng)體反序列化后的結(jié)果
     * @param rsp                            原始Http響應(yīng)對象
     * @param method                         被代理的方法
     * @param httpMetadata                   Http請求體
     */
    @Override
    public Object postAfterHttpResponseBodyResult(Object bodyResult, HttpResponse<?> rsp, Method method, HttpMetadata httpMetadata) {
        if (bodyResult instanceof BaseRsp){
            BaseRsp baseRsp = (BaseRsp) bodyResult;
            // 設(shè)置
            baseRsp.setCode(999);
        }
        
        return bodyResult;
    }
}

上面我們分別重寫了postBeforeHttpMetadata、postSendHttpRequest、postAfterHttpResponseBodyResult三個生命周期的鉤子方法去完成我們的需求,在發(fā)送請求前對請求體進行加簽、在發(fā)送請求時動態(tài)獲取令牌重新構(gòu)建請求體和打印日志、在發(fā)送請求后給響應(yīng)對象設(shè)置code為999。

責任編輯:武曉燕 來源: 一安未來
相關(guān)推薦

2025-05-06 00:12:10

2020-12-17 07:59:46

聲明式代碼命令式代碼代碼

2009-06-22 09:01:57

Spring聲明式事務(wù)

2022-06-21 08:12:17

K8sAPI對象Kubernetes

2024-11-13 19:03:14

2013-06-27 09:31:37

聲明式編程命令式編程編程

2009-09-02 14:18:08

C#聲明COM接口

2020-09-04 06:27:22

編碼命令式聲明式代碼

2021-09-06 13:42:14

Spring聲明式事務(wù)

2009-09-02 14:26:50

C#對接口成員訪問

2024-02-28 08:37:28

Lambda表達式Java函數(shù)式接口

2023-08-30 13:22:00

測試框架工具

2014-10-30 18:44:45

暢捷通T+平臺

2022-08-23 16:07:02

ArkUI鴻蒙

2010-05-26 13:56:59

Tomcat 7Servlet 3.0

2009-09-01 10:49:28

C#具有隱式類型聲明

2025-01-16 08:45:48

2019-07-04 15:13:16

分布式緩存Redis

2009-07-07 17:32:31

HTTP Servle

2012-03-15 11:21:19

Java
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 国产一区2区 | 国内精品久久久久久 | 精品国产一区二区三区四区在线 | www.99re| 国产成人精品久久久 | 中文字幕视频在线看 | 成人精品免费视频 | 欧美视频二区 | 亚洲精品久久久久久久久久久久久 | 欧美a v在线| 欧美福利专区 | 国产精品久久 | 看片网站在线 | 精品国产伦一区二区三区观看体验 | 欧美成人黄色小说 | 国产成人综合一区二区三区 | 国产日韩视频 | 日本三级全黄三级a | 综合自拍 | 国产免费a视频 | 欧美影院 | 婷婷精品 | 激情六月天| 九九热最新视频 | 亚洲精品久久久久久久不卡四虎 | 一本色道精品久久一区二区三区 | 毛片免费观看视频 | 亚洲国产aⅴ精品一区二区 免费观看av | 日本视频在线播放 | 成人a在线观看 | 成人免费大片黄在线播放 | 午夜免费在线电影 | 99精品免费久久久久久久久日本 | 6996成人影院网在线播放 | 久久亚洲欧美日韩精品专区 | 国产高清久久 | 国产精品免费在线 | 欧美日韩视频 | 色婷婷综合久久久中字幕精品久久 | 亚洲国产精品一区二区三区 | jdav视频在线观看免费 |