赞
踩
数据校验是我们日常开发过程中常做的工作,其目的性是为了提升我们系统的健壮性,举个简单的例子,我们要做一个创建用户的api接口服务,用户昵称是必填项,那么接口就需要对用户昵称进行非空校验。如果没填昵称抛出异常或者返回一些错误码。
那么问题来了,一次调用可能有n多个参数需要校验,比如用户手机绑定的注册服务,入参如下所示:
public class MobileRegisterDTO extends BaseDTO { /** * 手机号 */ private String mobile; /** * 国家码 */ private String countryCode; /** * 验证码 */ private String verificationCode; /** * 密码 */ private String password; /** * 昵称 */ private String nickname; /** * 是否是三方注册 */ private Boolean isThirdAccountRegistration; }
对于这个场景,很多人参数校验的代码可能就写成了下面这个样子:
public void mobileRegister(MobileRegisterDTO mobileRegisterDTO) {
if (Objects.isNull(mobileRegisterDTO) || StringUtils.isNotEmpty(mobileRegisterDTO.getMobile())
|| StringUtils.isNotEmpty(mobileRegisterDTO.getNickname())
|| StringUtils.isNotEmpty(mobileRegisterDTO.getPassword())
|| StringUtils.isNotEmpty(mobileRegisterDTO.getVerificationCode())
|| Objects.isNull(mobileRegisterDTO.getIsThirdAccountRegistration())) {
throw new ApplicationException("参数不合法")
}
// TODO 其他逻辑
}
如果增加参数,还需要再加一个if条件判断,十分不优雅,如何让这段代码变得高大上呢?
本质上和if-else区别不大,使用function显得高级点
private final List<Function<MobileRegisterDTO, Boolean>> conditionChecked = Lists.newArrayList( Objects::nonNull, c -> StringUtils.isNotEmpty(c.getMobile()), c -> StringUtils.isNotEmpty(c.getNickname()), c -> StringUtils.isNotEmpty(c.getPassword()), c -> StringUtils.isNotEmpty(c.getVerificationCode()), c -> Objects.isNull(c.getIsThirdAccountRegistration()) ); /** * 手机号注册 * @param mobileRegisterDTO 手机号注册DTO * @return 注册响应 */ public void mobileRegister(MobileRegisterDTO mobileRegisterDTO) { boolean argumentValid = conditionChecked.stream().allMatch(condition -> condition.apply(mobileRegisterDTO)); if (!argumentValid) { //参数校验不通过 } }
结合javax的validate功能,封装通用参数校验服务,实现参数校验的功能。
在参数变量上添加校验的注解:
public class MobileRegisterDTO extends BaseDTO { /** * 手机号 */ @NotBlank(message = "手机号不能为空") @Size(min = 6, max = 11) private String mobile; /** * 国家码 */ private String countryCode; /** * 验证码 */ @NotBlank(message = "验证码不能为空") private String verificationCode; /** * 密码 */ @NotBlank private String password; /** * 昵称 */ @NotBlank private String nickname; /** * 是否是三方注册 */ @NotNull private Boolean isThirdAccountRegistration; }
封装通用的校验工具服务:
import org.apache.commons.lang3.StringUtils; import javax.validation.ConstraintViolation; import javax.validation.Validation; import javax.validation.Validator; import java.util.List; import java.util.Set; public class ValidationUtil { public final static Validator validator = Validation.buildDefaultValidatorFactory().getValidator(); /** * 验证单个实体 * * @param t 参数 * @param <T> 类型 * @return 验证结果 */ public static <T> String validateOne(T t) { Set<ConstraintViolation<T>> validateResult = validator.validate(t); if (validateResult != null && validateResult.size() != 0) { StringBuilder sb = new StringBuilder(); for (ConstraintViolation<T> valid : validateResult) { sb.append(valid.getPropertyPath().toString()).append(StringUtils.SPACE).append(valid.getMessage()) .append(","); } return sb.toString(); } return StringUtils.EMPTY; } /** * 验证多个实体 * * @param ts 参数 * @param <T> 类型 * @return 验证结果 */ public static <T> String validateMutil(List<T> ts) { StringBuilder sb = new StringBuilder(); for (int index = 0; index < ts.size(); ++index) { String validateOneResult = validateOne(ts.get(index)); if (!StringUtils.isBlank(validateOneResult)) { sb.append("index[" + index + "]:").append(validateOneResult).append(";"); } } return sb.toString(); } }
使用:
public void mobileRegister(MobileRegisterDTO mobileRegisterDTO) {
String errorMsg = ValidationUtil.validateOne(mobileRegisterDTO);
if (StringUtils.isNotBlank(errorMsg)) {
//参数校验不通过
}
}
参数校验虽然看起来简单,简单的if-else也能实现参数校验的效果,但是使用一些spring、java新特性,可以让我们的代码看起来更加简洁优雅。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。