代码优化实战,3行代码解决了一百个if else!
事情是这样的,前段时间做代码review的时候,发现项目中有一个方法代码量超鸡儿多,而且大部分都是写的参数校验的代码,得,我们先抓着缕一缕需求先。
产品需求
找到产品要到了需求文档,需求是这样得:
- excel数据模板下载
- excel数据导入
- 导入得时候根据模板得校验规则来进行筛选,导入成功得返回成功列表,数据有问题得返回失败列表,失败列表支持数据编辑修正
好吧。看到需求第一眼可能就是第三列有点难度,我们知道,传统得数据校验是在DTO上面加注解
如下:
//第一种
public Result test(@RequestBody @Validated TestDTO dto) {...}
//第二种
public Result test(@RequestBody @Valid TestDTO dto{...}
//第三种
public Result test(@RequestBody @Validated(value = {SaveGroup.class}) TestDTO dto) {...}
TestDTO里面呢会有一些类似 @NotNull、@NotBlank、@Size等校验注解,这里就不列了。
然后再在全局异常拦截那里进行统一封装,使其放回得数据结构尽量保持统一,所以一般还得有一个GlobalExceptionHandle


讲到常见得数据校验,那么我们画风一转,再回来看需求,可见以上需求是不满足得,首先,我们入参是一个文件,也就是用户传得那个excel,我们得先解析文件再进行数据判断,合法得放一个集合,不合法得放一个集合,再者,即使入参是一个数组,这种校验一旦不满足立马进异常处理了,无法返回给前端正确得数据结构,所以引入了我们今天解决这类需求得解决方案。
重构开始-开篇
我们以之前写文章里面得一个项目easyexcel-demo为模板进行代码得改造和编写
代码地址:https://github.com/pengziliu/GitHub-code-practice

下载之前做的小demo,运行起来,创建一个工作簿导入数据
创建一份Excel数据

PostMan模拟调用数据解析

项目代码和控制台输出

重构开始-实战
好吧,上面介绍了一下之前项目得基本读取excel功能,我们就基于以上功能来实现我们开篇所说得需求。
我们对手机号和姓名自定义一下规则:
- 手机号满足基本手机号规则
- 姓名非空且不能超过四个字符
返回成功失败两个集合,全部满足得返回到成功,只要有一条不满足得丢入失败列表。
定义返回得数据结构
新建返回对象UserExcelVO.java

好了,兄弟们,这里我要上同事写的伪代码了。坐好扶稳了!!!
@PostMapping("/importExcel")
public UserExcelVO importExcel(@RequestParam("file") MultipartFile file){
List<UserExcelModel> list = null;
List<UserExcelModel> fail = new ArrayList<>();
UserExcelVO userExcelVO = new UserExcelVO();
String mobieReg = "^[1][3,4,5,7,8][0-9]{9}$$";
try {
list = EasyExcel.read(file.getInputStream(),UserExcelModel.class,new ModelExcelListener()).sheet().doReadSync();
list.forEach(data->{
//处理姓名的校验
if(StringUtils.isEmpty(data.getName())||data.getName().length()> 4 ){
fail.add(data);
return;
}
//处理手机号的校验
if (StringUtils.isEmpty(data.getMobile())|| !data.getMobile().matches(mobieReg)) {
fail.add(data);
return;
}
//以下根据字段多少可能有n个if
});
userExcelVO.setFail(fail);
list.removeAll(fail);
userExcelVO.setSuccess(list);
} catch (IOException e) {
e.printStackTrace();
}
return userExcelVO;
}
测试数据:
用户名 年龄 手机号 性别
宝典哥1 11 23847235 男
宝典哥2 12 15813847236 男
宝典哥3 13 15813847237 男
宝典哥4 14 15813847238 男
宝典哥5 15 15813847239 男
宝典哥6 16 15813847240 男
宝典哥7 17 152247241 男
宝典哥8 18 15813847242 男
宝典哥9 19 15813847243 男
宝典哥10 20 15813847244 男
宝典哥11 21 15813847245 男
宝典哥12 22 15813847246 男
宝典哥13 23 15813847247 男
宝典哥14 24 15813847248 男
宝典哥15 25 15813847249 男
测试结果:
{
"success": [
{
"cellStyleMap": {},
"name": "宝典哥2",
"age": 12,
"mobile": "15813847236",
"sex": "男"
},
{
"cellStyleMap": {},
"name": "宝典哥3",
"age": 13,
"mobile": "15813847237",
"sex": "男"
},
{
"cellStyleMap": {},
"name": "宝典哥4",
"age": 14,
"mobile": "15813847238",
"sex": "男"
},
{
"cellStyleMap": {},
"name": "宝典哥5",
"age": 15,
"mobile": "15813847239",
"sex": "男"
},
{
"cellStyleMap": {},
"name": "宝典哥6",
"age": 16,
"mobile": "15813847240",
"sex": "男"
},
{
"cellStyleMap": {},
"name": "宝典哥8",
"age": 18,
"mobile": "15813847242",
"sex": "男"
},
{
"cellStyleMap": {},
"name": "宝典哥9",
"age": 19,
"mobile": "15813847243",
"sex": "男"
}
],
"fail": [
{
"cellStyleMap": {},
"name": "宝典哥1",
"age": 11,
"mobile": "23847235",
"sex": "男"
},
{
"cellStyleMap": {},
"name": "宝典哥7",
"age": 17,
"mobile": "152247241",
"sex": "男"
},
{
"cellStyleMap": {},
"name": "宝典哥10",
"age": 20,
"mobile": "15813847244",
"sex": "男"
},
{
"cellStyleMap": {},
"name": "宝典哥11",
"age": 21,
"mobile": "15813847245",
"sex": "男"
},
{
"cellStyleMap": {},
"name": "宝典哥12",
"age": 22,
"mobile": "15813847246",
"sex": "男"
},
{
"cellStyleMap": {},
"name": "宝典哥13",
"age": 23,
"mobile": "15813847247",
"sex": "男"
},
{
"cellStyleMap": {},
"name": "宝典哥14",
"age": 24,
"mobile": "15813847248",
"sex": "男"
},
{
"cellStyleMap": {},
"name": "宝典哥15",
"age": 25,
"mobile": "15813847249",
"sex": "男"
}
]
}
根据测试结果应该是问题不大的,我这里也是模拟一下,但是实际的业务场景,一个excel里面假如是订单数据,最少是几十个字段起步的,难道要写几十个if else ,明显是不合理的,那我们能不能使用注解的方式帮我们解决问题呢,如果使用注解的话应该如何使用呢?
开造!
创建ValidationUtils.java
public class ValidationUtils {
public static Validator getValidator(){
return validator;
}
static Validator validator;
static{
ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
validator=validatorFactory.getValidator();
}
}
对Model加注解

对Controller进行改写
@PostMapping("/v2/importExcel")
public UserExcelVO importExcelV2(@RequestParam("file") MultipartFile file){
List<UserExcelModel> list = null;
List<UserExcelModel> fail = new ArrayList<>();
UserExcelVO userExcelVO = new UserExcelVO();
try {
list = EasyExcel.read(file.getInputStream(),UserExcelModel.class,new ModelExcelListener()).sheet().doReadSync();
list.forEach(data->{
//此处3行代码解决了一百个if else
Set<ConstraintViolation<UserExcelModel>> violations = ValidationUtils.getValidator().validate(data);
if(violations.size()>0){
fail.add(data);
}
});
userExcelVO.setFail(fail);
list.removeAll(fail);
userExcelVO.setSuccess(list);
} catch (IOException e) {
e.printStackTrace();
}
return userExcelVO;
}
测试
对同一组数据进行测试

测试结果如下,可以发现,两种实现数据输出结果一致
{
"success": [
{
"cellStyleMap": {},
"name": "宝典哥2",
"age": 12,
"mobile": "15813847236",
"sex": "男"
},
{
"cellStyleMap": {},
"name": "宝典哥3",
"age": 13,
"mobile": "15813847237",
"sex": "男"
},
{
"cellStyleMap": {},
"name": "宝典哥4",
"age": 14,
"mobile": "15813847238",
"sex": "男"
},
{
"cellStyleMap": {},
"name": "宝典哥5",
"age": 15,
"mobile": "15813847239",
"sex": "男"
},
{
"cellStyleMap": {},
"name": "宝典哥6",
"age": 16,
"mobile": "15813847240",
"sex": "男"
},
{
"cellStyleMap": {},
"name": "宝典哥8",
"age": 18,
"mobile": "15813847242",
"sex": "男"
},
{
"cellStyleMap": {},
"name": "宝典哥9",
"age": 19,
"mobile": "15813847243",
"sex": "男"
}
],
"fail": [
{
"cellStyleMap": {},
"name": "宝典哥1",
"age": 11,
"mobile": "23847235",
"sex": "男"
},
{
"cellStyleMap": {},
"name": "宝典哥7",
"age": 17,
"mobile": "152247241",
"sex": "男"
},
{
"cellStyleMap": {},
"name": "宝典哥10",
"age": 20,
"mobile": "15813847244",
"sex": "男"
},
{
"cellStyleMap": {},
"name": "宝典哥11",
"age": 21,
"mobile": "15813847245",
"sex": "男"
},
{
"cellStyleMap": {},
"name": "宝典哥12",
"age": 22,
"mobile": "15813847246",
"sex": "男"
},
{
"cellStyleMap": {},
"name": "宝典哥13",
"age": 23,
"mobile": "15813847247",
"sex": "男"
},
{
"cellStyleMap": {},
"name": "宝典哥14",
"age": 24,
"mobile": "15813847248",
"sex": "男"
},
{
"cellStyleMap": {},
"name": "宝典哥15",
"age": 25,
"mobile": "15813847249",
"sex": "男"
}
]
}
代码仓库
https://github.com/pengziliu/GitHub-code-practice
最新代码已提交,欢迎star,里面包含很多的项目教程和实例
总结
写代码的时候,除了做功能,应该要考虑代码的扩展性,不然产品说加个功能,我们又得吭哧吭哧写代码,那这样也台悲催了。
代码优化实战,3行代码解决了一百个if else!的更多相关文章
- Jquery几行代码解决跟随屏幕滚动DIV
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- AlloyTouch实战--60行代码搞定QQ看点资料卡
原文链接:https://github.com/AlloyTeam/AlloyTouch/wiki/kandian 先验货 访问DEMO你也可以点击这里 源代码可以点击这里 如你体验所见,流程的滚动的 ...
- GJM : AlloyTouch实战--60行代码搞定QQ看点资料卡
原文链接:https://github.com/AlloyTeam/AlloyTouch/wiki/kandian 先验货 访问DEMO你也可以点击这里 源代码可以点击这里 如你体验所见,流程的滚动的 ...
- 7行代码解决P1441砝码称重(附优化过程)
先贴上最终代码感受一下: #include <bits/stdc++.h> using namespace std; int i, N, M, wi[21], res = 0; int m ...
- Asp.Net Core-几行代码解决Razor中的嵌套if语句
MVC开发中,经常会遇到在razor中插入简单的逻辑判断. @if (clientManager.IsAdmin) { if (!Model.Topic.Top) { <a asp-action ...
- 八行代码解决八皇后问题(c++)
说的有点夸装,实际上并不只是巴航代码,加上前面的变量声明之类的一共有40多行的样子吧,好像是在知乎上看到的,现在有时间再把它写下来: 其中用到了一些c++11特性,例如lambda 以及给予范围的 f ...
- Swift几行代码解决UITableView空数据视图问题
tableView空数据问题 一般项目中tableView若数据为空时会有一个提示示意图 为了更好的管理这种提示示意图,笔者利用extension进行了简单的拓展 解决思路 利用swift面向协议的特 ...
- 6行代码解决golang TCP粘包
转自:https://studygolang.com/articles/12483 什么是TCP粘包问题以及为什么会产生TCP粘包,本文不加讨论.本文使用golang的bufio.Scanner来实现 ...
- 17行代码解决微信小程序图片延迟加载
js 页面 Page({ data: { realScrollTop: 0,//页面滚动距离 driveHeight //屏幕高度可初始化设置 }, scroll(e){ if(e.detail.sc ...
随机推荐
- P4017 最大食物链计数(洛谷)
老师开始帮我们查漏补缺啦!我们的老师这两天给了我们一些我们没怎么学的函数和算法,比如STL的函数和拓扑排序之类的,这个题就是讲拓扑排序的. 先看题板: 题目背景 你知道食物链吗?Delia 生物考试的 ...
- 集训作业 洛谷P1032 字串变换
集训的题目有点多,先写困难的绿题吧(简单的应该想想就会了) 嗯,这个题看起来像个搜索呢(就是个搜索) 我们仔细想想就知道这个题肯定不能用深搜,可以优化的地方太少了,TLE是必然的. 那我们该怎么办呢? ...
- c# Winfrom-DataGridView实现筛选功能
//应对用户需求,需要在DataGridView中直接进行筛选功能,在网上找了一些代码加上自己修改整理过后的类,仅供参考! //上面代码可以直接创建类库项目生成DLL文件,下面代码为另外项目引用创 ...
- MySQL数据库---记录相关操作
序 表中记录的相关操作一共四种:插入,更新,删除.查询.其中使用最多,也是最难的就是查询. 记录的插入 1. 插入完整数据(顺序插入) 语法一: INSERT INTO 表名(字段1,字段2,字段3… ...
- 做软件测试要月入20k?听听腾讯大牛怎么说
作者:兰色链接:https://www.zhihu.com/question/373819487/answer/1183309514来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请 ...
- 分布式ID生成服务,真的有必要搞一个
目录 阐述背景 Leaf snowflake 模式介绍 Leaf segment 模式介绍 Leaf 改造支持RPC 阐述背景 不吹嘘,不夸张,项目中用到ID生成的场景确实挺多.比如业务要做幂等的时候 ...
- Python网络爬虫四大选择器用法原理总结
前几天小编连续写了四篇关于Python选择器的文章,分别用正则表达式.BeautifulSoup.Xpath.CSS选择器分别抓取京东网的商品信息.今天小编来给大家总结一下这四个选择器,让大家更加深刻 ...
- spring tx——@EnableTransactionManagement
@EnableTransactionManagement import了TransactionManagementConfigurationSelector,而TransactionManagemen ...
- Alink漫谈(十三) :在线学习算法FTRL 之 具体实现
Alink漫谈(十三) :在线学习算法FTRL 之 具体实现 目录 Alink漫谈(十三) :在线学习算法FTRL 之 具体实现 0x00 摘要 0x01 回顾 0x02 在线训练 2.1 预置模型 ...
- Spring bean初始化