webflux-返回統一的自定義響應對象

前言

[TOC]java

通常來講,http請求的狀態碼,只是代表請求是否有問題,不能代表錯再哪裏了.好比用戶只是業務問題,須要給個警告,可是http的狀態碼不能說明業務問題.因而不少系統都採用了相似以下的響應體react

{
    code: xxx,
    msg: xxx,
    data: xxxxxx
}

我也是須要這樣的響應體.可是webflux須要你返回Mono對象或者Flux對象.才符合響應式開發的必要條件.web

因此常規的直接把內容放到響應體中是不可取的.須要再封裝.spring

解決方案

第一種(親測問題巨多)app

  • 在webflux處理響應信息的時候,經過切面替換webflux即將要返回的響應內容,包裝一個響應體.
  • 優勢工具

    • 侵入性小
  • 缺點oop

    • 接受類型衆多須要適配.net

      • 本代碼中只適配了2種常規類型
      • 一旦用戶返回Flux或者其餘內容直接報錯了.
    • 問題巨多不一一描述了

第二種(相對完美的方案)code

  • 依靠響應體的方法,把響應內容再加工
  • 優勢對象

    • 不影響webflux源碼
    • 基本沒有任何問題
    • 只須要修改響應體代碼
  • 缺點

    • 侵入性(通常響應體也是這樣,因此也不太算缺點)

第一個方案

參考:https://blog.csdn.net/xuguangyuansh/article/details/100288216
他的是kotlin版的.
因此我寫了一個java sringboot版的.

// 響應體
@Data
@ToString
public class ResponseInfo<T> implements Serializable {
    String msg;
    Integer code;
    Object data;
    
    public static <T> ResponseInfo<T> ok (T monoBody) {
        final ResponseInfo<T> responseInfo = new ResponseInfo<>();
        responseInfo.setCode(0);
        responseInfo.setData(monoBody);
        responseInfo.setMsg("ok");
        return responseInfo;
    }
}
// 切面bean,統一替換.
/**
 * webflux響應信息統一切換
 */
@Aspect
@Component
@ConditionalOnClass(name = {"org.springframework.web.reactive.result.method.annotation.ResponseBodyResultHandler"})
public class ResponseBodyResultHandlerAspect {

    @SneakyThrows
    @Around(value = "execution(* org.springframework.web.reactive.result.method.annotation.ResponseBodyResultHandler.handleResult(..)) && args(exchange, result)", argNames = "point,exchange,result")
    public Object handleResult(ProceedingJoinPoint point, ServerWebExchange exchange, HandlerResult result) {
        final Mono responseMono = ((Mono) result.getReturnValue()).map(responseValue -> responseValue instanceof ResponseInfo ? responseValue : ResponseInfo.ok(responseValue));
        return point.proceed(Arrays.asList(
                exchange,
                new HandlerResult(result.getHandler(), responseMono, result.getReturnTypeSource())
        ).toArray());
    }
}
// 控制層
@RestController
@RequestMapping("/test")
public class UserController {

    @GetMapping("/oop")
    public Mono getStr() {
        // 模擬獲取數據的Mono序列
        final Mono<String> data = Mono.just("test");
        return data;
    }
}

第二個方案

本身寫的.

// 裝飾Mono的響應體工具類,本身修改一下本身的響應體對象也能夠
@Data
@ToString
public class ResponseInfo<T> implements Serializable {
    String msg;
    Integer code;
    Object data;

    public static <T> Mono<ResponseInfo<T>> ok (Mono<T> monoBody) {
        return responseBodyCreate(monoBody,0,null);
    }

    public static <T> Mono<ResponseInfo<T>> ok (Mono<T> monoBody, String msg) {
        return responseBodyCreate(monoBody,0,msg);
    }

    public static <T> Mono<ResponseInfo<T>> ok (Mono<T> monoBody, int code, String msg) {
        return responseBodyCreate(monoBody,code,msg);
    }

    public static <T> Mono<ResponseInfo<T>> failed (Mono<T> monoBody) {
        return responseBodyCreate(monoBody,0,null);
    }

    public static <T> Mono<ResponseInfo<T>> failed (Mono<T> monoBody, String msg) {
        return responseBodyCreate(monoBody,0,msg);
    }

    public static <T> Mono<ResponseInfo<T>> failed (Mono<T> monoBody, int code, String msg) {
        return responseBodyCreate(monoBody,code,msg);
    }

    private static <T> Mono<ResponseInfo<T>> responseBodyCreate(Mono<T> monoData, int code, String msg) {
        return monoData.map(data-> {
            final ResponseInfo<T> responseInfo = new ResponseInfo<>();
            responseInfo.setCode(code);
            responseInfo.setData(data);
            responseInfo.setMsg(msg);
            return responseInfo;
        });
    }
}
// 控制層
@RestController
@RequestMapping("/test")
public class UserController {
    @GetMapping("/oop")
    public Mono getStr() {
        // 模擬獲取數據
        final Mono<String> data = Mono.just("test");
        return ResponseInfo.ok(data);
        
        // 簡寫
        // return ResponseInfo.ok(Mono.just("test"));
    }
}

結束語

約束語?不存在的,若是有幫助就請給個贊把.感謝!!

相關文章
相關標籤/搜索