使用注解校验的正则方法校验金额

  • Post author:
  • Post category:其他




校验金额的必要性

开发过程中,经常会遇到上游系统传String类型的金额过来的情况。我们需要将之转换为Bigdecimal类型再计算或者保存到数据库。

如下图所示,若上游系统发送特殊符号过来就会报错。涉及到金额那可就不是小事啦。

在这里插入图片描述



校验方法

所以我们需要校验,如下代码所示,上游系统一般会将金额放到Map里面传过来,我们首先将Map转换为我们定义的request对象,然后对对象的属性进行注解校验。

 public DecisionResponse fundOperationAccept(Map<String, Object> params) {
        FundBankCommandOrderRequest request =
                JSON.parseObject(JSON.toJSONString(params), FundBankCommandOrderRequest.class);
        LOGGER.info("fundOperationAccept,request:{}", request);
        DecisionResponse result = new DecisionResponse();
        // 参数校验
        fundOperationValidator.validateBankCommandOrder(request);
}

这里注入的Validator校验调用的包是javax.validation,下面代码是它的主要校验方法:

public class FundOperationValidator {

    private static final Logger LOGGER = LoggerFactory.getLogger(FundOperationValidator.class);
	@Autowired
    private Validator validator;
 /**
     * 校验资金操作入参
     * @param request
     */
    public void validateFundOperation(FundOperationalOrderRequest request) {
        LOGGER.info("validateFundOperation request{}", request);
        //校验公共数据
        Set<ConstraintViolation<FundOperationalOrderRequest>> validates = validator.validate(request);
        Map<String, String> messageMap = BeanValidators.extractPropertyAndMessage(validates);
        if (MapUtils.isNotEmpty(messageMap)) {
            LOGGER.error("操作ID为{},操作类型为{}的资金操作下发失败,失败原因为{}",
                    request.getOperationId(), request.getOperationType(), messageMap.toString());
            throw new AppException(CoreErrorCode.REQUEST_PARAM_VALIDATION_FALIURE, messageMap.toString());
        }
        LOGGER.info("validateFundOperation end");
    }
 }


public class BeanValidators {
    /**
     * 辅助方法, 转换Set<ConstraintViolation>为Map<property, message>.
     */
    public static Map<String, String> extractPropertyAndMessage(Set<? extends ConstraintViolation> constraintViolations) {
        Map<String, String> errorMessages = new HashMap<String, String>(CommonConstants.INITIAL_CAPACITY);
        for (ConstraintViolation violation : constraintViolations) {
            errorMessages.put(violation.getPropertyPath().toString(), violation.getMessage());
        }
        return errorMessages;
    }

我们在request对象的属性上加上@Pattern,该属性需要满足设置的正则表达式

 /**
     * 付款单金额,单位:元
     */
    @Pattern(regexp = "^[0-9]+(.[0-9]{1,2})?$", message = "金额格式不对")
    @NotBlank(message = "付款单金额不能为空")
    @Length(max = 16, message = "付款单金额超过最大长度")
    private String amount;



正则表达式思路

整数部分我们需要是0~9的数字,所以使用[0-9]

不能一个都没有,防止空字符串,所以使用[0-9]+

小数部分也是0~9的数字,且为1位或者2位,所以使用[0-9]+(.[0-9]{1,2})

小数部分也可能没有,所以使用[0-9]+(.[0-9]{1,2})?

^代表开始,&代表结束,最终得到:^[0-9]+(.[0-9]{1,2})?$

当然,有可能会出现上游传0开头的数字,比如03.22,这样的字符串,bigdecimal会自动去除前面的0,所以系统不会报错,此处我觉得没有必要校验这种情况。

如果还有其它不满足的情况,也请告诉我哈,PS:

某正则表达式测试网站:



版权声明:本文为zhuyacheneagle原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。