java中有时候需要对返回前端的数据做统一的数据格式化,如小数类型的字段需要格式化成保留两位小数的四舍五入格式; 这里使用两个注解: 一个标注类,一个标注字段,在返回前使用工具类方法调用一次,完成此目标.
1. 类上标注的注解@RoundMark
package com.niewj.common.annotation;
import java.lang.annotation.*;
/**
* 数学字段需要格式化的类标记注解
*
* @author niewj
* @date 2023/3/8 16:03
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RoundMark {
}
2. 字段上标注的注解@Round
package com.niewj.common.annotation;
import java.lang.annotation.*;
/**
* 实体字段格式化:float/double/decimal字段四舍五入保留2位小数(默认)
*
* @author niewj
* @date 2023/3/8 16:03
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Round {
int value() default 2;
}
3. 注解的使用
package com.niewj.business.model;
import com.niewj.common.annotation.Round;
import com.niewj.common.annotation.RoundMark;
import lombok.Data;
import java.math.BigDecimal;
/**
* 明细数据
*
* @author niewj
* @date 2023-02-12
*/
@Data
@RoundMark
public class DataReturnToFront {
/**
* 商品skuid
*/
private Long skuId;
/**
* 总商品量
*/
private Long count;
/**
* 商品平均曝光量
*/
@Round
private Double avgExp;
/**
* 商品平均曝光量-环比昨日
*/
@Round
private Double avgExpDodRatio;
/**
* 商品平均曝光量-(新增)
*/
@Round
private Double avgExpIncrement;
/**
* 商品[平均曝光量]-环比昨日-新增
*/
@Round
private Double avgExpIncrementDodRatio;
/**
* 商品[平均成交额]
*/
@Round
private Double avgSaleAmt;
/**
* 商品[平均成交额]-环比(昨日)
*/
@Round
private Double avgSaleAmtDodRatio;
/**
* 商品[平均成交额]-新增
*/
@Round
private Float avgSaleAmtIncrement;
/**
* 管控[平均成交额]-环比(昨日)-新增
*/
@Round
private BigDecimal avgSaleAmtIncrementDodRatio;
}
4.注解的处理过程,工具类:
package com.niewj.common.util;
import com.niewj.common.annotation.Round;
import com.niewj.common.annotation.RoundMark;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Arrays;
import java.util.List;
/**
* 注解工具类:用于对实体对象通过类和字段上标记注解来处理对象
*/
@Slf4j
public class AnnotationUtil {
/**
* 遍历格式化列表List内元素对象的数字字段
*
* @param targetList 待处理数据集合
* @param
*/
public static void roundListItemFields(List targetList) {
if (CollectionUtils.isEmpty(targetList)) {
log.info("targetList为空,不需要处理");
return;
}
targetList.stream().forEach(e -> {
roundDecimalValues(e);
});
}
/**
* 对小数数字格式的数据四舍五入:对类上标注了@RoundMark/字段上标注了@Round的数据进行四舍五入
*
* @param target 待处理实体对象
* @param
*/
public static void roundDecimalValues(T target) {
Class extends Object> targetClass = target.getClass();
boolean hasRoundingNumberAnno = targetClass.isAnnotationPresent(RoundMark.class);
if (hasRoundingNumberAnno) {
//为属性处理字段值
roundDecimalField(targetClass, target);
}
}
/**
* 对目标类中的每个字段来匹配field注解,如果匹配则进行四舍五入
*
* @param targetClass 标注了Round注解的类
* @param target 类的实例对象-即需要处理的字段所在对象
* @param
*/
private static void roundDecimalField(Class extends Object> targetClass, T target) {
Field[] fields = targetClass.getDeclaredFields();
Arrays.stream(fields).forEach(field -> {
boolean hasRoundingNumberAnno = field.isAnnotationPresent(Round.class);
if (hasRoundingNumberAnno) {
//获取注解的值
int scale = field.getAnnotation(Round.class).value();
Object originFieldVal;
Object roundedFieldVal;
try {
field.setAccessible(true);
originFieldVal = field.get(target);
if (originFieldVal instanceof Float) {
BigDecimal value = new BigDecimal(String.valueOf(originFieldVal)).setScale(scale, RoundingMode.HALF_UP);
roundedFieldVal = value.floatValue();
} else if (originFieldVal instanceof Double) {
BigDecimal value = new BigDecimal(String.valueOf(originFieldVal)).setScale(scale, RoundingMode.HALF_UP);
roundedFieldVal = value.doubleValue();
} else if (originFieldVal instanceof BigDecimal) {
roundedFieldVal = new BigDecimal(String.valueOf(originFieldVal)).setScale(scale, RoundingMode.HALF_UP);
} else {
roundedFieldVal = originFieldVal;
}
field.set(target, roundedFieldVal);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
});
}
}
5.使用方式:controller端
@GetMapping("/test")
@ResponseBody
@RecCostTime
public List test() {
log.info("======================");
DataReturnToFront detail = new DataReturnToFront();
detail.setSkuId(233230L);
detail.setCount(0L);
detail.setAvgExp(2220.1234566D);
detail.setAvgExpDodRatio(2220.1254566D);
detail.setAvgExpIncrement(-2220.1254566D);
detail.setAvgExpIncrementDodRatio(-2220.1264566D);
detail.setAvgSaleAmt(2220.1234566D);
detail.setAvgSaleAmtDodRatio(2220.1254566D);
detail.setAvgSaleAmtIncrement(2220.1254566F);
detail.setAvgSaleAmtIncrementDodRatio(BigDecimal.valueOf(0.1234566D));
DataReturnToFront detail2 = new DataReturnToFront();
detail2.setSkuId(5230L);
detail2.setCount(2330L);
detail2.setAvgExp(20.135634566D);
detail2.setAvgExpDodRatio(22.55554566D);
detail2.setAvgExpIncrement(-2220.5555D);
detail2.setAvgExpIncrementDodRatio(-2220.5555D);
detail2.setAvgSaleAmt(2220.5555D);
detail2.setAvgSaleAmtDodRatio(2220.5555D);
detail2.setAvgSaleAmtIncrement(2220.5555F);
detail2.setAvgSaleAmtIncrementDodRatio(BigDecimal.valueOf(0.5555D));
List list = new ArrayList();
list.add(detail);
list.add(detail2);
// 四舍五入格式化-批量处理
AnnotationUtil.roundListItemFields(list);
// 单个处理
AnnotationUtil.roundDecimalValues(detail);
return list;
}
- roundDecimalValues是对单个对象的标注了@Round字段(前提是类上有@RoundMark标记)进行四舍五入修改字段值.
- roundListItemFields是对list遍历了一下.
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net