@Valid
: 嵌套校验 = 入参@Valid + 属性上@Valid
用在方法入参上无法单独提供嵌套验证功能。
能配合嵌套验证注解@Valid进行嵌套验证。
能够用在成员属性(字段)上,提示验证框架进行嵌套验证。
@Validated
: 嵌套校验 = 入参@Validated + 属性上@Valid
用在方法入参上无法单独提供嵌套验证功能。
能配合嵌套验证注解@Valid进行嵌套验证。
不能用在成员属性(字段)上,也无法提示框架进行嵌套验证。
参考:https://blog.csdn.net/qq_27680317/article/details/79970590
<dependencies>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>1.18.20version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
<version>2.4.5version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
<version>2.4.5version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
<scope>compilescope>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-validationartifactId>
<version>2.4.5version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-jsonartifactId>
<version>2.4.5version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>fastjsonartifactId>
<version>1.2.76version>
dependency>
<dependency>
<groupId>io.springfoxgroupId>
<artifactId>springfox-swagger-uiartifactId>
<version>2.9.2version>
dependency>
<dependency>
<groupId>io.springfoxgroupId>
<artifactId>springfox-swagger2artifactId>
<version>2.9.2version>
dependency>
dependencies>
/**
* @Author: Huishi
* @Date: 2021/10/15 13:17
*/
public enum ApiCode {
SUCCESS(200, "操作成功"),
FAIL(500, "操作失败"),
SYSTEM_EXCEPTION(5000, "系统异常!"),
PARAMETER_EXCEPTION(5001, "请求参数校验异常"),
;
private final int code;
private final String msg;
ApiCode(final int code, final String msg) {
this.code = code;
this.msg = msg;
}
public static ApiCode getApiCode(int code) {
ApiCode[] ecs = ApiCode.values();
for (ApiCode ec : ecs) {
if (ec.getCode() == code) {
return ec;
}
}
return SUCCESS;
}
public int getCode() {
return code;
}
public String getMsg() {
return msg;
}
}
/**
* @Author: Huishi
* @Date: 2021/10/15 13:16
*/
@Data
@Accessors(chain = true)
@Builder
@AllArgsConstructor
public class ApiResult<T> implements Serializable {
/**
* 响应码
*/
private int code;
/**
* 响应消息
*/
private String msg;
/**
* 是否成功
*/
private boolean success;
/**
* 响应数据
*/
private T data;
/**
* 响应时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date time = new Date();
public ApiResult() {
}
public static ApiResult result(boolean flag){
if (flag){
return ok();
}
return fail();
}
public static ApiResult result(ApiCode apiCode){
return result(apiCode,null);
}
public static ApiResult result(ApiCode apiCode,Object data){
return result(apiCode,null,data);
}
public static ApiResult result(ApiCode apiCode,String msg,Object data){
boolean success = false;
if (apiCode.getCode() == ApiCode.SUCCESS.getCode()){
success = true;
}
String message = apiCode.getMsg();
if (StringUtils.isNotBlank(msg)){
message = msg;
}
return ApiResult.builder()
.code(apiCode.getCode())
.msg(message)
.data(data)
.success(success)
.time(new Date())
.build();
}
public static ApiResult ok(){
return ok(null);
}
public static ApiResult ok(Object data){
return result(ApiCode.SUCCESS,data);
}
public static ApiResult ok(Object data,String msg){
return result(ApiCode.SUCCESS,msg,data);
}
public static ApiResult okMap(String key,Object value){
Map<String,Object> map = new HashMap<>();
map.put(key,value);
return ok(map);
}
public static ApiResult fail(ApiCode apiCode){
return result(apiCode,null);
}
public static ApiResult fail(String msg){
return result(ApiCode.FAIL,msg,null);
}
public static ApiResult fail(ApiCode apiCode,Object data){
if (ApiCode.SUCCESS == apiCode){
throw new RuntimeException("失败结果状态码不能为" + ApiCode.SUCCESS.getCode());
}
return result(apiCode,data);
}
public static ApiResult fail(String key,Object value){
Map<String,Object> map = new HashMap<>();
map.put(key,value);
return result(ApiCode.FAIL,map);
}
public static ApiResult fail() {
return fail(ApiCode.FAIL);
}
}
参考:https://blog.csdn.net/qq_27680317/article/details/79970590
public class Item {
@NotNull(message = "id不能为空")
@Min(value = 1, message = "id必须为正整数")
private Long id;
@Valid // 嵌套验证必须用@Valid
@NotNull(message = "props不能为空")
@Size(min = 1, message = "props至少要有一个自定义属性")
private List<Prop> props;
}
————————————————
public class Prop {
@NotNull(message = "pid不能为空")
@Min(value = 1, message = "pid必须为正整数")
private Long pid;
@NotNull(message = "vid不能为空")
@Min(value = 1, message = "vid必须为正整数")
private Long vid;
@NotBlank(message = "pidName不能为空")
private String pidName;
@NotBlank(message = "vidName不能为空")
private String vidName;
}
/**
* @Author: Huishi
* @Date: 2021/10/15 13:10
*/
@ControllerAdvice
@RestController
@Slf4j
public class GlobalExceptionHandler {
/**
* 非法参数验证异常
*
* @param ex
* @return
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(value = HttpStatus.OK)
public ApiResult handleMethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException ex) {
BindingResult bindingResult = ex.getBindingResult();
List<String> list = new ArrayList<>();
List<FieldError> fieldErrors = bindingResult.getFieldErrors();
for (FieldError fieldError : fieldErrors) {
list.add(fieldError.getDefaultMessage());
}
Collections.sort(list);
log.error("fieldErrors" + JSON.toJSONString(list));
return ApiResult.fail(ApiCode.PARAMETER_EXCEPTION, list);
}
}
@Configuration
@EnableSwagger2 //开启Swagger2
public class SwaggerConfig
{
//配置
@Bean
public Docket docket(){
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo());
}
//作者信息
private ApiInfo apiInfo() {
Contact contact = new Contact("Huishi", "https://blog.csdn.net/qq_36937684?spm=1001.2101.3001.5343", "[email protected]");
return new ApiInfo("文档","测试 Spring-boot-valid","v1.0","https://mvnrepository.com/search?q=springfox++swagger",contact,"Apache 2.0", "http://www.apache.org/licenses/LICENSE-2.0", new ArrayList());
}
}
@RestController
public class ItemController {
@Autowired
ItemService itemService;
@PostMapping("/item/add") // 或者用@Validated也是一样的
public @ResponseBody ApiResult<Boolean> addItem(@Valid @RequestBody Item item) throws Exception {
int add = itemService.add(item);
return ApiResult.ok(add);
}
}
①正常
{
"id": 2,
"props": [
{
"pid": 3,
"pidName": "string",
"vid": 8,
"vidName": "string"
}
]
}
返回
{
"code": 200,
"msg": "操作成功",
"success": true,
"data": 2,
"time": "2021-10-15 06:08:54"
}
②Item类 id属性为空
{
"props": [
{
"pid": 3,
"pidName": "string",
"vid": 8,
"vidName": "string"
}
]
}
返回
{
"code": 5001,
"msg": "请求参数校验异常",
"success": false,
"data": [
"id不能为空"
],
"time": "2021-10-15 06:10:51"
}
③Prop类 不满足条件
{
"id": 3,
"props": [
{
"pid": 0,
"pidName": "string",
"vid": 8,
"vidName": "string"
}
]
}
返回
{
"code": 5001,
"msg": "请求参数校验异常",
"success": false,
"data": [
"pid必须为正整数"
],
"time": "2021-10-15 06:11:58"
}