前言平时做一些统计数据,经常从数据库或者是从接口获取出来的数据,单位是跟业务需求不一致的。
比如, 我们拿出来的 分, 实际上要是元
又比如,我们拿到的数据需要 乘以100 返回给前端做 百分比展示
又比如, 千分比转换
又比如,拿出来的金额需要变成 万为单位
又比如,需要保留2位小数
......
等等等等。
平时我们怎么搞?
很多时候拿到的是一个数据集合list,就需要去遍历然后根据每个dto的属性去做相关单位转换。
一直get 完 set ,get 完 set ,get 完 set ,get 完 set ,get 完 set ,人都麻了。
就像这样:
所以,如果通过反射自动匹配出来一些操作转换,是不是就看代码看起来舒服一点,人也轻松一点。
答案: 是的
然后,我就搞了。
本篇内容简要:① 初步的封装,通过map去标记需要转换的 类属性字段
② 进一步的封装, 配合老朋友自定义注解搞事情
产品:
支付总金额 换成万 为单位, 方便运营统计 ;
那个什么计数,要是百分比的 ;
然后还有一个是千分比;
另外,还有2个要保留2位小数;
还有啊,那个。。。。。。
我:
别说了,喝口水吧。
拿到的数据都在这个dto里面 :
开始封装:① 初步的封装,通过map去标记需要转换的 类属性字段思路玩法:
a.通过反射拿出字段
b.配合传入的转换标记map 匹配哪些字段需要操作
c.然后从map取出相关字段的具体操作是什么,然后执行转换操作
d.重新赋值
① 简单弄个枚举,列出现在需求上的转换操作类型
unitconverttype.java
/** * @author : jcccc * @createtime : 2023/01/14 * @description : **/public enum unitconverttype { /** * 精度 */ r, /** * 万元 */ b, /** * 百分 */ percentage, /** * 千分 */ permil}
② 核心封装的转换函数
unitconvertutil.java
import lombok.extern.slf4j.slf4j;import java.lang.reflect.field;import java.math.bigdecimal;import java.util.arraylist;import java.util.hashmap;import java.util.list;import java.util.map; /** * @author : jcccc * @createtime : 2023/01/14 * @description : **/@slf4jpublic class unitconvertutil { public static <t> void unitmapconvert(list<t> list, map<string, unitconverttype> propertymap) { for (t t : list) { field[] declaredfields = t.getclass().getdeclaredfields(); for (field declaredfield : declaredfields) { if (propertymap.keyset().stream().anymatch(x -> x.equals(declaredfield.getname()))) { try { declaredfield.setaccessible(true); object o = declaredfield.get(t); unitconverttype unitconverttype = propertymap.get(declaredfield.getname()); if (o != null) { if (unitconverttype.equals(unitconverttype.percentage)) { bigdecimal bigdecimal = ((bigdecimal) o).multiply(new bigdecimal(100)).setscale(2, bigdecimal.round_half_up); declaredfield.set(t, bigdecimal); } if (unitconverttype.equals(unitconverttype.permil)) { bigdecimal bigdecimal = ((bigdecimal) o).multiply(new bigdecimal(1000)).setscale(2, bigdecimal.round_half_up); declaredfield.set(t, bigdecimal); } if (unitconverttype.equals(unitconverttype.b)) { bigdecimal bigdecimal = ((bigdecimal) o).divide(new bigdecimal(10000)).setscale(2, bigdecimal.round_half_up); declaredfield.set(t, bigdecimal); } if (unitconverttype.equals(unitconverttype.r)) { bigdecimal bigdecimal = ((bigdecimal) o).setscale(2, bigdecimal.round_half_up); declaredfield.set(t, bigdecimal); } } } catch (exception ex) { log.error("处理失败"); continue; } } } } } public static void main(string[] args) { //获取模拟数据 list<mysumreportdto> list = getmysumreportlist(); map<string, unitconverttype> map =new hashmap<>(); map.put("paytotalamount", unitconverttype.b); map.put("jcamountpercentage", unitconverttype.percentage); map.put("jccountpermillage", unitconverttype.permil); map.put("length", unitconverttype.r); map.put("width", unitconverttype.r); unitmapconvert(list,map); system.out.println("通过map标识的自动转换玩法:"+list.tostring()); } private static list<mysumreportdto> getmysumreportlist() { mysumreportdto mysumreportdto = new mysumreportdto(); mysumreportdto.setpaytotalamount(new bigdecimal(1100000)); mysumreportdto.setjcamountpercentage(bigdecimal.valueof(0.695)); mysumreportdto.setjccountpermillage(bigdecimal.valueof(0.7894)); mysumreportdto.setlength(bigdecimal.valueof(1300.65112)); mysumreportdto.setwidth(bigdecimal.valueof(6522.12344)); mysumreportdto mysumreportdto1 = new mysumreportdto(); mysumreportdto1.setpaytotalamount(new bigdecimal(2390000)); mysumreportdto1.setjcamountpercentage(bigdecimal.valueof(0.885)); mysumreportdto1.setjccountpermillage(bigdecimal.valueof(0.2394)); mysumreportdto1.setlength(bigdecimal.valueof(1700.64003)); mysumreportdto1.setwidth(bigdecimal.valueof(7522.12344)); list<mysumreportdto> list = new arraylist<>(); list.add(mysumreportdto); list.add(mysumreportdto1); return list; }}
代码简析:
看看怎么调用的:
public static void main(string[] args) { //获取模拟数据 list<mysumreportdto> list = getmysumreportlist(); system.out.println("转换前:"+list.tostring()); map<string, unitconverttype> map =new hashmap<>(); map.put("paytotalamount", unitconverttype.b); map.put("jcamountpercentage", unitconverttype.percentage); map.put("jccountpermillage", unitconverttype.permil); map.put("length", unitconverttype.r); map.put("width", unitconverttype.r); unitmapconvert(list,map); system.out.println("通过map标识的自动转换玩法:"+list.tostring());}
代码简析:
效果:
整个集合list的 对应字段都自动转换成功(转换逻辑想怎么样就自己在对应if里面调整、拓展):
② 进一步的封装, 配合老朋友自定义注解搞事情实说实话,第一步的封装程度已经够用了,就是传map标识出来哪些需要转换,对应转换枚举类型是什么。
其实我感觉是够用的。
但是么,为了用起来更加方便,或者说 更加地可拓展, 那么配合自定义注解是更nice的。
开搞。
创建一个自定义注解 ,jcbigdecconvert.java
import java.lang.annotation.elementtype;import java.lang.annotation.retention;import java.lang.annotation.retentionpolicy;import java.lang.annotation.target; /** * @author : jcccc * @createtime : 2023/01/14 * @description : **/@target(elementtype.field)@retention(retentionpolicy.runtime)public @interface jcbigdecconvert { unitconverttype name();}
怎么用? 就是在我们的报表dto里面,去标记字段。
示例:
myyearsumreportdto.java
ps: 可以看到我们在字段上面使用了自定义注解
import lombok.data;import java.io.serializable;import java.math.bigdecimal; /** * @author : jcccc * @createtime : 2023/2/03 * @description : **/ @datapublic class myyearsumreportdto implements serializable { private static final long serialversionuid = 5285987517581372888l; //支付总金额 @jcbigdecconvert(name=unitconverttype.b) private bigdecimal paytotalamount; //jc金额百分比 @jcbigdecconvert(name=unitconverttype.percentage) private bigdecimal jcamountpercentage; //jc计数千分比 @jcbigdecconvert(name=unitconverttype.permil) private bigdecimal jccountpermillage; //保留2位 @jcbigdecconvert(name=unitconverttype.r) private bigdecimal length; //保留2位 @jcbigdecconvert(name=unitconverttype.r) private bigdecimal width;}
然后针对配合我们的自定义,封一个转换函数,反射获取属性字段,然后解析注解,然后做对应转换操作。
代码:
public static <t> void unitannotateconvert(list<t> list) { for (t t : list) { field[] declaredfields = t.getclass().getdeclaredfields(); for (field declaredfield : declaredfields) { try { if (declaredfield.getname().equals("serialversionuid")){ continue; } jcbigdecconvert myfieldann = declaredfield.getannotation(jcbigdecconvert.class); if(objects.isnull(myfieldann)){ continue; } unitconverttype unitconverttype = myfieldann.name(); declaredfield.setaccessible(true); object o = declaredfield.get(t); if (objects.nonnull(o)) { if (unitconverttype.equals(unitconverttype.percentage)) { bigdecimal bigdecimal = ((bigdecimal) o).multiply(new bigdecimal(100)).setscale(2, bigdecimal.round_half_up); declaredfield.set(t, bigdecimal); } if (unitconverttype.equals(unitconverttype.permil)) { bigdecimal bigdecimal = ((bigdecimal) o).multiply(new bigdecimal(1000)).setscale(2, bigdecimal.round_half_up); declaredfield.set(t, bigdecimal); } if (unitconverttype.equals(unitconverttype.b)) { bigdecimal bigdecimal = ((bigdecimal) o).divide(new bigdecimal(10000)).setscale(2, bigdecimal.round_half_up); declaredfield.set(t, bigdecimal); } if (unitconverttype.equals(unitconverttype.r)) { bigdecimal bigdecimal = ((bigdecimal) o).setscale(2, bigdecimal.round_half_up); declaredfield.set(t, bigdecimal); } } } catch (exception ex) { log.error("处理失败"); } } } }
写个调用示例看看效果:
public static void main(string[] args) { list<myyearsumreportdto> yearslist = getmyyearsumreportlist(); unitannotateconvert(yearslist); system.out.println("通过注解标识的自动转换玩法:"+yearslist.tostring()); } private static list<myyearsumreportdto> getmyyearsumreportlist() { myyearsumreportdto mysumreportdto = new myyearsumreportdto(); mysumreportdto.setpaytotalamount(new bigdecimal(1100000)); mysumreportdto.setjcamountpercentage(bigdecimal.valueof(0.695)); mysumreportdto.setjccountpermillage(bigdecimal.valueof(0.7894)); mysumreportdto.setlength(bigdecimal.valueof(1300.65112)); mysumreportdto.setwidth(bigdecimal.valueof(6522.12344)); myyearsumreportdto mysumreportdto1 = new myyearsumreportdto(); mysumreportdto1.setpaytotalamount(new bigdecimal(2390000)); mysumreportdto1.setjcamountpercentage(bigdecimal.valueof(0.885)); mysumreportdto1.setjccountpermillage(bigdecimal.valueof(0.2394)); mysumreportdto1.setlength(bigdecimal.valueof(1700.64003)); mysumreportdto1.setwidth(bigdecimal.valueof(7522.12344)); list<myyearsumreportdto> list = new arraylist<>(); list.add(mysumreportdto); list.add(mysumreportdto1); return list; }
效果也是很ok:
以上就是怎么使用springboot封装一个自适配的数据单位转换工具类的详细内容。