SpringBoot整合Validation
Table of Contents generated with DocToc (opens new window)
# Spring Boot整合Validation校验注意事项
# Maven配置
<!-- 注 此时使用的SpringBoot版本是2.4.5 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
1
2
3
4
5
2
3
4
5
只导入这一个starter和web的starter即可,不用加别的什么hibernate的包
# 使用方式注意
# 单个参数校验
当需要校验的参数都是非复杂对象的时候(即为String、Integer等类型时),需要在类上增加以下注解,校验才会生效
org.springframework.validation.annotation.@Validated
@Api(tags = {"博客端文章相关接口"}) @RestController @RequestMapping(value = "/article") @Validated @Uncheck public class ArticleController extends CommonController { @ApiOperation("文章详情") @GetMapping(value = "/detail") @Uncheck public ApiResponse detail(@NotNull(message = "id不能为空") Integer id){ Article article = articleService.getArticleById(id); return ApiResponse.success(article); } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 对象校验
当参数是复杂对象时,不需要在类上加上面的注解,但需要在类前加以下注解,不加则不会生效
javax.validation.@Valid
@PostMapping(value = "/login") @ResponseBody public ApiResponse login(@RequestBody @Valid LoginRequest loginRequest) { return userService.login(loginRequest); }
1
2
3
4
5
# 配合SpringMVC全局异常校验使用
/**
* @author zhangdikai
* @date 2022-07-28 14:34
*/
@RestControllerAdvice
public class GlobalExceptionHandler {
private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
/**
* 处理 form data方式调用接口校验失败抛出的异常
* @param e
* @return
*/
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler({BindException.class})
public ApiResponse handleValidationException(Exception e) {
ApiResponse response = ApiResponse.fail();
logger.error(e.getMessage(), e);
response.error(ErrorType.BAD_REQUEST, e.getMessage());
return response;
}
/**
* 处理json请求体调用参数异常
* @param e
* @return
*/
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler({MethodArgumentNotValidException.class})
public ApiResponse handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
ApiResponse response = ApiResponse.fail();
logger.error(e.getMessage(), e);
StringBuilder errorMsg = new StringBuilder();
BindingResult bindingResult = e.getBindingResult();
List<ObjectError> allErrors = bindingResult.getAllErrors();
if (!allErrors.isEmpty()) {
for (ObjectError objectError : allErrors) {
if (objectError instanceof FieldError) {
FieldError fieldError = (FieldError) objectError;
errorMsg.append(fieldError.getField()).append(":").append(fieldError.getDefaultMessage()).append(";");
} else {
errorMsg.append(objectError.getDefaultMessage()).append(";");
}
}
response.error(errorMsg.toString());
} else {
response.error(e.getMessage());
}
return response;
}
/**
* 处理单个参数校验失败抛出的异常
* @param e
* @return
*/
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(ConstraintViolationException.class)
public ApiResponse constraintViolationExceptionHandler(ConstraintViolationException e) {
ApiResponse response = ApiResponse.fail();
Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
List<String> collect = constraintViolations.stream()
.map(ConstraintViolation::getMessage)
.collect(Collectors.toList());
response.error(ErrorType.BAD_REQUEST,collect.toString());
return response;
}
@ResponseStatus(HttpStatus.NOT_FOUND)
@ExceptionHandler({NoHandlerFoundException.class})
public ApiResponse handlerNoFoundException(NoHandlerFoundException e) {
logger.error(e.getMessage(), e);
ApiResponse response = ApiResponse.fail();
response.error("404", "路径不存在,请检查路径是否正确");
return response;
}
@ExceptionHandler({DuplicateKeyException.class})
public ApiResponse handleDuplicateKeyException(DuplicateKeyException e) {
logger.error(e.getMessage(), e);
ApiResponse response = ApiResponse.fail();
response.error("数据库中已存在该记录");
return response;
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler({MissingServletRequestParameterException.class})
public ApiResponse handleMissingServletRequestParameterException(Exception e) {
ApiResponse response = ApiResponse.fail();
logger.error("参数解析失败", e);
response.error(ErrorType.BAD_REQUEST, "参数解析失败");
return response;
}
@ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
@ExceptionHandler({HttpRequestMethodNotSupportedException.class})
public ApiResponse handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
ApiResponse response = ApiResponse.fail();
logger.error("不支持当前请求方法", e);
response.error(ErrorType.METHOD_NOT_ALLOWED, "不支持当前请求方法");
return response;
}
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler({Exception.class})
public ApiResponse handleException(Exception e) {
ApiResponse response = ApiResponse.fail();
logger.error("系统异常", e);
response.error(ErrorType.SYSTEM_ERROR, "系统异常");
return response;
}
/**
* 处理业务异常
* @param e
* @return
*/
@ExceptionHandler({BusinessException.class})
public ApiResponse handleBusinessException(BusinessException e) {
ApiResponse<String> response = ApiResponse.fail();
logger.error(e.getMessage(), e);
response.error(e.getMessage());
if (e.getErrorCode() != null) {
response.setCode(e.getErrorCode());
}
return response;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
主要是前三个方法,分别对应form、json、单个参数三种参数形式校验所产生的异常的处理
# 总结
提示
实际配置是非常简单的,但网上很多教程令人眼花缭乱,配来配去反而变复杂了
在 GitHub 上编辑此页 (opens new window)
最后更新: 2022/10/04, 16:10:00