Webplus - returns a unified custom response object

Keywords: Java WebFlux

Preface

[TOC]

Generally speaking, the status code of http request only indicates whether there is a problem in the request, and cannot indicate where the error is. For example, the user is only a business problem and needs to give a warning, but the status code of http does not indicate a business problem. Therefore, many systems adopt the following response

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

I also need such a response body. But webplus requires you to return Mono or Flux objects to meet the requirements of responsive development

So it is not advisable to put the content directly into the response body. It needs to be encapsulated again

Solution

  1. When webplus processes the response information, it wraps a response body by replacing the response content that webplus is about to return
  2. Depending on the method of response body, the response content is reprocessed

First option

Reference resources: https://blog.csdn.net/xuguangyuansh/article/details/100288216
He's a kotlin version
So I wrote a java sringboot version

// Response body
@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;
    }
}

// Tangent bean, unified replacement
/**
 * webflux Unified switching of response information
 */
@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());
    }
}

// Control layer
@RestController
@RequestMapping("/test")
public class UserController {

    @GetMapping("/oop")
    public Mono getStr() {
        // Mono sequence of simulated data acquisition
        final Mono<String> data = Mono.just("test");
        return data;
    }
}

Second option

I wrote it myself

// Response body tool class for decorating 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;
        });
    }
}
// Control layer
@RestController
@RequestMapping("/test")
public class UserController {
    @GetMapping("/oop")
    public Mono getStr() {
        // Analog data acquisition
        final Mono<String> data = Mono.just("test");
        return ResponseInfo.ok(data);
    }
}

Concluding remarks

Constraint language? It doesn't exist. If it helps, please give me a compliment. Thank you!!

Posted by illzz on Thu, 05 Dec 2019 21:00:41 -0800