I usually do some statistical data, and the data obtained from the database or interface are often inconsistent with the business requirements.
For example, the cents we took out are actually yuan
Another example, the data we get needs to be multiplied by 100 Return to the front-end for percentage display
Another example is thousandth conversion
Another example is that the amount taken out needs to be converted into ten thousand units
Another example, you need to retain 2 decimal places
......
and so on.
What do we usually do?
Many times what you get is a data collection list, and you need to traverse it and perform relevant unit conversions based on the attributes of each DTO.
Everyone gets numb after getting and setting, getting and setting, getting and setting, getting and setting, and getting and setting.
Like this:
So, if some operation conversions are automatically matched through reflection, the code will look more comfortable and people will be more relaxed. a little.
Answer: Yes
Then, I did it.
① Preliminary encapsulation, using map to mark the class attribute fields that need to be converted
② Further Encapsulate, cooperate with old friends’ custom annotations to do things
Product:
The total payment amount is converted into ten thousand units to facilitate operational statistics;
What kind of count is it? If it is a percentage;
Then there is another one which is a percentage per thousand;
In addition, there are 2 more that need to retain 2 decimal places;
And ah, that. . . . . .
Me:
Stop talking and drink some water.
The data obtained is all in this DTO:
How to play:
a. Take out the fields through reflection
b. Use the incoming conversion mark Map to match which fields need to be operated
c. Then what is the specific operation to extract the relevant fields from the map, and then perform the conversion operation
d. Reassign the value
① Simply make an enumeration and list the current Conversion operation type on demand
UnitConvertType.java
/** * @Author : JCccc * @CreateTime : 2023/01/14 * @Description : **/ public enum UnitConvertType { /** * 精度 */ R, /** * 万元 */ B, /** * 百分 */ PERCENTAGE, /** * 千分 */ PERMIL }
② Core encapsulated conversion function
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 : **/ @Slf4j public 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; } }
Code analysis:
Look at how to call it:
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()); }
Code analysis:
Effect:
The corresponding fields of the entire collection list are automatically converted successfully (you can adjust and expand the conversion logic in the corresponding if if you want):
To be honest, the first step of encapsulation is enough, which is to pass the map to identify which ones need to be converted, and the corresponding conversion enumeration What is the type.
Actually, I feel it is enough.
But, in order to make it more convenient to use, or more scalable, it would be nicer to use custom annotations.
Let’s do it.
Create a custom annotation, 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(); }
How to use it? Just mark the fields in our report DTO.
Example:
MyYearSumReportDTO.java
ps: You can see that we use custom annotations on the fields
import lombok.Data; import java.io.Serializable; import java.math.BigDecimal; /** * @Author : JCccc * @CreateTime : 2023/2/03 * @Description : **/ @Data public 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; }
and then match our custom Definition, seal a conversion function, obtain the attribute field by reflection, then parse the annotation, and then perform the corresponding conversion operation.
Code:
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("处理失败"); } } } }
Write a calling example to see the effect:
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; }
The effect is also very good:
The above is the detailed content of How to use Springboot to encapsulate an adaptive data unit conversion tool class. For more information, please follow other related articles on the PHP Chinese website!