解析springboot包装controller返回值问题

1、springboot项目统一包装返回值,通常返回结果包含code、message、data,结构如下

import lombok.AllArgsConstructor;

import lombok.Data;

import lombok.NoArgsConstructor;

@Data

@NoArgsConstructor

@AllArgsConstructor

public class ResponseResult<T> {

    private int code;

    private String message;

    private T data;

    public ResponseResult(T data) {

        this.data = data;

        this.code = 0;

        this.message = "success";

    }

}

2、基于ControllerAdvice和HttpMessageConverter实现

定义类ResponseAdvisor实现ResponseBodyAdvice接口,重写supports跟beforeBodyWrite方法

import org.springframework.core.MethodParameter;

import org.springframework.http.MediaType;

import org.springframework.http.ResponseEntity;

import org.springframework.http.converter.HttpMessageConverter;

import org.springframework.http.server.ServerHttpRequest;

import org.springframework.http.server.ServerHttpResponse;

import org.springframework.web.bind.annotation.ControllerAdvice;

import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

@ControllerAdvice

public class ResponseAdvisor implements ResponseBodyAdvice<Object> {

    @Override

    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {

        return true;

    }

    @Override

    public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType,

                                  Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest,

                                  ServerHttpResponse serverHttpResponse) {

        if(o instanceof ResponseResult){

            return o;

        }

        return new ResponseResult<>(o);

    }

3、接口测试

3.1 测试返回Object类型:

@RestController

@RequestMapping("/test")

public class TestController {

    @GetMapping("/test")

    public Test test(){

        return new Test("test", 10);

    }

}

执行结果如下:

@RestController

@RequestMapping("/test")

public class TestController {

    @GetMapping("/test")

    public Test test(){

        return new Test("test", 10);

    }

    @GetMapping("/test1")

    public String test1(){

        return "test";

    }

}

执行结果如下:

3.3 如果Controller类的返回值没有String类型的,仅有上面这个类就够了。如果有String类型的返回值,就有可能遇到类型不匹配的问题。HttpMessageConverter是根据Controller的原始返回值类型进行处理的,而我们在ResponseAdvisor中改变了返回值的类型。如果HttpMessageConverter处理的目标类型是Object还好说,如果是其它类型就会出现问题,其中最容易出现问题的就是String类型,因为在所有的HttpMessageConverter实例集合中,StringHttpMessageConverter要比其它的Converter排得靠前一些。我们需要尝试将处理Object类型的HttpMessageConverter放得靠前一些,这可以在一个Configuration类中完成:

import org.springframework.context.annotation.Configuration;

import org.springframework.http.converter.HttpMessageConverter;

import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;

import org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration;

import java.util.List;

@Configuration

public class ResponseResultConfig extends DelegatingWebMvcConfiguration {

    @Override

    protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {

        converters.add(0, new MappingJackson2HttpMessageConverter());

        super.configureMessageConverters(converters);

    }

}

3.4 重启服务后再次测试返回String类型,返回结果如下:

 3.5 测试返回其他基本数据类型,也都没问题。

 欢迎大家添加博主微信,备注“技术交流”,拉你进技术交流群

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值