清明放假没事在家写一些常用的轮子,以便减少一些重复繁琐的编码工作。
话不多说,继续往下看
有时我们的接口数据返回给前端或者导出为excel时,需要给相关值带单位(kg/立方米/%等)、或保留小数位等。尤其是一些统计类的报表,值特别多、单位也就贼多了。
做法
- 查询时在sql中拼接。给sql添加了好多无聊的字符,看起来都不好看,维护性不好,看起来都头疼
- 业务代码中循环拼接。这也很麻烦
- 交给前端回显时去拼接。前端有可能要骂娘
想法
- 既然是面向对象编程,那最好就是有维护一个视图对象,供我们返回到前端
- 一般我们通过sql查出来的po、dto模型或者通过业务处理后的bo模型不会直接给到前端,而是处理到vo再给到前端。
- 所以我就在想,我可以定义一些注解指明这个属性的单位是啥、保留小数位、或者替换符,然后通过一个对象转换的方法,获取到该属性注解的值,再通过反射赋予到vo模型中去。
- 想起来很简单,说干就干。不到两小时就撸出来了这个轮子,代码都很简单,主要是要有一些可以简化撸码的想法。也方便我们工作。
代码
可置于需要注解的对象的属性
/** * 响应体vo属性 * * @author MinWeikai * @date 2021/3/25 9:34 */@Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface RespVoProperty { /** * 保留小数位数 * 默认-1不进行保留 * * @return */int keepDecimal() default -1; /** * 单位 * * @return */String unit() default ""; /** * 替换值 * * @return */String replaceStr() default ""; }
vo模型使用示例
@Data public class PersonVo { private String name; @RespVoProperty(unit = "块") private String money; @RespVoProperty(unit = "岁", replaceStr = "-") private String age; @RespVoProperty(unit = "kg", keepDecimal = 2) private String weight; }
转换方法
/** * 数值集合对象转换为字符集合对象, * 可自定义数值保留位数,无值时的替换符、单位等 * * @author MinWeikai * @date 2021/4/3 11:20 */public class Converts { /** * 匹配并格式化属性 * * @param source * @param keepDecimal * @param unit * @param replaceStr * @param data * @param field * @param <T> */private static <T> void formatVoField(Object source, int keepDecimal, String unit, String replaceStr, T data, Field field) { if (Objects.equals("serialVersionUID", field.getName())) { return; } Object oldTemp = null; try { oldTemp = ReflectionUtil.invokeGetterMethod(source, field.getName()); } catch (Exception e) { e.printStackTrace(); } // 此处可自定义规则 switch (field.getType().getSimpleName()) { case "Float": if (ObjectUtil.isNotNull(oldTemp)) { if (keepDecimal == -1) { oldTemp = new BigDecimal((float) oldTemp); } else { oldTemp = new BigDecimal((float) oldTemp) .setScale(keepDecimal, BigDecimal.ROUND_HALF_UP); } oldTemp = String.valueOf(oldTemp).concat(unit); } else { oldTemp = replaceStr; } break; case "Integer": if (ObjectUtil.isNotNull(oldTemp)) { oldTemp = String.valueOf(oldTemp).concat(unit); } else { oldTemp = replaceStr; } break; case "BigDecimal": if (ObjectUtil.isNotNull(oldTemp)) { if (keepDecimal == -1) { oldTemp = new BigDecimal(oldTemp.toString()); } else { oldTemp = new BigDecimal(oldTemp.toString()) .setScale(keepDecimal, BigDecimal.ROUND_HALF_UP); } oldTemp = String.valueOf(oldTemp).concat(unit); } else { oldTemp = replaceStr; } break; default: } if (ObjectUtil.isNotNull(oldTemp)) { ReflectionUtil.invokeSetterMethod(data, field.getName(), oldTemp); } } /** * 转化为响应模型 * * @param source 源对象 * @param voClass vo类 * @param <T> * @return */public static <T> T toRespVo(Object source, final Class<T> voClass) { T data = null; try { data = voClass.newInstance(); } catch (InstantiationException | IllegalAccessException e) { e.printStackTrace(); } // 返回模型属性map Map<String, Field> voFieldsMap = Arrays.stream(voClass.getDeclaredFields()) .collect(Collectors.toMap(Field::getName, Function.identity())); // 对老属性赋予参数并置返回模型 for (Field field : source.getClass().getDeclaredFields()) { RespVoProperty property = Optional.ofNullable(voFieldsMap.get(field.getName())) .map(annotationClass -> annotationClass.getAnnotation(RespVoProperty.class)) .orElse(null); if (Objects.isNull(property)) { formatVoField(source, -1, "", "", data, field); } else { formatVoField(source, property.keepDecimal(), property.unit(), property.replaceStr(), data, field); } } return data; } /** * 集合转化为响应模型集合 * * @param sources 源对象集合 * @param voClass vo类 * @param <T> * @return */public static <T> List<T> toRespVos(List<? extends Object> sources, final Class<T> voClass) { List<T> targets = new ArrayList<>(); if (CollectionUtils.isEmpty(sources)) { return targets; } sources.parallelStream().forEach(source -> targets.add(toRespVo(source, voClass))); return targets; } // 测试方法 public static void main(String[] args) { List<Person> list = new ArrayList<>(); Person data1 = new Person(); data1.setName("李三"); data1.setAge(14); data1.setMoney(BigDecimal.ONE); data1.setWeight(15.2f); System.out.println("-----------------单对象转化vo----------------"); System.out.println(toRespVo(data1, PersonVo.class)); System.out.println("--------------------------------------------"); System.out.println("-----------------集合对象转化vo----------------"); list.add(data1); Person data2 = new Person(); data2.setName("wangwu"); data2.setAge(45); data2.setMoney(BigDecimal.valueOf(6.41f)); data2.setWeight(null); list.add(data2); Person data3 = new Person(); data3.setName("张思"); data3.setAge(null); data3.setMoney(BigDecimal.valueOf(25f)); data3.setWeight(17.689f); list.add(data3); System.out.println(toRespVos(list, PersonVo.class)); } }
方法中用到了一个反射方法工具
Be First to Comment