栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

SpringBoot项目中验证框架Validator完美实现

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SpringBoot项目中验证框架Validator完美实现

SpringBoot项目中验证框架Validator完美实现
    • 1、简介
    • 2、Validator常见注解清单
    • 3、校验案例实战
      • 3.1、校验实体
      • 3.2、校验Cntroller层实现
    • 4、统一捕获验证注解异常
    • 5、自定义验证异常

1、简介

Spring Boot支持JSR-303验证框架,默认实现是Hibernate Validator,项目中只要在Java Bean上放一些校验注解,就可以实现校验支持,杜绝通篇 if else 参数判断,而且这个校验是支持group的概念的,对于不同的group生效的校验不一样。这个很有用,因为对于增删改查等不同的操作,需要执行的校验本来就是不一样的。
注意:
spring boot2.3.x版本的spring boot项目,在使用hibernate-validator相关的注解的时候,发现不能导入相关的包。
官方给出的解决方法,手动导入相关依赖就行,如下:


  org.springframework.boot
  spring-boot-starter-validation

2、Validator常见注解清单
注释描述
@AssertFalse被注释的参数必须为 false
@AssertTrue被注释的元素必须为 true
@NotNull参数不能是Null
@Null参数是Null
@Szie带注释的参数大小必须介于指定边界(包括)之间
@PositiveOrZero被注释的元素必须严格的正数(包含0)
@Positive被注释的元素必须严格的正数(0为无效值)
@Pattern被注释的元素必须符合指定的正则表达式
@NotEmpty同StringUtils.isNotEmpty
@NotBlank同StringUtils.isNotBlank
@NegativeOrZero带注释的元素必须是一个严格的负数(包含0)
@Negative带注释的元素必须是一个严格的负数(0为无效值)
@Min被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Email邮箱规则
@DecimalMax被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Range(min=1, max=99)参数需要在指定的范围内
3、校验案例实战 3.1、校验实体
@Data
//@TableName("t_teacher"),实体类名以驼峰的形式命名,可以省略@TableName,否则加上
public class TTeacher implements Serializable {
	private static final long serialVersionUID = 1L;

	public interface Update{}
    public interface Add{}

	@TableId(type = IdType.AUTO)
	
	@NotNull(groups = {Update.class},message = "不能为空")
    @Null(groups = {Add.class},message = "必须为空")
	private Integer id;

	//教师名称
	@Size(min=3, max=20)
	private String teacherName;

	//教师年龄
	private integer age;

	//学科
	private String course;

	//评分
	private BigDecimal score;

	//教学天数
	private Integer teachingDays;

	//状态
	private String status;

	//授课总数
	private Integer teachingCount;

	//每天教学价格
	private BigDecimal priceOfDay;

	//开始教学时间
	private Date startTime;

	//简介
	private String description;

	//照片
	private String photo;

	//详细信息
	private String detail;

}

3.2、校验Cntroller层实现
 //如果想在参数中使用 @NotNull 这种注解校验,就必须在类上添加 @Validated
//如果方法中的参数是对象类型,则必须要在参数对象前面添加 @Validated
@Validated
@RestController
@RequestMapping("/teacher")
public class TeacherController {

	@Autowired
	private TeacherService teacherService;

	@IgnoreAnnotation
	@GetMapping(value = "/findAll",name = "查询所有老师数据")
	public ResponseMessage> findAll(){

		return new OverAllExceptionAdvice().sendSuccessResponse(teacherService.findAll());
	}
	// 这里就声明了要激活Add group对应的校验注解
   // 那么就会校验tTeacher的id不能为空
	@PostMapping(value = "/add",name = "新增教师")
	public ResponseMessage add(@RequestBody @Validated({TTeacher.Add.class}) TTeacher tTeacher){
		teacherService.add(tTeacher);
		return new OverAllExceptionAdvice().sendSuccessResponse();
	}

	@PutMapping(value = "/update",name = "更新教师信息")
	public ResponseMessage update(@RequestBody TTeacher tTeacher){
		teacherService.update(tTeacher);
		return new OverAllExceptionAdvice().sendSuccessResponse();
	}

