乐趣区

关于aspectj:java2个自定义注解1个工具类对小数类型字段进行四舍五入处理

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 <T>
     */
    public static <T> void roundListItemFields(List<T> targetList) {if (CollectionUtils.isEmpty(targetList)) {log.info("targetList 为空, 不须要解决");
            return;
        }
        targetList.stream().forEach(e -> {roundDecimalValues(e);
        });
    }

    /**
     * 对小数数字格局的数据四舍五入: 对类上标注了 @RoundMark/ 字段上标注了 @Round 的数据进行四舍五入
     *
     * @param target 待处理实体对象
     * @param <T>
     */
    public static <T> 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 <T>
     */
    private static <T> 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<DataReturnToFront> 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 遍历了一下.
退出移动版