网站首页 > 技术文章 正文
SpringBoot + Mybatis + Shiro + mysql + redis智能平台源码分享 推荐阅读
1 抛砖引玉
先来看一段十分基础的业务代码
Map<String, Object> map = service.getDataByName("悟空GoKu");
Long userId = (Long)map.get("userId");
String phone = (String)map.get("phone");
复制代码
每次我写这种map获取返回数据总是感觉十分别扭
- map就像个无底洞,你不看服务提供方代码的话就不知道里面到底放了什么key。
- 拿到数据之后都要自己强转一下,有点麻烦。
- 这玩意有潜在的类型转换异常发生。
2 请求参数Request
首先要肯定的是用map来传输参数(前端http请求后端接口)真的是方便,不需要额外去定义一个类,想往里面塞什么数据就塞什么,就如下面的例子,不需要为每个接口都定义一个RequestVo类,统一map接收
@PostMapping(value = "/map")
public ApiResponse testMap(@RequestBody Map<String, Object> map) {
//获取map中的数据
Long userId = (Long)map.get("userId");
String phone = (String)map.get("phone");
//业务代码...
return ApiResponse.ok();
}
复制代码
上面说了我不喜欢这样获取数据,但也不喜欢定义一个类来接收,因为这样会造成类数量激增,可能一个请求接口就得对应创建一个请求类。
有人说不定义成类,有些额外的功能就无法使用:
- swagger这种文档注解无法完美兼容。
不想用swagger,代码侵入性太强,样式、目录展示也一般,接口文档推荐开源yapi
swagger有时确实方便,增加参数时,代码跟文档同时更新,不必额外维护文档,但我还是不喜欢将文档跟代码耦合在一起。
- validator验证注解无法使用。
验证逻辑我还是喜欢写在controller,逻辑更清晰。
原来的注解不一定适合某些复杂验证,那岂不是要自定义注解,又回到了类激增的问题
说回了map,map.get(key)这样获取数据确实别扭,但我们可以封装请求啊, 例如上一篇文章<<当技术leader说要把接口设计成RESTful,我拒绝了>>提到的ApiRequest。
public class ApiRequest implements Serializable {
//....省略部分代码
private Map<String, Object> data; //通过拦截器处理后请求参数已存放在这里
public Long getDataParamAsLong(String name, Long defaultValue) {
Long i = defaultValue;
try{
i = StringUtils.isNotEmpty(getDataParamAsString(name)) ?
Long.valueOf(getDataParamAsString(name)) : defaultValue;
}catch (Exception e){
e.printStackTrace();
}
return i;
}
}
复制代码
@PostMapping(value = "/test")
public ApiResponse test(ApiRequest apiRequest) {
Long userId = apiRequest.getDataParamAsLong("userId", 0L);
//省略部分代码....
ApiResponse response = ApiResponse.ok()
return response;
}
复制代码
这里已经是面向json编程了,而不是以往的面向对象。
3 响应参数Response
对于返回数据,我一般会在controller层拿到service的数据后再根据业务需求来处理数据(结构修改,数据整合),最终用map整合再response,给前端一个合适的结构, 而不是数据库查到什么就整个类对象返回。
当前有些返回数据我也会定义一个类ReponseVo封装,最后return给前端
你这前后矛盾啊,之前还说不要面向对象。
这里主要考虑的有些场景下,多个接口返回的数据完全一样,可以共用。 对于部分app开发者来说,他们会依赖后台的接口来定义自己的model,相似的数据会要求后台返回的字段命名和结构一样,以便他们能共用model。
这.......其实他们可以自己定义属于他们的model,而不是完全依赖后台字段命名。
4 service层数据传输
前面说的是前端/移动端http请求我们的网关接口,这里是说我们服务端之间的远程方法调用/本地方法调用,也可以理解成service层方法调用。如果是多个参数的话,需要封装一个DTO,这里最好不用map。
- 这种接口我们不可能去写一份文档来维护。
- 数据反序列化问题(划重点)。
如果某个方法内部使用了缓存,且通过json反序列化后才返回,容易引发调用方发生异常
//set
@PostMapping(value = "/setData")
public ApiResponse setData(ApiRequest request) {
//省略部分代码...
Map<String, Object> map = new HashMap<>();
map.put("id", 123L);
map.put("name", "悟空GoKu");
stringRedisTemplate.set("KEY_GOKU", JsonUtil.toJsonString(map));
return ApiResponse.ok();
}
//get
@PostMapping(value = "/getData")
public ApiResponse getData(ApiRequest request) {
Map<String, Object> map = stringRedisTemplate.get("KEY_GOKU", Map.class);
Long id = (Long)map.get("id"); //会发生异常ClassCastException
return ApiResponse.ok();
}
json 反序列化 map 时如果原来的整数值小于 int 最大值,反序列化后原本为 Long 类型的字段,会变为 Integer 类型。
json 序列化的优势在于可读性更强。但没有携带类型信息,只有提供了准确的类型信息才能准确地进行反序列化,这点也特别容易引发线上问题。
5 总结
最后来几句总结阐述下本文的观点,仅代表个人看法
- 前端/移动端请求接口,面向json编程,用map来传输数据,部分接口的返回数据可定义成VO类
- 服务端之间的方法调用,多个参数的话需要定义DTO类来传输数据。
- 前后端联调,有一份清晰可见的接口文档极为重要,写好代码的同时不要忘记也要写好文档。
特别想diss那些字段不写注释、代码加了字段又不同步到文档的后端开发者hhh
作者:悟空GoKu
链接:https://juejin.im/post/5eb7fc9d5188256d51477c44
猜你喜欢
- 2024-11-24 赶快收藏!图灵前端图书学习路线图
- 2024-11-24 什么是BitMap?BitMap技术的原理和应用
- 2024-11-24 何时使用 Map 来代替普通的 JS 对象
- 2024-11-24 go语言深入Gin框架内幕(二)
- 2024-11-24 WeakMap和Map的区别,WeakMap原理,为什么能被 GC?
- 2024-11-24 2.7k star!MindMap 助你轻松绘制思维导图,高效工作必备!
- 2024-11-24 Python小知识,如何使用 Map, Filter 和 Reduce 内置函数
- 2024-11-24 解密 JavaScript 中的数据结构:Map vs Object
- 2024-11-24 Vue短文:如何使 Map 和 Set 类型的数据具有响应性?
- 2024-11-24 前端最常用的25个正则表达式,代码效率提高 80%
你 发表评论:
欢迎- 07-10Oracle 与 Google Cloud 携手大幅扩展多云服务
- 07-10分享收藏的 oracle 11.2.0.4各平台的下载地址
- 07-10Oracle 和 Microsoft 推出 Oracle Exadata 数据库服务
- 07-10Oracle Database@Azure 推进到南美等新区域并增加了新服务
- 07-10Oracle宣布推出 Oracle Database@AWS 的有限预览版
- 07-10Oracle与Nextcloud合作,推出主权云上的安全协作平台
- 07-10NodeRED魔改版连接MsSql、PostgreSQL、MySQL、OracleDB存储无忧
- 07-10对于企业数据云备份,“多备份”承诺的是成本更低,管理更高效#36氪开放日深圳站#
- 601℃几个Oracle空值处理函数 oracle处理null值的函数
- 593℃Oracle分析函数之Lag和Lead()使用
- 581℃0497-如何将Kerberos的CDH6.1从Oracle JDK 1.8迁移至OpenJDK 1.8
- 578℃Oracle数据库的单、多行函数 oracle执行多个sql语句
- 573℃Oracle 12c PDB迁移(一) oracle迁移到oceanbase
- 566℃【数据统计分析】详解Oracle分组函数之CUBE
- 552℃最佳实践 | 提效 47 倍,制造业生产 Oracle 迁移替换
- 547℃Oracle有哪些常见的函数? oracle中常用的函数
- 最近发表
-
- Oracle 与 Google Cloud 携手大幅扩展多云服务
- 分享收藏的 oracle 11.2.0.4各平台的下载地址
- Oracle 和 Microsoft 推出 Oracle Exadata 数据库服务
- Oracle Database@Azure 推进到南美等新区域并增加了新服务
- Oracle宣布推出 Oracle Database@AWS 的有限预览版
- Oracle与Nextcloud合作,推出主权云上的安全协作平台
- NodeRED魔改版连接MsSql、PostgreSQL、MySQL、OracleDB存储无忧
- 对于企业数据云备份,“多备份”承诺的是成本更低,管理更高效#36氪开放日深圳站#
- 解读丨《归档文件整理规则》— 电子文件元数据存储
- Data Guard跳归档恢复的实践(dataguard failover)
- 标签列表
-
- 前端设计模式 (75)
- 前端性能优化 (51)
- 前端模板 (66)
- 前端跨域 (52)
- 前端缓存 (63)
- 前端aes加密 (58)
- 前端脚手架 (56)
- 前端md5加密 (54)
- 前端路由 (61)
- 前端数组 (73)
- 前端js面试题 (50)
- 前端定时器 (59)
- 前端获取当前时间 (50)
- Oracle RAC (76)
- oracle恢复 (77)
- oracle 删除表 (52)
- oracle 用户名 (80)
- oracle 工具 (55)
- oracle 内存 (55)
- oracle 导出表 (62)
- oracle约束 (54)
- oracle 中文 (51)
- oracle链接 (54)
- oracle的函数 (57)
- 前端调试 (52)
本文暂时没有评论,来添加一个吧(●'◡'●)