影落离风

The shadow falls away from the wind

0%

利用反射将bean对象格式化为特定字符串

前言

在常见业务开发中,我们经常会遇到客户需要这样的需求:将几个属性拼接起来显示在页面上。比如一些显示通知类的内容

代码中的对象属性如下:

1
2
3
4
5
6
7
8
9
10
Student student = new Student();
student.setName("张三");
student.setIdentity("匪徒");
student.setDate(new Date());

Schoolbag bag = new Schoolbag();
bag.setColor("黄色");
bag.setPencilCase(new PencilCase("中性笔", 2));

student.setBag(bag);

需求就是显示这样的文本:各单位请注意:匪徒张三于2021-07-18 11:35:09背着黄色的包,里面装了2支中性笔

想法

代码中写死并拼接,这个工作无论是后端还是前端做,都不灵活,增加或修改该文本都需要发包;

用过String.format方法的同学应该知道根据特定符号替换里面的值,所以我就在想,bean对象可不可以也这样,根据对象的属性名取值拼接。

比如我预先把对象的属性名放在字符串中,然后利用反射取到对象里的值,然后替换该属性名。这一串含有属性名的文本我可以放在项目的配置中心,这样无论是开发、前端、测试、客户都可以进行文本的修改,当然属性名你不能修改,不然反射取不到值。

做法

1. 首先可以写一个可以根据属性名利用反射获取对象值的工具类,如上Student对象,而且还要满足根据层级对象取值。当你看到这个博客的时候,恭喜你,不用写了,我在好多年前已经写了。也正因为之前写过这个工具类,我现在遇到这个需求也才会想到这个方案。[利用反射对层级对象取其某层对象的某个值,可忽略层对象不存在](https://minwk.top/my-optional-object-filed-value/)
2. 然后再写一个方法取出字符串中的属性名,为了方便取属性名,我们可以定义一个特殊符号来取,比如 {%name%},完整如下
1
2
String format = "各单位请注意:{%identity%}{%name%}于{%date%}背着{%bag.color%}的包," +
"里面装了{%bag.pencilCase.num%}支{%bag.pencilCase.name%}";
3. 方法名beanFormatStr(Student, format),将bean根据定义的字符串格式化为所需要的文本。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* 通过对format与source对象反射匹配拼接值
* 需要匹配的值可在format中写为
*
* @param source
* @param format String format = "{%name%}在{%date%}背着{%bag.color%}的书包," +
* "但是只装了{%bag.pencilCase.num%}支{%bag.pencilCase.name%},因为他是装笔!";
* @return
*/
public static String beanFormatStr(Object source, String format) {
String[] str = format.split("\\{%");
StringBuilder sb = new StringBuilder();
for (String s : str) {
int a = s.indexOf("%}");
if (a != -1) {
String key = s.substring(0, a);
sb.append(MyOptional.getVStrByField(source, key));
sb.append(s.substring(a + 2));
}else {
sb.append(s);
}
}
return sb.toString();
}

总结

当你看完这个代码,其实会觉得很简单,很好实现,只是要有这个想法很难。

要时刻怀着致力于写出思路更加清晰,逻辑性更强,冗余度更低,可维护性和可重用性更高的代码,这是我一直为之奋斗的目标。

简单一个字就是要“懒”

咦~~,这个方法我之前写过类似的我懒得再写,我可不可以再把它抽象封装一下让这里也能用;

我天!!,这个业务写起来这么多行,我都懒得看/写下去,这样就会想着把他精简或封装;

客户变得真tm快!这个功能还没上线他就变了,我真是懒得改了,这个功能客户可不可以通过后台去维护,让他自己去玩。一定要想办法把客户易变的东西,交给他自己去维护;

代码

利用反射对层级对象取其某层对象的某个值,可忽略层对象不存在

以下面这两个代码为准,上面这个博客里的代码我也懒得去更新了;上面这个也能用,只是我有新增的一些方法没有

MyOptional.java

MyFormat

就这些了,有问题再联系吧,都12:19了,该吃饭了:v: