# 问题背景
项目后端与前端全部使用 JSON 进行数据交互,比如查询用户列表,通常后端从数据库查出的数据放入实体类再转为 JSON 返回给前端,但是前端的小伙伴表示明明只需要 nickname,avatar,userId 三个字段,为什么传过来的数据多出 phone,address ,profile 之类十几个字段,里面都 null,0 等值?
其实是因为 User 实体类定义了太多字段,转为 JSON 的时候都被包括进去了。稍微多几个还能忍,但通常 User/Order 这些实体类字段特别多,对调试开发实在非常不友好。
因此本次任务就是:确保每个接口返回字段都与接口文档上一模一样,去除冗余字段。
解决过程就省略了,直接抛出我最后的解决方案吧:就是 MyBatis 的返回值几乎完全抛弃实体类,全部使用com.alibaba.fastjson.JSONObject
。
# 使用 JSONObject
先最简化直观的看一下 JSONObject 的使用吧。
Controller:
|
|
Service:
|
|
ServiceImpl:
|
|
Dao:
|
|
UserMapper.xml , 这里的 resultType 直接就是 JSONObject ,如果是一对多的情况,就要多加一步,请移步看这篇文章。
|
|
# 为什么可以使用JSONObject
因为 JSONObject 实现了 Map<String,Object>
, MyBatis 那边完全是把它当成 Map<String,Object>
处理的,相信不少人都直接用过 map 来接收MyBatis 返回结果。
fastjson 是这样的,Gson 并不是,所以 Gson 的 JsonObject 是不可以的。
有兴趣了解更深入的原理的话,请参考我此系列的其它文章。
# 优劣对比
# 便捷性
JSONObject 便捷到可以说是无脑,接收参数、 sql 传参、封装 sql 结果、返回到前端,全程使用。
JavaBean 则接口层接收参数转为实体类,返回给前端再转为 json,新增一个业务通常还需要多建一个实体类。
# 工具方法拓展
JSONObject 可以方便地封装出通用的工具方法,比如封装分页信息,比如封装处理结果的成功和失败信息,特别是校验参数字段非空,不同的接口通常需要校验的字段不同,如下面这个简单的方法就可以校验各字段是否都非空。
|
|
JavaBean 在处理分页上通常要引各自写的 PageBean 工具类 , 使用过程通常不会比上面ServiceImpl里的分页简单。
JavaBean 的参数校验都不用说,更头痛更复杂了,不知道有没有人有用起来很爽的方法。
# 返回字段
JSONObject 想返回几个字段就几个字段,而 JavaBean 如果只想返回某几个字段的话,就需要单独建个实体类。
字段有改动的话,JSONObject 灵活性就更强了,直接在 mapper.xml 里改下就完事。
# 业务层
不可否认的是,JSONObject 在业务层进行处理时,失去了 JavaBean 的编译提示,也失去了 IDE 的快捷补全,更有可能出现取错值的情况。
比如 jsonObject.getString(“pasword”) ,输入错了单词都可能没注意,最终取出来 null 。
# 可读性
通常大家可能认为 JavaBean 有更好的可读性,我觉得只要变量名取得好,JSONObject 也是没有什么问题的。毕竟类名是固定死的,变量名和参数名才能更好地反映此处业务的处理。
尤其是如今前后端分离的项目,前后端开发人员一般对照着文档确认字段含义。
# 总结
JSONObject 开发非常方便,具有更强的灵活性,适用于中小型项目,简单业务的开发,也适用于文档至上的前后端分离开发与微服务项目。
更具体的用法,可以参考 Github 项目。