0%

SpringBoot校验和全局异常处理

SpringBoot校验和全局异常处理

引入依赖

  • 在使用校验机制时,需要引入如下依赖
1
2
3
4
5
6
<--! 在这里必须使用6.0以下的版本-->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.18.Final</version>
</dependency>

约束性注解说明

  • 关于实体类或参数的一些注解
注解 功能
@NotNull 不能为null
@Null 必须为null
@NotBlank 字符串不能为null,字符串trim()后也不能等于“”
@NotEmpty 不能为null,集合、数组、map等size()不能为0;字符串trim()后可以等于“”
@Max 最大不能超过
@Min 最小不能超过
@Digits(integer = x, fraction = y) 设置必须是数字且数字整数的位数不超过x和小数的位数不超过y
@Length 字符串长度必须在指定范围内
@Past 日期必须在当前日期的过去
@Future 日期必须在当前日期的未来
@DecimalMax 设置不能超过最大值
@DecimalMin 设置不能超过最小值
@AssertFalse 可以为null,如果不为null的话必须为false
@AssertTrue 可以为null,如果不为null的话必须为true
@Range 值必须在指定范围内
@Size 集合、数组、map等的size()值必须在指定范围内
@Email 必须是email格式
@Pattern 必须满足指定的正则表达式
@URL 必须是一个URL
  • 实体类使用约束性注解:其中的message为校验失败的提示消息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class NewCoffeeRequest {
@NotBlank(message = "咖啡名称不能为空")
private String name;
@NotNull(message = "咖啡价格不能为null")
private Money price;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Money getPrice() {
return price;
}

public void setPrice(Money price) {
this.price = price;
}
}

@Valid和@Validated

  • 注解的使用:

    在参数的前面添加注解,代表该参数需要被校验,校验的内容就是约束性注解定义的内容

1
2
3
4
5
6
7
8
9
10
11
12
@PostMapping(path = "/", consumes = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
@ResponseStatus(HttpStatus.CREATED)
//在这里对Post请求提交的参数进行校验,并把校验的结果写入BindingResult参数中,BindingResult参数必须紧跟在被校验参数的后面
public Coffee addJsonCoffee(@RequestBody @Valid NewCoffeeRequest newCoffee, BindingResult result){
//如果校验不通过则会抛出异常
if (result.hasErrors()){
log.warn("errors:{}", result);
throw new ValidationException(result.toString());
}
return coffeeService.saveCoffee(newCoffee.getName(), newCoffee.getPrice());
}
  • 两者的区别:

    1. @Valid是使用Hibernate validation的时候使用

      @Validated是只用Spring Validator校验机制使用

    2. 注解位置:

      @Validated:用在类型、方法和方法参数上。但不能用于成员属性(field)

      @Valid:可以用在方法、构造函数、方法参数和成员属性(field)上

    3. @Validated提供了分组的功能,可以在参数验证时,根据不同的分组采用不同的验证机制,而@Valid没有分组的功能。对一个参数需要多种验证方式时,可通过分配不同的组达到目的,具体的做法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    //定义分组接口
    public interface IGroupA {
    }

    public interface IGroupB {
    }
    //然后在@Validated注解中添加接口的类
    @PostMapping("stu")
    public String addStu(@Validated({IGroupA.class}) @RequestBody StudentBean studentBean){
    return "add student success";
    }
  • 嵌套校验

    一个待校验的实体类,如果其中还包含了待校验的对象,就需要在待校验的对象上加上@Valid注解,才能校验包含的对象,注意,这里不能使用@Validated。

SpringBoot中的异常处理

  • @ControllerAdvice:用于捕获 Controller 层抛出的异常,如果添加 @ResponseBody 返回信息则为JSON格式,它将捕获@Controller层抛出的异常,使业务逻辑与异常处理剥离开。
  • @RestControllerAdvice :相当于 @ControllerAdvice@ResponseBody 的结合体,它将捕获@Controller@RestController层抛出的异常。
  • @ExceptionHandler:用于同于处理一种异常,减少重复性代码。

自定义异常类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@ResponseStatus(HttpStatus.BAD_REQUEST)
@Getter
@AllArgsConstructor
//FormValidationException继承了运行时的异常类,表示它是一个runtime的异常类,该类在抛出之后,会被系统捕获,并返回400状态码
public class FormValidationException extends RuntimeException {
private BindingResult result;
}
//controller
@PostMapping(path = "/", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
@ResponseBody
@ResponseStatus(HttpStatus.CREATED)
public Coffee addCoffee(@Valid NewCoffeeRequest newCoffee, BindingResult result){
if (result.hasErrors()){
log.warn("errors:{}", result);
throw new FormValidationException(result);
}
return coffeeService.saveCoffee(newCoffee.getName(), newCoffee.getPrice());
}

自定义一个全局异常处理

1
2
3
4
5
6
7
8
9
10
11
12
import javax.validation.ValidationException;
//当ValidationException异常抛出时,GlobalControllerAdvice将会捕获ValidationException异常,并执行Handler方法体,并返回400
@RestControllerAdvice
public class GlobalControllerAdvice {
@ExceptionHandler(ValidationException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public Map<String, String> validationExceptionHandler(ValidationException exception){
Map<String, String > map = new HashMap<>();
map.put("message", exception.getMessage());
return map;
}
}
-------------本文结束感谢您的阅读-------------