	@DeleteMapping(value = "/del/{id}",name = "根据id删除教师信息")
	public ResponseMessage del(@PathVariable("id") @NotNull @Min(value = 10,message = "id不能小于此数字") Integer id){
		teacherService.del(id);
		return new OverAllExceptionAdvice().sendSuccessResponse();
	}
}


执行结果,http://localhost:8090/elasticsearch/teacher/add

http://localhost:8090/elasticsearch/teacher/del/5

4、统一捕获验证注解异常
@RestControllerAdvice
@Slf4j
public class OverAllExceptionAdvice implements ResponseBodyAdvice {

	public ResponseMessage sendSuccessResponse(){
		return new ResponseMessage(ResponseStatus.SUCCESS.getCode(),ResponseStatus.SUCCESS.getMessage(), null);
	}

	public ResponseMessage sendSuccessResponse(T data) {
		return new ResponseMessage(ResponseStatus.SUCCESS.getCode(),ResponseStatus.SUCCESS.getMessage(), data);
	}

	@ExceptionHandler(BindException.class)
	public ResponseMessage sendErrorResponse_Validator(BindException exception){
		FieldError err = exception.getFieldError();
		String message = "参数{".concat(err.getField()).concat("}").concat(err.getDefaultMessage());
		log.info("{} -> {}", err.getObjectName(), message);
		return new ResponseMessage(ResponseStatus.UNKNOWEXCEPTION.getCode(),ResponseStatus.UNKNOWEXCEPTION.getMessage(), null);
	}
	
	
	@ExceptionHandler(ConstraintViolationException.class)
	public ResponseMessage sendErrorResponse_ConstraintViolation(ConstraintViolationException exception){
		Set> constraintViolations = exception.getConstraintViolations();
		for (ConstraintViolation constraintViolation : constraintViolations) {
			PathImpl pathImpl = (PathImpl) constraintViolation.getPropertyPath();
			// 读取参数字段,constraintViolation.getMessage() 读取验证注解中的message值
			String paramName = pathImpl.getLeafNode().getName();
			String message = "参数{".concat(paramName).concat("}").concat(constraintViolation.getMessage());
			log.info("{} -> {} -> {}", constraintViolation.getRootBeanClass().getName(), pathImpl.toString(), message);
		}
		return new ResponseMessage(ResponseStatus.UNKNOWEXCEPTION.getCode(),ResponseStatus.UNKNOWEXCEPTION.getMessage(), null);
	}

	@ExceptionHandler(Exception.class)
	public ResponseMessage sendErrorResponse_System(Exception exception){
		log.info("请求异常:{}",exception.getMessage());
		if (exception instanceof BusinessRuntimeException) {
			return this.sendErrorResponse_UserDefined(exception);
		}

		return new ResponseMessage(ResponseStatus.UNKNOWEXCEPTION.getCode(),ResponseStatus.UNKNOWEXCEPTION.getMessage(), null);
	}

	
	@Override
	public boolean supports(MethodParameter methodParameter, Class> aClass) {
		//IgnoreAnnotation:被IgnoreAnnotation标记的方法所响应的数据不会走beforeBodyWrite()方法。
		if (methodParameter.hasMethodAnnotation(IgnoreAnnotation.class))
			return false;
		return true;
	}

	
	@Override
	public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
								  Class> selectedConverterType, ServerHttpRequest request,
								  ServerHttpResponse response) {
	//处理的具体执行方法的逻辑
		return body;
	}
}
 

IgnoreAnnotation注解代码实现:

@documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface IgnoreAnnotation {
}

5、自定义验证异常

代码实现:

@Constraint(validatedBy = {Agevalidator.class})
@documented
@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicty.RUNTIME)
public @interface Age {
    
    String message() default "年龄是非法的,不能超过{max}岁";
    int max() default 100;
    Class[] groups default {};
    Class[] payload() default {};
    
}
public class Agevalidator implements ConstraintValidator {
    private Age age;
    private Integer max;
    
    public void initialize(Age age) {
        this.age = age;
        this.max = age.max();
    }
    
    public boolean isValid(Integer value, ConstraintValidatorContext context) {
        return value < max;
    }
    
}
转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号