开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第9天,点击查看活动详情
0. 背景
话说有一天咱们虾搞一通餐饮有限公司的新任产品“梅骰恼”想出了一个绝妙的提升用户粘性的办法,就是搞一个干饭社区。于是他兴高采烈地来到了“老少通吃软件开发部”,大声喊:“我想到了一个idea,你们帮我 realize 一下,别总等我 push,要自驱,by yourself ,from the heart!”
他刚说完,程序员小贺就对他说:“什么业务啊?好好说话。”梅骰恼手舞足蹈地说:“是这样,我们新做一个干饭社区……”小贺打断了他:“照着什么抄?”梅骰恼一笑:“照着大厂的抄,下周要。一会儿我发一段语音来指导,我还有个会,我先走了。”众人开始喧闹,很久才安静。很快,大家开始了一周的拼搏,实现了一个简易的版本。
转眼就来到了下周一,梅骰恼兴高采烈地来到了开发组:“我有一个excel文档,帮我导入咱们干饭社区,这里面是我找来的用户。”小贺顶着黑眼圈问他:“还有excel吗?还是就这一回。”梅骰恼挠挠头:“以后我给你,你就导呗,你实现个界面,我一扔……”小贺无奈地说:“好吧,我实现一个文档导入的功能吧。”
1. 通过配置文件配置目录
小贺开始了自己的导入之旅,首先他想到要配置存放人员名单的excel的目录,如果失败了,也应该有一个失败的数据的目录,于是他在application.yml中写道:
excel-import:
community-user-dir: /app/excel/community-user/
community-user-error-data-dir: /app/excel/community-user/error/
很快,他想到要在启动的时候自动创建目录,使用的时候为了避免出错,应该使用绝对路径。于是对应的配置类很快就写好了:
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
import java.io.File;
/**
* 导入人员信息excel文件配置
*/
@Data
@Configuration
@ConfigurationProperties(prefix = "excel-import")
public class ImportUserInfoFileConfig {
private String communityUserDir;
private String communityUserAbsoluteDirPath;
private String communityUserErrorDataDir;
private String communityUserErrorDataAbsoluteDirPath;
@PostConstruct
private void init() {
// 先创建用户目录
File dir = new File(communityUserDir);
dir.mkdirs();
communityUserAbsoluteDirPath = dir.getAbsolutePath();
// 然后创建错误数据目录
dir = new File(communityUserErrorDataDir);
dir.mkdirs();
communityUserErrorDataAbsoluteDirPath = dir.getAbsolutePath();
}
}
2. 使用 BiConsumer 重构
正当小贺对自己的周到思考沾沾自喜时,小孙看到了他刚刚写的代码,喃喃自语道:“要是再多了,还得重复写吗?”小贺从喜悦中缓过神来,他问小孙:“这种代码还能重构吗?”小孙笑着说:“看我的,我给你秀一波操作!”于是小孙帮他改成:
@Data
@Configuration
@ConfigurationProperties(prefix = "excel-import")
public class ImportUserInfoFileConfig {
private String communityUserDir;
private String communityUserAbsoluteDirPath;
private String communityUserErrorDataDir;
private String communityUserErrorDataAbsoluteDirPath;
@PostConstruct
private void init() {
initOneDir(communityUserDir, ImportUserInfoFileConfig::setCommunityUserAbsoluteDirPath);
initOneDir(communityUserErrorDataDir, ImportUserInfoFileConfig::setCommunityUserErrorDataAbsoluteDirPath);
}
private void initOneDir(String dirFilePath, BiConsumer<ImportUserInfoFileConfig, String> setMethod) {
File dir = new File(dirFilePath);
dir.mkdirs();
setMethod.accept(this, dir.getAbsolutePath() + "/");
}
}
3. 神奇的 BiConsumer
小贺感到惊讶:“怎么还能传递函数,这样确实只用一行一行地在init函数里加了,妙啊。”小孙得意地说:“这个啊,叫BiConsumer,我刚学到的,可以解决这种set式的代码的重构的问题。我来给你详细说说。”
介绍 java.util.function.BiConsumer 首先要介绍 java.util.function.Consumer,它设计的初衷就是给操作的对象产生一些副作用,啥叫副作用,就是影响对象的值。所以最少要把对象传进去吧,我们假设有一个函数是给对象做初始化性别的,比如:
@Data
public class InitExample {
private int sex;
public void initSex(){
this.setSex(1);
}
public static void main(String[] args) {
Consumer<InitExample> initSex = InitExample::initSex;
InitExample initExample = new InitExample();
initSex.accept(initExample);
}
}
这样不就是说 java.util.function.Consumer 至少要传入对象嘛,那我除了对象还有参数怎么办呢?这就需要 java.util.function.BiConsumer 了,就像我们上面例子中的set方法。
小孙讲完后,小贺惊讶于小孙的好学,更加刻苦地学习Java8了……
总结
本例中,我们学习了如何封装set方法,使用Consumer家族来方便我们相似代码的封装。掘友们,你们平时又有哪些好的实践呢?欢迎你在评论区与我讨论。