Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Webflux doesn't support ResponseBodyAdvice yet?

Tags:

Since ResponseBodyAdvice interface is in web.servlet package How could I implement such functions in webflux?

like image 425
user3435786 Avatar asked Feb 09 '18 11:02

user3435786


1 Answers

I also have this problem, i found it can be done by HandlerResultHandler.

For Example, I extend ResponseBodyResultHandler to wrap all my response

First, you should write ResponseWrapper.java

public class ResponseWrapper extends ResponseBodyResultHandler {
    private static MethodParameter param;

    static {
        try {
            //get new params
            param = new MethodParameter(ResponseWrapper.class
                    .getDeclaredMethod("methodForParams"), -1);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }

    public ResponseWrapper(List<HttpMessageWriter<?>> writers, RequestedContentTypeResolver resolver) {
        super(writers, resolver);
    }

    private static Mono<Response> methodForParams() {
        return null;
    }

    @Override
    public boolean supports(HandlerResult result) {
        boolean isMono = result.getReturnType().resolve() == Mono.class;
        boolean isAlreadyResponse = result.getReturnType().resolveGeneric(0) == Response.class;
        return isMono && !isAlreadyResponse;
    }

    @Override
    @SuppressWarnings("unchecked")
    public Mono<Void> handleResult(ServerWebExchange exchange, HandlerResult result) {
        Preconditions.checkNotNull(result.getReturnValue(), "response is null!");
        // modify the result as you want
        Mono<Response> body = ((Mono<Object>) result.getReturnValue()).map(Response::success)
                .defaultIfEmpty(Response.success());
        return writeBody(body, param, exchange);
    }
}    

Then, add Bean in SpringBootApplication

@SpringBootApplication
public class SmartApplication {

    @Autowired
    ServerCodecConfigurer        serverCodecConfigurer;
    @Autowired
    RequestedContentTypeResolver requestedContentTypeResolver;

    @Bean
    ResponseWrapper responseWrapper() {
        return new ResponseWrapper(serverCodecConfigurer
                .getWriters(), requestedContentTypeResolver);
    }
    //Spring start
    public static void main(String[] args) {
        SpringApplication.run(SmartApplication.class, args);
    }
}

My response class, for reference

@JsonInclude(JsonInclude.Include.NON_NULL)
public class Response<T> {
    boolean success;
    T       data;
    Object  error;
    String  warning;

    public Response() {
    }


    public static Response success() {
        return success(null);
    }

    public static <T> Response success(T data) {
        return new Response<T>().setSuccess(true).setData(data);
    }

    public static Response error(Throwable e) {
        LogManager.getLogger(StackLocatorUtil.getCallerClass(2)).info(e);
        return new Response().setSuccess(false).setError(e);
    }

    public static Response error(Object e) {
        return new Response().setSuccess(false).setError(e);
    }

    public static Response error(String e) {
        return new Response().setSuccess(false).setError(e);
    }

    /* get success */
    public boolean isSuccess() {
        return success;
    }

    /* set success */
    public Response setSuccess(boolean success) {
        this.success = success;
        return this;
    }

    /* get data */
    public Object getData() {
        return data;
    }

    /* set data */
    public Response setData(T data) {
        this.data = data;
        return this;
    }

    /* get error */
    public Object getError() {
        return error;
    }

    /* set error */
    public Response setError(Object error) {
        this.error = error;
        return this;
    }
}
like image 107
Lambda Avatar answered Sep 20 '22 12:09

Lambda