使用 Java 8 函数式编程减少重复代码:Function 应用

您所在的位置:网站首页 java函数代码 使用 Java 8 函数式编程减少重复代码:Function 应用

使用 Java 8 函数式编程减少重复代码:Function 应用

2024-07-14 21:01:57| 来源: 网络整理| 查看: 265

问题背景

我们的项目中常常会对数据做一些校验,例如添加一个用户,我们需要校验这些内容:

用户名称是否已被使用 邮箱是否已被使用 工号是否已被使用 手机号是否已被使用

等等这些校验

添加用户方法 @Override @Transactional(rollbackFor = Exception.class) public void add(UserAddDTO dto) { // 校验名称是否重复 throwExceptionWhenNameExists(dto); // 校验邮箱是否重复 throwExceptionWhenEmailExists(dto); // 校验手机号是否重复 throwExceptionWhenPhoneExists(dto); // 校验工号是否重复 throwExceptionWhenWorkNoExists(dto); SysUser user = init(dto); // 保存用户 save(user); // 保存用户角色 saveRoles(dto, user); // 保存用部门 saveDept(dto, user); } 校验名称是否重复 private void throwExceptionWhenNameExists(UserAddDTO dto) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper(); wrapper.eq(SysUser::getUsername, dto.getUsername()); long count = count(wrapper); if(count > 0) throw new RuntimeException("用户名称已被使用"); } 校验邮箱是否重复 private void throwExceptionWhenEmailExists(UserAddDTO dto) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper(); wrapper.eq(SysUser::getEmail, dto.getEmail()); long count = count(wrapper); if(count > 0) throw new RuntimeException("邮箱已被使用"); } 问题分析

上面的这种做法,对于每个字段,我们都要写一个方法。感觉非常的麻烦,而且一个项目有很多这样的地方。

如果每个地方都是这种写法,就会浪费比较多的时间。

我们可以发现,像是这种校验都有一个共同的特征,就是通过某个字段统计在表中的数量,我们是不是可以像 MyBatis-Plus 一样,将获取该字段的方法传递过去就行了? 对于要验证的字段,我们可以通过 SysUser::getUserName、SysUser::getPhone 这种方式传递过去,然后再将对应的值传过去。最终期望的结果是这样的:

// 校验名称是否重复 assertFieldNoRepeat(dto.getUserName(), SysUser::getUserName, "用户名称已被使用"); // 校验邮箱是否重复 assertFieldNoRepeat(dto.getUserName(), SysUser::getUserName, "邮箱已被使用"); //......

以终为始,以结果为导向反过来推导:

首先,我们将需要校验的值传进去

其次,再将这个值对应的字段传进去

然后,将异常消息给传进去

这样子,同一个类,无论那个字段,都可以用这种方式校验是否重复了

最终得出的方法是这样的

优化后的方法 /** * 重复字段校验 * @param getColumn 被验证的字段 * @param val 被校验的值 * @param msg 异常消息 */ private void assertFieldNoRepeat(SFunction getColumn, Object val, String msg) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper(); wrapper.eq(getColumn, val); long count = count(wrapper); if(count > 0) throw new RuntimeException(msg); }

这样子,我们就不用为每一个字段都编写一个校验方法了。

再优化一下

除了 SysUser 之外,是不是其他的表也存在很多这样的场景。

我们是不是可以将这个方法再提取一下,变成一个工具类。

对于不同的类,我们可以通过泛型的方式传进来,对于 count 方法,我们是不是可以同样使用 Function 的方式传进来。我们最终期望的效果是这样的:

// SysUser 校验名称是否重复 FieldValidUtil.assertFieldNoRepeat(dto.getUsername(), SysUser::getUsername, this::count, "用户名称已被使用"); // SysUser 校验邮箱是否重复 FieldValidUtil.assertFieldNoRepeat(dto.getEmail(), SysUser::getEmail, this::count, "邮箱已被使用"); // 或者别的类 // Material 物料校验编码是否重复 FieldValidUtil.assertFieldNoRepeat(materialDto.getCode(), Material::getCode, materialService::count, "物料编码已被使用");

以终为始,通过反方向推导:

首先,我们需要将被校验的值传入,

其次,再将这个值对应的类、字段传进去,

然后,再通过这个类的 Service 的 count 方法统计数量

最终推导出的工具类的实现是这样子的:

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.support.SFunction; /** * 字段校验工具 */ public class FieldValidUtil { /** * 重复字段校验 * @param val 被校验的值 * @param getColumn 被校验的列 * @param method 指定的方法 * @param msg 异常消息 */ public static void assertFieldNoRepeat(Object val, SFunction getColumn, SFunction method, String msg) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper(); wrapper.eq(getColumn, val); Long count = method.apply(wrapper); if(count > 0) throw new RuntimeException(msg); } } 总结

我们要善于发现工作中的这些痛点,然后分析这些问题的共同点,进行抽象归纳,找到共性,然后想办法将这些同类型的问题用同一种方式解决,避免将时间浪费在重复的事情上。



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