1. 首页
  2. IT资讯

这么写参数校验 Validator 就不会被劝退了

“u003Cpu003E优质文章,及时送达u003Cu002Fpu003Eu003Cimg src=”http:u002Fu002Fp1.pstatp.comu002Flargeu002Fpgc-imageu002FRcsUnd92eoboDR” img_width=”640″ img_height=”29″ alt=”这么写参数校验 Validator 就不会被劝退了” inline=”0″u003Eu003Cpu003E作者 | 锦成同学u003Cu002Fpu003Eu003Cpu003E链接 | juejin.imu002Fpostu002F5d3fbeb46fb9a06b317b3c48u003Cu002Fpu003Eu003Cpu003E很痛苦遇到大量的参数进行校验,在业务中还要抛出异常或者不断的返回异常时的校验信息,在代码中相当冗长, 充满了if-else这种校验代码,今天我们就来学习 Spring 的javax.validation 注解式参数校验。u003Cu002Fpu003Eu003Cpu003Eu003Cstrongu003E1. javax.validation的一系列注解可以帮我们完成参数校验,免去繁琐的串行校验u003Cu002Fstrongu003Eu003Cu002Fpu003Eu003Cpu003E不然我们的代码就像下面这样:u003Cu002Fpu003Eu003Cpreu003Eu003Ccodeu003E@PostMapping(“u002Fsaveu002Fserial”)u003Cu002Fcodeu003Eu003Ccodeu003E public Object save(@RequestBody UserVO userVO) {u003Cu002Fcodeu003Eu003Ccodeu003E String mobile = userVO.getMobile;u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E u002Fu002F手动逐个 参数校验~ 写法u003Cu002Fcodeu003Eu003Ccodeu003E if (StringUtils.isBlank(mobile)) {u003Cu002Fcodeu003Eu003Ccodeu003E return RspDTO.paramFail(“mobile:手机号码不能为空”);u003Cu002Fcodeu003Eu003Ccodeu003E } else if (!Pattern.matches(“^[1][3,4,5,6,7,8,9][0-9]{9}$”, mobile)) {u003Cu002Fcodeu003Eu003Ccodeu003E return RspDTO.paramFail(“mobile:手机号码格式不对”);u003Cu002Fcodeu003Eu003Ccodeu003E }u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E u002Fu002F抛出自定义异常等~写法u003Cu002Fcodeu003Eu003Ccodeu003E if (StringUtils.isBlank(userVO.getUsername)) {u003Cu002Fcodeu003Eu003Ccodeu003E throw new BizException(Constant.PARAM_FAIL_CODE, “用户名不能为空”);u003Cu002Fcodeu003Eu003Ccodeu003E }u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E u002Fu002F 比如写一个map返回u003Cu002Fcodeu003Eu003Ccodeu003E if (StringUtils.isBlank(userVO.getSex)) {u003Cu002Fcodeu003Eu003Ccodeu003E Map<String, Object> result = new HashMap<>(5);u003Cu002Fcodeu003Eu003Ccodeu003E result.put(“code”, Constant.PARAM_FAIL_CODE);u003Cu002Fcodeu003Eu003Ccodeu003E result.put(“msg”, “性别不能为空”);u003Cu002Fcodeu003Eu003Ccodeu003E return result;u003Cu002Fcodeu003Eu003Ccodeu003E }u003Cu002Fcodeu003Eu003Ccodeu003E u002Fu002F………各种写法 …u003Cu002Fcodeu003Eu003Ccodeu003E userService.save(userVO);u003Cu002Fcodeu003Eu003Ccodeu003E return RspDTO.success;u003Cu002Fcodeu003Eu003Ccodeu003E}u003Cu002Fcodeu003Eu003Cu002Fpreu003Eu003Cpu003E这被大佬看见,一定说,都9102了还这么写,然后被劝退了…..u003Cu002Fpu003Eu003Cpu003Eu003Cu002Fpu003Eu003Ch2 toutiao-origin=”h3″u003Eu003Cstrongu003E2. 什么是javax.validationu003Cu002Fstrongu003Eu003Cu002Fh2u003Eu003Cpu003EJSR303 是一套JavaBean参数校验的标准,它定义了很多常用的校验注解,我们可以直接将这些注解加在我们JavaBean的属性上面(面向注解编程的时代),就可以在需要校验的时候进行校验了,在SpringBoot中已经包含在starter-web中,再其他项目中可以引用依赖,并自行调整版本:u003Cu002Fpu003Eu003Cpreu003Eu003Ccodeu003E <!–jsr 303–>u003Cu002Fcodeu003Eu003Ccodeu003E <dependency>u003Cu002Fcodeu003Eu003Ccodeu003E <groupId>javax.validation<u002FgroupId>u003Cu002Fcodeu003Eu003Ccodeu003E <artifactId>validation-api<u002FartifactId>u003Cu002Fcodeu003Eu003Ccodeu003E <version>1.1.0.Final<u002Fversion>u003Cu002Fcodeu003Eu003Ccodeu003E <u002Fdependency>u003Cu002Fcodeu003Eu003Ccodeu003E <!– hibernate validator–>u003Cu002Fcodeu003Eu003Ccodeu003E <dependency>u003Cu002Fcodeu003Eu003Ccodeu003E <groupId>org.hibernate<u002FgroupId>u003Cu002Fcodeu003Eu003Ccodeu003E <artifactId>hibernate-validator<u002FartifactId>u003Cu002Fcodeu003Eu003Ccodeu003E <version>5.2.0.Final<u002Fversion>u003Cu002Fcodeu003Eu003Ccodeu003E <u002Fdependency>u003Cu002Fcodeu003Eu003Cu002Fpreu003Eu003Ch2 toutiao-origin=”h3″u003Eu003Cimg src=”http:u002Fu002Fp1.pstatp.comu002Flargeu002Fpgc-imageu002FRdiQ4osYabd29″ img_width=”640″ img_height=”255″ alt=”这么写参数校验 Validator 就不会被劝退了” inline=”0″u003Eu003Cu002Fh2u003Eu003Cpu003Eu003Cu002Fpu003Eu003Ch2 toutiao-origin=”h3″u003Eu003Cstrongu003E3. 注解说明u003Cu002Fstrongu003Eu003Cu002Fh2u003Eu003Culu003Eu003Cliu003Eu003Cpu003E@Not:不能为,但可以为empty(“”,” “,” “)u003Cu002Fpu003Eu003Cu002Fliu003Eu003Cliu003Eu003Cpu003E@NotEmpty:不能为,而且长度必须大于0 (” “,” “)u003Cu002Fpu003Eu003Cu002Fliu003Eu003Cliu003Eu003Cpu003E@NotBlank:只能作用在String上,不能为,而且调用trim后,长度必须大于0(“test”) 即:必须有实际字符u003Cu002Fpu003Eu003Cu002Fliu003Eu003Cu002Fulu003Eu003Cimg src=”http:u002Fu002Fp1.pstatp.comu002Flargeu002Fpgc-imageu002FRdiQ4p92xoJXyZ” img_width=”1080″ img_height=”1392″ alt=”这么写参数校验 Validator 就不会被劝退了” inline=”0″u003Eu003Cimg src=”http:u002Fu002Fp1.pstatp.comu002Flargeu002Fpgc-imageu002FRdiQ4pVBsx8FBj” img_width=”1080″ img_height=”1478″ alt=”这么写参数校验 Validator 就不会被劝退了” inline=”0″u003Eu003Cpu003E此处只列出Hibernate Validator提供的大部分验证约束注解,请参考hibernate validator官方文档了解其他验证约束注解和进行自定义的验证约束注解定义。u003Cu002Fpu003Eu003Cpu003Eu003Cu002Fpu003Eu003Ch1 toutiao-origin=”h2″u003E实战演练u003Cu002Fh1u003Eu003Cpu003E话不多说,直接走实践路线,同样使用的是SpringBoot的快速框架u003Cu002Fpu003Eu003Cpu003E详细代码见:u003Cu002Fpu003Eu003Cblockquoteu003Eu003Cpu003Ehttps:u002Fu002Fgithubu003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-1″u003E.comu003Cu002Fiu003Eu002FleaJoneu002Fmybotu003Cu002Fpu003Eu003Cu002Fblockquoteu003Eu003Cpu003Eu003Cu002Fpu003Eu003Ch2 toutiao-origin=”h3″u003Eu003Cstrongu003E1. @Validated 声明要检查的参数u003Cu002Fstrongu003Eu003Cu002Fh2u003Eu003Cpu003E这里我们在控制器层进行注解声明u003Cu002Fpu003Eu003Cpreu003Eu003Ccodeu003E u002F**u003Cu002Fcodeu003Eu003Ccodeu003E * 走参数校验注解u003Cu002Fcodeu003Eu003Ccodeu003E *u003Cu002Fcodeu003Eu003Ccodeu003E * @param userDTOu003Cu002Fcodeu003Eu003Ccodeu003E * @returnu003Cu002Fcodeu003Eu003Ccodeu003E *u002Fu003Cu002Fcodeu003Eu003Ccodeu003E @PostMapping(“u002Fsaveu002Fvalid”)u003Cu002Fcodeu003Eu003Ccodeu003E public RspDTO save(@RequestBody @Validated UserDTO userDTO) {u003Cu002Fcodeu003Eu003Ccodeu003E userService.save(userDTO);u003Cu002Fcodeu003Eu003Ccodeu003E return RspDTO.success;u003Cu002Fcodeu003Eu003Ccodeu003E }u003Cu002Fcodeu003Eu003Cu002Fpreu003Eu003Cpu003Eu003Cu002Fpu003Eu003Ch2 toutiao-origin=”h3″u003Eu003Cstrongu003E2. 对参数的字段进行注解标注u003Cu002Fstrongu003Eu003Cu002Fh2u003Eu003Cpreu003Eu003Ccodeu003E@Datau003Cu002Fcodeu003Eu003Ccodeu003Epublic class UserDTO implements Serializable {u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E private static final long serialVersionUID = 1L;u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E u002F*** 用户ID*u002Fu003Cu002Fcodeu003Eu003Ccodeu003E @Not(message = “用户id不能为空”)u003Cu002Fcodeu003Eu003Ccodeu003E private Long userId;u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E u002F** 用户名*u002Fu003Cu002Fcodeu003Eu003Ccodeu003E @NotBlank(message = “用户名不能为空”)u003Cu002Fcodeu003Eu003Ccodeu003E @Length(max = 20, message = “用户名不能超过20个字符”)u003Cu002Fcodeu003Eu003Ccodeu003E @Pattern(regexp = “^[\\\u4E00-\\\u9FA5A-Za-z0-9\\*]*$”, message = “用户昵称限制:最多20字符,包含文字、字母和数字”)u003Cu002Fcodeu003Eu003Ccodeu003E private String username;u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E u002F** 手机号*u002Fu003Cu002Fcodeu003Eu003Ccodeu003E @NotBlank(message = “手机号不能为空”)u003Cu002Fcodeu003Eu003Ccodeu003E @Pattern(regexp = “^[1][3,4,5,6,7,8,9][0-9]{9}$”, message = “手机号格式有误”)u003Cu002Fcodeu003Eu003Ccodeu003E private String mobile;u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E u002F**性别*u002Fu003Cu002Fcodeu003Eu003Ccodeu003E private String sex;u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E u002F** 邮箱*u002Fu003Cu002Fcodeu003Eu003Ccodeu003E @NotBlank(message = “联系邮箱不能为空”)u003Cu002Fcodeu003Eu003Ccodeu003E @Email(message = “邮箱格式不对”)u003Cu002Fcodeu003Eu003Ccodeu003E private String email;u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E u002F** 密码*u002Fu003Cu002Fcodeu003Eu003Ccodeu003E private String password;u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E u002F*** 创建时间 *u002Fu003Cu002Fcodeu003Eu003Ccodeu003E @Future(message = “时间必须是将来时间”)u003Cu002Fcodeu003Eu003Ccodeu003E private Date createTime;u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E}u003Cu002Fcodeu003Eu003Cu002Fpreu003Eu003Cpu003Eu003Cu002Fpu003Eu003Ch2 toutiao-origin=”h3″u003Eu003Cstrongu003E3. 在全局校验中增加校验异常u003Cu002Fstrongu003Eu003Cu002Fh2u003Eu003Cpu003EMethodArgumentNotValidException是springBoot中进行绑定参数校验时的异常,需要在springBoot中处理,其他需要处理ConstraintViolationException异常进行处理.u003Cu002Fpu003Eu003Cpu003E为了优雅一点,我们将参数异常,业务异常,统一做了一个全局异常,将控制层的异常包装到我们自定义的异常中.u003Cu002Fpu003Eu003Cpu003E为了优雅一点,我们还做了一个统一的结构体,将请求的code,和msg,data一起统一封装到结构体中,增加了代码的复用性.u003Cu002Fpu003Eu003Cpreu003Eu003Ccodeu003E@RestControllerAdviceu003Cu002Fcodeu003Eu003Ccodeu003Epublic class GlobalExceptionHandler {u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E private Logger logger = LoggerFactory.getLogger(getClass);u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E private static int DUPLICATE_KEY_CODE = 1001;u003Cu002Fcodeu003Eu003Ccodeu003E private static int PARAM_FAIL_CODE = 1002;u003Cu002Fcodeu003Eu003Ccodeu003E private static int VALIDATION_CODE = 1003;u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E u002F**u003Cu002Fcodeu003Eu003Ccodeu003E * 处理自定义异常u003Cu002Fcodeu003Eu003Ccodeu003E *u002Fu003Cu002Fcodeu003Eu003Ccodeu003E @ExceptionHandler(BizException.class)u003Cu002Fcodeu003Eu003Ccodeu003E public RspDTO handleRRException(BizException e) {u003Cu002Fcodeu003Eu003Ccodeu003E logger.error(e.getMessage, e);u003Cu002Fcodeu003Eu003Ccodeu003E return new RspDTO(e.getCode, e.getMessage);u003Cu002Fcodeu003Eu003Ccodeu003E }u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E u002F**u003Cu002Fcodeu003Eu003Ccodeu003E * 方法参数校验u003Cu002Fcodeu003Eu003Ccodeu003E *u002Fu003Cu002Fcodeu003Eu003Ccodeu003E @ExceptionHandler(MethodArgumentNotValidException.class)u003Cu002Fcodeu003Eu003Ccodeu003E public RspDTO handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {u003Cu002Fcodeu003Eu003Ccodeu003E logger.error(e.getMessage, e);u003Cu002Fcodeu003Eu003Ccodeu003E return new RspDTO(PARAM_FAIL_CODE, e.getBindingResult.getFieldError.getDefaultMessage);u003Cu002Fcodeu003Eu003Ccodeu003E }u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E u002F**u003Cu002Fcodeu003Eu003Ccodeu003E * ValidationExceptionu003Cu002Fcodeu003Eu003Ccodeu003E *u002Fu003Cu002Fcodeu003Eu003Ccodeu003E @ExceptionHandler(ValidationException.class)u003Cu002Fcodeu003Eu003Ccodeu003E public RspDTO handleValidationException(ValidationException e) {u003Cu002Fcodeu003Eu003Ccodeu003E logger.error(e.getMessage, e);u003Cu002Fcodeu003Eu003Ccodeu003E return new RspDTO(VALIDATION_CODE, e.getCause.getMessage);u003Cu002Fcodeu003Eu003Ccodeu003E }u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E u002F**u003Cu002Fcodeu003Eu003Ccodeu003E * ConstraintViolationExceptionu003Cu002Fcodeu003Eu003Ccodeu003E *u002Fu003Cu002Fcodeu003Eu003Ccodeu003E @ExceptionHandler(ConstraintViolationException.class)u003Cu002Fcodeu003Eu003Ccodeu003E public RspDTO handleConstraintViolationException(ConstraintViolationException e) {u003Cu002Fcodeu003Eu003Ccodeu003E logger.error(e.getMessage, e);u003Cu002Fcodeu003Eu003Ccodeu003E return new RspDTO(PARAM_FAIL_CODE, e.getMessage);u003Cu002Fcodeu003Eu003Ccodeu003E }u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E @ExceptionHandler(NoHandlerFoundException.class)u003Cu002Fcodeu003Eu003Ccodeu003E public RspDTO handlerNoFoundException(Exception e) {u003Cu002Fcodeu003Eu003Ccodeu003E logger.error(e.getMessage, e);u003Cu002Fcodeu003Eu003Ccodeu003E return new RspDTO(404, “路径不存在,请检查路径是否正确”);u003Cu002Fcodeu003Eu003Ccodeu003E }u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E @ExceptionHandler(DuplicateKeyException.class)u003Cu002Fcodeu003Eu003Ccodeu003E public RspDTO handleDuplicateKeyException(DuplicateKeyException e) {u003Cu002Fcodeu003Eu003Ccodeu003E logger.error(e.getMessage, e);u003Cu002Fcodeu003Eu003Ccodeu003E return new RspDTO(DUPLICATE_KEY_CODE, “数据重复,请检查后提交”);u003Cu002Fcodeu003Eu003Ccodeu003E }u003Cu002Fcodeu003Eu003Cbru003Eu003Cbru003Eu003Ccodeu003E @ExceptionHandler(Exception.class)u003Cu002Fcodeu003Eu003Ccodeu003E public RspDTO handleException(Exception e) {u003Cu002Fcodeu003Eu003Ccodeu003E logger.error(e.getMessage, e);u003Cu002Fcodeu003Eu003Ccodeu003E return new RspDTO(500, “系统繁忙,请稍后再试”);u003Cu002Fcodeu003Eu003Ccodeu003E }u003Cu002Fcodeu003Eu003Ccodeu003E}u003Cu002Fcodeu003Eu003Cu002Fpreu003Eu003Cpu003Eu003Cstrongu003E4. 测试u003Cu002Fstrongu003Eu003Cu002Fpu003Eu003Cpu003E如下文:确实做到了参数校验时返回异常信息和对应的code,方便了我们不再繁琐的处理参数校验u003Cu002Fpu003Eu003Cimg src=”http:u002Fu002Fp1.pstatp.comu002Flargeu002Fpgc-imageu002FRdiQ4q44XLg2Te” img_width=”640″ img_height=”309″ alt=”这么写参数校验 Validator 就不会被劝退了” inline=”0″u003Eu003Cpu003E在ValidationMessages.properties 就是校验的message,有着已经写好的默认的message,且是支持i18n的,大家可以阅读源码赏析u003Cu002Fpu003Eu003Cpu003Eu003Cu002Fpu003Eu003Ch1 toutiao-origin=”h2″u003E自定义参数注解u003Cu002Fh1u003Eu003Ch2 toutiao-origin=”h3″u003Eu003Cstrongu003E1. 比如我们来个 自定义身份证校验 注解u003Cu002Fstrongu003Eu003Cu002Fh2u003Eu003Cpreu003Eu003Ccodeu003E@Documentedu003Cu002Fcodeu003Eu003Ccodeu003E@Target({ElementType.PARAMETER, ElementType.FIELD})u003Cu002Fcodeu003Eu003Ccodeu003E@Retention(RetentionPolicy.RUNTIME)u003Cu002Fcodeu003Eu003Ccodeu003E@Constraint(validatedBy = IdentityCardNumberValidator.class)u003Cu002Fcodeu003Eu003Ccodeu003Epublic @interface IdentityCardNumber {u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E String message default “身份证号码不合法”;u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E Class<?> groups default {};u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E Class<? extends Payload> payload default {};u003Cu002Fcodeu003Eu003Ccodeu003E}u003Cu002Fcodeu003Eu003Cu002Fpreu003Eu003Cpu003E这个注解是作用在Field字段上,运行时生效,触发的是IdentityCardNumber这个验证类。u003Cu002Fpu003Eu003Culu003Eu003Cliu003Eu003Cpu003Emessage 定制化的提示信息,主要是从ValidationMessages.properties里提取,也可以依据实际情况进行定制u003Cu002Fpu003Eu003Cu002Fliu003Eu003Cliu003Eu003Cpu003Egroups 这里主要进行将validator进行分类,不同的类group中会执行不同的validator操作u003Cu002Fpu003Eu003Cu002Fliu003Eu003Cliu003Eu003Cpu003Epayload 主要是针对bean的,使用不多。u003Cu002Fpu003Eu003Cu002Fliu003Eu003Cu002Fulu003Eu003Cpu003Eu003Cu002Fpu003Eu003Ch2 toutiao-origin=”h3″u003Eu003Cstrongu003E2. 然后自定义Validatoru003Cu002Fstrongu003Eu003Cu002Fh2u003Eu003Cpu003E这个是真正进行验证的逻辑代码:u003Cu002Fpu003Eu003Cpreu003Eu003Ccodeu003Epublic class IdentityCardNumberValidator implements ConstraintValidator<IdentityCardNumber, Object> {u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E @Overrideu003Cu002Fcodeu003Eu003Ccodeu003E public void initialize(IdentityCardNumber identityCardNumber) {u003Cu002Fcodeu003Eu003Ccodeu003E }u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E @Overrideu003Cu002Fcodeu003Eu003Ccodeu003E public boolean isValid(Object o, ConstraintValidatorContext constraintValidatorContext) {u003Cu002Fcodeu003Eu003Ccodeu003E return IdCardValidatorUtils.isValidate18Idcard(o.toString);u003Cu002Fcodeu003Eu003Ccodeu003E }u003Cu002Fcodeu003Eu003Ccodeu003E}u003Cu002Fcodeu003Eu003Cu002Fpreu003Eu003Cpu003EIdCardValidatorUtils在项目源码中,可自行查看u003Cu002Fpu003Eu003Cpu003Eu003Cu002Fpu003Eu003Ch2 toutiao-origin=”h3″u003Eu003Cstrongu003E3. 使用自定义的注解u003Cu002Fstrongu003Eu003Cu002Fh2u003Eu003Cpreu003Eu003Ccodeu003E @NotBlank(message = “身份证号不能为空”)u003Cu002Fcodeu003Eu003Ccodeu003E @IdentityCardNumber(message = “身份证信息有误,请核对后提交”)u003Cu002Fcodeu003Eu003Ccodeu003E private String clientCardNo;u003Cu002Fcodeu003Eu003Cu002Fpreu003Eu003Cpu003Eu003Cstrongu003E4. 使用groups的校验u003Cu002Fstrongu003Eu003Cu002Fpu003Eu003Cpu003E有的u003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-3″u003E宝宝u003Cu002Fiu003E说同一个对象要复用,比如UserDTO在更新时候要校验userId,在保存的时候不需要校验userId,在两种情况下都要校验username,那就用上groups了:u003Cu002Fpu003Eu003Cpu003E先定义groups的分组接口Create和Updateu003Cu002Fpu003Eu003Cpreu003Eu003Ccodeu003Eimport javax.validation.groups.Default;u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003Epublic interface Create extends Default {u003Cu002Fcodeu003Eu003Ccodeu003E}u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003Eimport javax.validation.groups.Default;u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003Epublic interface Update extends Default{u003Cu002Fcodeu003Eu003Ccodeu003E}u003Cu002Fcodeu003Eu003Cu002Fpreu003Eu003Cpu003E再在需要校验的地方@Validated声明校验组u003Cu002Fpu003Eu003Cpreu003Eu003Ccodeu003E u002F**u003Cu002Fcodeu003Eu003Ccodeu003E * 走参数校验注解的 groups 组合校验u003Cu002Fcodeu003Eu003Ccodeu003E *u003Cu002Fcodeu003Eu003Ccodeu003E * @param userDTOu003Cu002Fcodeu003Eu003Ccodeu003E * @returnu003Cu002Fcodeu003Eu003Ccodeu003E *u002Fu003Cu002Fcodeu003Eu003Ccodeu003E @PostMapping(“u002Fupdateu002Fgroups”)u003Cu002Fcodeu003Eu003Ccodeu003E public RspDTO update(@RequestBody @Validated(Update.class) UserDTO userDTO) {u003Cu002Fcodeu003Eu003Ccodeu003E userService.updateById(userDTO);u003Cu002Fcodeu003Eu003Ccodeu003E return RspDTO.success;u003Cu002Fcodeu003Eu003Ccodeu003E }u003Cu002Fcodeu003Eu003Cu002Fpreu003Eu003Cpu003E在DTO中的字段上定义好groups = {}的分组类型u003Cu002Fpu003Eu003Cpreu003Eu003Ccodeu003E@Datau003Cu002Fcodeu003Eu003Ccodeu003Epublic class UserDTO implements Serializable {u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E private static final long serialVersionUID = 1L;u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E u002F*** 用户ID*u002Fu003Cu002Fcodeu003Eu003Ccodeu003E @Not(message = “用户id不能为空”, groups = Update.class)u003Cu002Fcodeu003Eu003Ccodeu003E private Long userId;u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E u002F**u003Cu002Fcodeu003Eu003Ccodeu003E * 用户名u003Cu002Fcodeu003Eu003Ccodeu003E *u002Fu003Cu002Fcodeu003Eu003Ccodeu003E @NotBlank(message = “用户名不能为空”)u003Cu002Fcodeu003Eu003Ccodeu003E @Length(max = 20, message = “用户名不能超过20个字符”, groups = {Create.class, Update.class})u003Cu002Fcodeu003Eu003Ccodeu003E @Pattern(regexp = “^[\\\u4E00-\\\u9FA5A-Za-z0-9\\*]*$”, message = “用户昵称限制:最多20字符,包含文字、字母和数字”)u003Cu002Fcodeu003Eu003Ccodeu003E private String username;u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E u002F**u003Cu002Fcodeu003Eu003Ccodeu003E * 手机号u003Cu002Fcodeu003Eu003Ccodeu003E *u002Fu003Cu002Fcodeu003Eu003Ccodeu003E @NotBlank(message = “手机号不能为空”)u003Cu002Fcodeu003Eu003Ccodeu003E @Pattern(regexp = “^[1][3,4,5,6,7,8,9][0-9]{9}$”, message = “手机号格式有误”, groups = {Create.class, Update.class})u003Cu002Fcodeu003Eu003Ccodeu003E private String mobile;u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E u002F**u003Cu002Fcodeu003Eu003Ccodeu003E * 性别u003Cu002Fcodeu003Eu003Ccodeu003E *u002Fu003Cu002Fcodeu003Eu003Ccodeu003E private String sex;u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E u002F**u003Cu002Fcodeu003Eu003Ccodeu003E * 邮箱u003Cu002Fcodeu003Eu003Ccodeu003E *u002Fu003Cu002Fcodeu003Eu003Ccodeu003E @NotBlank(message = “联系邮箱不能为空”)u003Cu002Fcodeu003Eu003Ccodeu003E @Email(message = “邮箱格式不对”)u003Cu002Fcodeu003Eu003Ccodeu003E private String email;u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E u002F**u003Cu002Fcodeu003Eu003Ccodeu003E * 密码u003Cu002Fcodeu003Eu003Ccodeu003E *u002Fu003Cu002Fcodeu003Eu003Ccodeu003E private String password;u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E u002F*** 创建时间 *u002Fu003Cu002Fcodeu003Eu003Ccodeu003E @Future(message = “时间必须是将来时间”, groups = {Create.class})u003Cu002Fcodeu003Eu003Ccodeu003E private Date createTime;u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E}u003Cu002Fcodeu003Eu003Cu002Fpreu003Eu003Cpu003E注意:在声明分组的时候尽量加上 extend javax.validation.groups.Default 否则,在你声明@Validated(Update.class)的时候,就会出现你在默认没添加groups = {}的时候的校验组@Email(message = “邮箱格式不对”),会不去校验,因为默认的校验组是groups = {Default.class}.u003Cu002Fpu003Eu003Cpu003Eu003Cu002Fpu003Eu003Ch2 toutiao-origin=”h3″u003Eu003Cstrongu003E5. restful风格用法u003Cu002Fstrongu003Eu003Cu002Fh2u003Eu003Cpu003E在多个参数校验,或者@RequestParam 形式时候,需要在controller上加注@Validatedu003Cu002Fpu003Eu003Cpreu003Eu003Ccodeu003E @GetMapping(“u002Fget”)u003Cu002Fcodeu003Eu003Ccodeu003E public RspDTO getUser(@RequestParam(“userId”) @Not(message = “用户id不能为空”) Long userId) {u003Cu002Fcodeu003Eu003Ccodeu003E User user = userService.selectById(userId);u003Cu002Fcodeu003Eu003Ccodeu003E if (user == ) {u003Cu002Fcodeu003Eu003Ccodeu003E return new RspDTO<User>.nonAbsent(“用户不存在”);u003Cu002Fcodeu003Eu003Ccodeu003E }u003Cu002Fcodeu003Eu003Ccodeu003E return new RspDTO<User>.success(user);u003Cu002Fcodeu003Eu003Ccodeu003E }u003Cu002Fcodeu003Eu003Cu002Fpreu003Eu003Cpreu003Eu003Ccodeu003E@RestControlleru003Cu002Fcodeu003Eu003Ccodeu003E@RequestMapping(“useru002F”)u003Cu002Fcodeu003Eu003Ccodeu003E@Validatedu003Cu002Fcodeu003Eu003Ccodeu003Epublic class UserController extends AbstractController { …u003Cu002Fcodeu003Eu003Cu002Fpreu003Eu003Cpu003Eu003Cu002Fpu003Eu003Ch1 toutiao-origin=”h2″u003E总结u003Cu002Fh1u003Eu003Cpu003E用起来很简单,soEasy,重点参与的统一结构体返回,统一参数校验,是减少我们代码大量的try catch 的法宝,我觉得在项目中,将异常处理好,并将异常做好日志管理,才是很好的升华,文章浅显,只是一个菜鸟的进阶笔记.u003Cu002Fpu003Eu003Cp class=””u003E-END-u003Cu002Fpu003E”

原文始发于:这么写参数校验 Validator 就不会被劝退了

主题测试文章,只做测试使用。发布者:℅傍ㄖ免沦陷dε鬼,转转请注明出处:http://www.cxybcw.com/18006.html

联系我们

13687733322

在线咨询:点击这里给我发消息

邮件:1877088071@qq.com

工作时间:周一至周五,9:30-18:30,节假日休息

QR code