## 统一验证

本商城使用spring提供的统一校验工具`spring-boot-starter-validation`对请求进行校验

### 导入依赖

```xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>
```

这里通过注解封装了几种常用的校验

- `@NotNull` 不能为null
- `@NotEmpty` 不能为null、空字符串、空集合
- `@NotBlank` 不能为null、空字符串、纯空格的字符串
- `@Min` 数字最小值不能小于x
- `@Max` 数字最大值不能大于x
- `@Email` 字符串为邮件格式
- `@Max` 数字最大值不能大于x
- `@Size` 字符串长度最小为x、集合长度最小为x
- `@Pattern` 正则表达式

我们以`SpuDTO`为例，看看怎么使用

```java
public class SpuDTO{
	private static final long serialVersionUID = 1L;

	@Schema(description = "spuId" )
	private Long spuId;

	@Schema(description = "品牌ID" )
	private Long brandId;

	@NotNull(message = "分类不能为空")
	@Schema(description = "分类ID" )
	private Long categoryId;

	@NotNull(message = "店铺分类不能为空")
	@Schema(description = "店铺分类ID" )
	private Long shopCategoryId;

	@NotNull(message = "商品名称不能为空")
	@Schema(description = "spu名称" )
	private String name;
    
    /** 省略其余字段以及get、set、tostring方法*/
}
```

我们在Controller层使用该bean，并使用`@Valid`注解，使校验的注解生效，如`SpuController` ：

```java
@RestController("platformSpuController")
@RequestMapping("/admin/spu")
@Tag(name = "admin-spu信息")
public class SpuController {

    @Autowired
    private SpuService spuService;
    
    @PostMapping
    @Operation(summary = "保存spu信息" , description = "保存spu信息")
    public ServerResponseEntity<Void> save(@Valid @RequestBody SpuDTO spuDTO) {
        checkSaveOrUpdateInfo(spuDTO);
        spuService.save(spuDTO);
        return ServerResponseEntity.success();
    }
}
```

并且在`DefaultExceptionHandlerConfig` 拦截由`@Valid` 触发的异常信息并返回：

```java
@RestController
@RestControllerAdvice
public class DefaultExceptionHandlerConfig {

   @ExceptionHandler({ MethodArgumentNotValidException.class, BindException.class })
	public ResponseEntity<ServerResponseEntity<List<String>>> methodArgumentNotValidExceptionHandler(Exception e) {
		logger.error("methodArgumentNotValidExceptionHandler", e);
		List<FieldError> fieldErrors = null;
		if (e instanceof MethodArgumentNotValidException) {
			fieldErrors = ((MethodArgumentNotValidException) e).getBindingResult().getFieldErrors();
		}
		if (e instanceof BindException) {
			fieldErrors = ((BindException) e).getBindingResult().getFieldErrors();
		}
		if (fieldErrors == null) {
			return ResponseEntity.status(HttpStatus.OK)
					.body(ServerResponseEntity.fail(ResponseEnum.METHOD_ARGUMENT_NOT_VALID));
		}
		List<String> defaultMessages = new ArrayList<>(fieldErrors.size());
		for (FieldError fieldError : fieldErrors) {
			defaultMessages.add(fieldError.getField() + ":" + fieldError.getDefaultMessage());
		}
		return ResponseEntity.status(HttpStatus.OK)
				.body(ServerResponseEntity.fail(ResponseEnum.METHOD_ARGUMENT_NOT_VALID, defaultMessages));
	}

	@ExceptionHandler({ HttpMessageNotReadableException.class })
	public ResponseEntity<ServerResponseEntity<List<FieldError>>> methodArgumentNotValidExceptionHandler(
			HttpMessageNotReadableException e) {
		logger.error("methodArgumentNotValidExceptionHandler", e);
		return ResponseEntity.status(HttpStatus.OK)
				.body(ServerResponseEntity.fail(ResponseEnum.HTTP_MESSAGE_NOT_READABLE));
	}
}
```

