Spring Boot 3.x Rest API最佳实践之统一响应结构

上一篇:Spring Boot 3.x Rest API最佳实践之API实现

下一篇:Spring Boot 3.x Rest API统一异常处理最佳实践

前面我们完成了电商示例API的设计和简单实现,本小节在此基础上完成统一响应结构的实战。

文章目录

定义Response

java 复制代码
package com.juan.demo.common.dto;


import ...

@Getter
@Setter
@ToString
public class Response<T> {

    /** 响应状态:0-成功 1-失败 */
    private Integer status;

    /** 实际数据 */
    @JsonInclude(JsonInclude.Include.NON_NULL)
    private T data;

    private static final Integer STATUS_SUCCESS = 0;

    public Response() {}

    private Response(Integer status, T data) {
        this.status = status;
        this.data = data;
    }

    public static <T> Response<T> ok(T data) {
        return new Response<>(STATUS_SUCCESS, data);
    }

    public static <T> Response<T> ok() {
        return ok(null);
    }

    public static void main(String[] args) {
        System.out.println(Response.ok());
        System.out.println(Response.ok(new ProductResultItemDTO(1L, "spring boot3入门", 30000)));
    }

}

主要考察类上的泛型和方法上的泛型的用法。以及结合构造器重载、静态方法重载的使用,以及通过静态方法返回该类的实例,而不是外部去new(调相关的构造器)。

注意

这里除了无参构造(提供给外部的框架,如JacksonFastJson来通过反射创建其实例),其他都做成私有的,外部无法new。

如果数据域是空的(null),将被忽略,不会参与json的序列化。

响应体拦截

实现ResponseBodyAdvice接口,对所有的Rest Controller的响应结果进行拦截,做统一的json结构包装。

java 复制代码
package com.juan.demo.common.web.support;

import ...

@Slf4j
@RestControllerAdvice
public class RestBodyAdvice implements ResponseBodyAdvice<Object> {
    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        return Response.ok(body);
    }
}

这里的@RestControllerAdvice表明我们要对所有响应Rest API的控制器的响应都做拦截,是否要拦截可以实现supports方法中的判断逻辑,比如像swagger在线文档的数据请求这里就应该返回false,后续碰到时再完善。

beforeBodyWrite方法中,我们直接用之前定义好的统一响应类型Response的静态方法ok(body)来返回统一的结构,这样返回的对象,会由web模块集成的json框架自动完成json序列化响应给浏览器客户端。

测试之前的api,发现hello api报错:

复制代码
java.lang.ClassCastException: class com.juan.demo.common.dto.Response cannot be cast to class java.lang.String (com.juan.demo.common.dto.Response is in unnamed module of loader org.springframework.boot.devtools.restart.classloader.RestartClassLoader @31d7df32; java.lang.String is in module java.base of loader 'bootstrap')

这是因为String类型的返回结果,web框架在解析映射方法的时候就已经决定好了要将响应结果转成字符串给前端响应。因此我们要在beforeBodyWrite方法中,对api返回值为String类型的情况进行判断,手动进行json字符串序列化和响应给前端。

调整如下:

java 复制代码
package com.juan.demo.common.web.support;

import ...

@Slf4j
...
public class RestBodyAdvice implements ResponseBodyAdvice<Object> {

    @Resource
    private ObjectMapper objectMapper;

    ...

    @SneakyThrows
    @Override
    public Object beforeBodyWrite(...) {
        // 获取api返回值类型
        Type type = returnType.getGenericParameterType();
        log.info("type = {}", type);
        // 如果已经是字符串,则手动json序列化,并将内容类型重置为json格式,默认是普通文本格式
        if (type == String.class) {
            response.getHeaders().set("Content-Type", MediaType.APPLICATION_JSON_VALUE);
            return objectMapper.writeValueAsString(Response.ok(body));
        }
        ...
    }
}

再次测试,ok!

Rest API测试

其他测试留给读者自行验证。

相关推荐
vx-程序开发5 小时前
【计算机毕设】django校园跑腿服务系统83141
java·数据库·vue.js·spring boot·spring·elasticsearch·django
一 乐6 小时前
养老院管理系统|基于springboot + vue养老院管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·毕业设计
今年下半年8 小时前
SpringBoot整合金蝶中间件
spring boot·中间件·maven
字节探索9 小时前
别再只会写 Controller 了!一文吃透 Spring Boot 高级特性与项目实战
spring boot·spring
MetaLite9 小时前
全网最好的SpringBoot接口请求对象设计
java·spring boot·后端
摇滚侠10 小时前
《Spring Boot 3:高级与架构设计》第 2 章 IOC容器的高级机制 BeanFactoryPostProcessor 个人理解 6
java·spring boot·笔记·后端
xcl092511 小时前
宠物商城社交托运购物系统开发实战:从架构设计到完整实现指南
java·spring boot
没差c11 小时前
RetrofitClient写接口、导包、配置、路径
java·spring boot·okhttp
RuoyiOffice12 小时前
SpringBoot+Vue3 节日主题换肤实战:一条参数换全站配色,节后自动还原
spring boot·vue3·spring boot 3·vben admin·ruoyi office·节日主题·换肤方案
摇滚侠12 小时前
《Spring Boot 3:高级与架构设计》第 2 章 IOC容器的高级机制 Environment 个人理解 4
java·spring boot·笔记·后端