springboot interface parameter verification (JSR303)

A lot of validation annotations are defined in the javax.validation.constraints package, and dependencies are introduced:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>

Just add corresponding annotations on the entity class,
insert image description here

Entity class:

package com.zhmsky.mallproduct.entity;

import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;

import java.io.Serializable;
import java.util.Date;
import lombok.Data;

import javax.validation.constraints.NotBlank;

/**
* 品牌
* 
* @author zhmsky
* @email [email protected]
* @date 2022-07-30 16:40:28
*/
@Data
@TableName("pms_brand")
public class BrandEntity implements Serializable {
    
    
    private static final long serialVersionUID = 1L;

    /**
    * 品牌名
    */
    @NotBlank(message = "品牌名不能为空")
    private String name;
    
}

1. Handling verification exceptions in the controller interface

message can specify the verification description,
and then use the @Valid annotation in the corresponding controller interface method to specify the interface parameter verification, followed by BindingResult to receive the verification result. When the verification fails, it will encapsulate and return the verification failure information , if the verification is passed, the relevant logic is executed

@RequestMapping(value = "/save",method = RequestMethod.POST)
public R save(@Valid @RequestBody BrandEntity brand, BindingResult result){
    
    
    if(result.hasErrors()){
    
    
        Map<String, String> map = new HashMap<>();
        //获取校验结果
        for (FieldError fieldError : result.getFieldErrors()) {
    
    
            //获取错误提示
            String message = fieldError.getDefaultMessage();
            //校验错误的字段
            String field = fieldError.getField();
            //封装错误
            map.put(field,message);
        }
        return R.error(20001,"参数校验失败").put("errorMap",map);
    }
	brandService.save(brand);
    return R.ok();
}

2. Unified exception handling

If parameter verification exception handling is performed on each interface, the workload is relatively large and the code is cumbersome, so global exception handling is introduced, that is, the
use of @RestControllerAdvice+@ExceptionHandler annotations.

package com.zhmsky.mallproduct.exception;

import com.zhmsky.common.utils.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.HashMap;
import java.util.Map;

/**
 * 同意异常处理类
 * @author zhmsky
 * @date 2022/8/1 21:36
 */
@Slf4j
@RestControllerAdvice(basePackages = {
    
    "com.zhmsky.mallproduct.controller"})
public class MallProductControllerAdvice {
    
    

    //具体的某个异常类型处理
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public R handleValidException(MethodArgumentNotValidException e){
    
    
        log.error("数据异常:{},异常类型:{}",e.getMessage(),e.getClass());
        BindingResult result = e.getBindingResult();
        Map<String, String> map = new HashMap<>();
        for (FieldError fieldError : result.getFieldErrors()) {
    
    
            map.put(fieldError.getDefaultMessage(),fieldError.getField());
        }
        return R.error().put("errorMap",map);
    }

    //抛出的所有异常类型处理
    @ExceptionHandler(Throwable.class)
    public R handleException(Throwable e){
    
    
        //TODO 处理逻辑
        return R.error();
    }
}

3. Error code enumeration class

package com.zhmsky.common.exception;

/**
 * @author zhmsky
 * @date 2022/8/1 21:56
 */
public enum ErrorCodeEnum {
    
    
  
    UNKNOWN_EXCEPTION(10000, "系统未知错误"),

    VALID_EXCEPTION(10001, "参数格式校验失败");

    /**
     * 错误码
     */
    private Integer code;

    /**
     * 错误提示
     */
    private String msg;

    ErrorCodeEnum(Integer code, String msg) {
    
    
        this.code = code;
        this.msg = msg;
    }

    public Integer getCode(){
    
    
        return this.code;
    }

    public String getMsg(){
    
    
        return this.msg;
    }
}

4. Custom parameter verification annotation

1. Write custom validation annotations

Refer to the @NotBlank annotation of javax.validation.constraints,

@Documented
@Constraint(validatedBy = {
    
     })
@Target({
    
     METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
@Repeatable(List.class)
public @interface NotBlank {
    
    
    //校验规则提示信息
	String message() default "{javax.validation.constraints.NotBlank.message}";
    
    //分组校验
	Class<?>[] groups() default {
    
     };

    //负载
	Class<? extends Payload>[] payload() default {
    
     };

	/**
	 * Defines several {@code @NotBlank} constraints on the same element.
	 *
	 * @see NotBlank
	 */
	@Target({
    
     METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
	@Retention(RUNTIME)
	@Documented
	public @interface List {
    
    
		NotBlank[] value();
	}
}

Imitate the above to quickly write a custom annotation:

@Documented
@Constraint(validatedBy = {
    
    StatusValueConstraintValidator.class})
@Target({
    
    METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
@Retention(RUNTIME)
public @interface statusValue {
    
    
    //校验规则提示信息(在配置文件中配置)
    String message() default "{com.zhmsky.common.validator.statusValue.message}";

    Class<?>[] groups() default {
    
    };

    Class<? extends Payload>[] payload() default {
    
    };

    //注解参数
    int[] values() default {
    
    };
}

Create a ValidationMessages.properties file, and configure custom validation rule prompts in the configuration file:

com.zhmsky.common.validator.statusValue.message=error.......xxxx

2. Write a custom validator

//statusValue就是自定义的注解,Integer就是自定义注解标注的字段类型
public class StatusValueConstraintValidator implements ConstraintValidator<statusValue, Integer> {
    
    
    
    private Set<Integer> set = new HashSet<>();
    
    //初始化方法
    @Override
    public void initialize(statusValue constraintAnnotation) {
    
    
        //字段标注的注解里面设定的值(校验规则)
        int[] values = constraintAnnotation.values();
        for (int value : values) {
    
    
            set.add(value);
        }
    }
    
    //判断是否校验成功
    @Override
    public boolean isValid(Integer value, ConstraintValidatorContext context) {
    
    
        //value就是字段字段实际接收到的值
        return set.contains(value);
    }
}

3. Associate custom annotations and custom validators

That is, specify the custom validator in the @Constraint annotation of the custom annotation,
insert image description here

4. Test the custom annotation @statusValue

@Data
@TableName("pms_brand")
public class BrandEntity implements Serializable {
    
    
	private static final long serialVersionUID = 1L;
    
    	/**
	 * 品牌名
	 */
	@NotBlank(message = "品牌名不能为空")
	private String name;
    
    
	/**
	 * 显示状态[0-不显示;1-显示],指定字段值只能为 0 或 1
	 */
	@statusValue(values={
    
    0,1})
	private Integer showStatus;

}

Use the @Validated annotation in the corresponding controller interface to verify, and the showStatus field passes in a value of 3.
The test result is shown in the figure:
insert image description here

Guess you like

Origin blog.csdn.net/weixin_42194695/article/details/126128963