当前位置: 首页 > news >正文

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

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

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

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

在这里插入图片描述

文章目录

    • 定义Response
    • 响应体拦截
    • Rest API测试

定义Response

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结构包装。

package com.juan.demo.common.web.support;import ...@Slf4j
@RestControllerAdvice
public class RestBodyAdvice implements ResponseBodyAdvice<Object> {@Overridepublic boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {return true;}@Overridepublic 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字符串序列化和响应给前端。

调整如下:

package com.juan.demo.common.web.support;import ...@Slf4j
...
public class RestBodyAdvice implements ResponseBodyAdvice<Object> {@Resourceprivate ObjectMapper objectMapper;...@SneakyThrows@Overridepublic 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测试

在这里插入图片描述

在这里插入图片描述

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

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 作为硬件工程师和射频工程师必备的射频前端冷知识
  • 提升前端性能的JavaScript技巧
  • 异步调用实践:Async,Future, TaskExecutor、EventListener
  • 网络编程----TCP/IP协议
  • scrcpy源码 windows10编译傻瓜式教程
  • 字符串查找 - 模拟实现strstr 、BF算法 、 KMP算法
  • 【AI】算力底座的巨变
  • golang中的星号*通配符字符串模式匹配 和问号? 通配符字符串模式匹配的2种实现方法 和相关的单元测试用例
  • SQL Zoo 6.The JOIN operation
  • 【c++】类和对象 (中) (类的默认成员函数)
  • Springboot 实现 Modbus Rtu 协议接入物联网设备
  • matlab实现红绿灯识别
  • MySQL事务隔离级别、InnoDB使用MVCC+各种锁实现了RC和RR事务隔离级别、具体案例
  • cpio 命令
  • element-ui周选择器,如何获取年、周、起止日期?
  • 【附node操作实例】redis简明入门系列—字符串类型
  • Apache的80端口被占用以及访问时报错403
  • ECMAScript入门(七)--Module语法
  • Java深入 - 深入理解Java集合
  • js正则,这点儿就够用了
  • Promise面试题,控制异步流程
  • RxJS: 简单入门
  • 问题之ssh中Host key verification failed的解决
  • 我看到的前端
  • 系统认识JavaScript正则表达式
  • 用jquery写贪吃蛇
  • 原创:新手布局福音!微信小程序使用flex的一些基础样式属性(一)
  • 掌握面试——弹出框的实现(一道题中包含布局/js设计模式)
  • UI设计初学者应该如何入门?
  • 说说我为什么看好Spring Cloud Alibaba
  • # include “ “ 和 # include < >两者的区别
  • # 深度解析 Socket 与 WebSocket:原理、区别与应用
  • #我与Java虚拟机的故事#连载03:面试过的百度,滴滴,快手都问了这些问题
  • (2009.11版)《网络管理员考试 考前冲刺预测卷及考点解析》复习重点
  • (7)STL算法之交换赋值
  • (html转换)StringEscapeUtils类的转义与反转义方法
  • (ZT)出版业改革:该死的死,该生的生
  • (补)B+树一些思想
  • (转)负载均衡,回话保持,cookie
  • ******之网络***——物理***
  • .NET gRPC 和RESTful简单对比
  • .NET MAUI Sqlite程序应用-数据库配置(一)
  • .NET 设计模式—适配器模式(Adapter Pattern)
  • .NET/C# 使用反射注册事件
  • .NET版Word处理控件Aspose.words功能演示:在ASP.NET MVC中创建MS Word编辑器
  • .NET精简框架的“无法找到资源程序集”异常释疑
  • @Bean有哪些属性
  • @RequestBody与@ResponseBody的使用
  • @RequestMapping-占位符映射
  • @RestController注解的使用
  • [2008][note]腔内级联拉曼发射的,二极管泵浦多频调Q laser——
  • [AS3]URLLoader+URLRequest+JPGEncoder实现BitmapData图片数据保存
  • [AutoSar]BSW_Memory_Stack_004 创建一个简单NV block并调试
  • [BeginCTF]真龙之力
  • [Contest20180313]灵大会议