springboot实现校验参数,以及异常处理(转载)
转载地址:https://blog.csdn.net/qq_32352777/article/details/108424932
简述
@Validation是一套帮助我们继续对传输的参数进行数据校验的注解,通过配置Validation可以很轻松的完成对数据的约束。
@Validated作用在类、方法和参数上
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Validated { Class<?>[] value() default {}; }
错误的状态码
返回的响应码推荐使用400 bad request.(看个人喜好,自己封装请求返回结果其实更好)
所有参数注解含义

全局异常处理类
说明:若不做异常处理,@Validated注解的默认异常消息如下(示例):
2020-09-05 21:48:38.106 WARN 9796 --- [nio-8080-exec-3] .w.s.m.s.DefaultHandlerExceptionResolver :
Resolved [org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in public java.lang.String com.example.validateddemo.controller.DemoController.validatedDemo1(com.example.validateddemo.entity.dto.UseDto):
[Field error in object 'useDto' on field 'username': rejected value [null]; codes [NotBlank.useDto.username,NotBlank.username,NotBlank.java.lang.String,NotBlank];
arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [useDto.username,username]; arguments []; default message [username]]; default message [用户名不能为空!]] ]
因此我们在这里做了一个全局的异常处理类,用于处理参数校验失败后抛出的异常,同时进行日志输出。
/** * 传参异常处理 * @Author: zt * @Date: 2021/5/27 21:59 */ @Slf4j @RestControllerAdvice public class ParamValidatedAdvice { @ExceptionHandler(value = MethodArgumentNotValidException.class) public AjaxResult handleBindGetException(MethodArgumentNotValidException exception){ List<String> errors = exception.getBindingResult() .getFieldErrors() .stream() .map(item -> item.getDefaultMessage()) .collect(Collectors.toList()); return AjaxResult.error("参数校验失败",errors); } }
基础参数校验
实体类
package com.example.validateddemo.entity.dto; import lombok.Data; import org.springframework.format.annotation.DateTimeFormat; import javax.validation.constraints.*; @Data public class User1Dto { /** * 用户名 */ @NotBlank(message = "用户名不能为空!") private String username; /** * 性别 */ @NotBlank(message = "性别不能为空!") private String gender; /** * 年龄 */ @Min(value = 1, message = "年龄有误!") @Max(value = 120, message = "年龄有误!") private int age; /** * 地址 */ @NotBlank(message = "地址不能为空!") private String address; /** * 邮箱 */ @Email(message = "邮箱有误!") private String email; /** * 手机号码 */ @Pattern(regexp = "^(13[0-9]|14[579]|15[0-3,5-9]|16[6]|17[0135678]|18[0-9]|19[89])\\d{8}$",message = "手机号码有误!") private String mobile; }
控制类
package com.example.validateddemo.controller; import com.example.validateddemo.entity.dto.Use1Dto; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @author He Changjie on 2020/9/5 */ @RestController @RequestMapping("/api/v1") public class Demo1Controller { @PostMapping("/insert") public String validatedDemo1(@Validated @RequestBody Use1Dto use1Dto){ System.out.println(use1Dto); return "success"; } }
嵌套参数验证
验证实体中的其他需要被验证的对象集合或其他对象
实体类
package com.example.validateddemo.entity.dto; import lombok.Data; import javax.validation.Valid; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import java.util.List; /** * 队伍实体 * 数据传输对象 * @author He Changjie on 2020/9/5 */ @Data public class Team1Dto { /** * 队伍名称 */ @NotBlank(message = "队伍名称不能为空!") private String name; /** * 队伍人员 */ @NotNull(message = "队伍人员不能为空!") @Valid private List<User1Dto> userList; /** * 队伍负责人 */ @NotNull(message = "队伍负责人不能为空!") @Valid private User1Dto user; }
控制类
package com.example.validateddemo.controller; import com.example.validateddemo.base.Result; import com.example.validateddemo.entity.dto.Team1Dto; import com.example.validateddemo.entity.dto.Use1Dto; import com.example.validateddemo.utils.ResultUtil; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @author He Changjie on 2020/9/5 */ @RestController @RequestMapping("/api/v1") public class Demo1Controller { @PostMapping("/insert") public Result validatedDemo1(@Validated @RequestBody Use1Dto use1Dto){ return ResultUtil.success(use1Dto); } @PostMapping("/insert2") public Result validatedDemo2(@Validated @RequestBody Team1Dto team1Dto){ return ResultUtil.success(team1Dto); } }
分组参数验证
将不同的校验规则分给不同的组,在使用时,指定不同的校验规则
接口类
package com.example.validateddemo.interfaces; /** * 校验分组1 * @author He Changjie on 2020/9/5 */ public interface Group1 { }
package com.example.validateddemo.interfaces; /** * 校验分组2 * @author He Changjie on 2020/9/5 */ public interface Group2 { }
实体类
package com.example.validateddemo.entity.dto; import com.example.validateddemo.interfaces.Group1; import com.example.validateddemo.interfaces.Group2; import lombok.Data; import javax.validation.constraints.*; /** * @author He Changjie on 2020/9/5 */ @Data public class User2Dto { /** * 用户名 */ @NotBlank(message = "用户名不能为空!", groups = {Group1.class}) private String username; /** * 性别 */ @NotBlank(message = "性别不能为空!") private String gender; /** * 年龄 */ @Min(value = 1, message = "年龄有误!", groups = {Group1.class}) @Max(value = 120, message = "年龄有误!", groups = {Group2.class}) private int age; /** * 地址 */ @NotBlank(message = "地址不能为空!") private String address; /** * 邮箱 */ @Email(message = "邮箱有误!", groups = {Group2.class}) private String email; /** * 手机号码 */ @Pattern(regexp = "^(13[0-9]|14[579]|15[0-3,5-9]|16[6]|17[0135678]|18[0-9]|19[89])\\d{8}$",message = "手机号码有误!", groups = {Group2.class}) private String mobile; }
控制类
package com.example.validateddemo.controller; import com.example.validateddemo.base.Result; import com.example.validateddemo.entity.dto.Team1Dto; import com.example.validateddemo.entity.dto.User1Dto; import com.example.validateddemo.entity.dto.User2Dto; import com.example.validateddemo.interfaces.Group1; import com.example.validateddemo.interfaces.Group2; import com.example.validateddemo.utils.ResultUtil; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @author He Changjie on 2020/9/5 */ @RestController @RequestMapping("/api/v1") public class Demo1Controller { @PostMapping("/insert") public Result validatedDemo1(@Validated @RequestBody User1Dto user1Dto){ return ResultUtil.success(user1Dto); } @PostMapping("/insert2") public Result validatedDemo2(@Validated @RequestBody Team1Dto team1Dto){ return ResultUtil.success(team1Dto); } @PostMapping("/insert3") public Result validatedDemo3(@Validated @RequestBody User2Dto user2Dto){ return ResultUtil.success(user2Dto); } @PostMapping("/insert4") public Result validatedDemo4(@Validated(Group1.class) @RequestBody User2Dto user2Dto){ return ResultUtil.success(user2Dto); } @PostMapping("/insert5") public Result validatedDemo5(@Validated(Group2.class) @RequestBody User2Dto user2Dto){ return ResultUtil.success(user2Dto); } }
@Valid和@Validated 区别
通过源码分析:
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Valid { }
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Validated { Class<?>[] value() default {}; }
@Valid:没有分组的功能。
@Valid:可以用在方法、构造函数、方法参数和成员属性(字段)上
@Validated:提供了一个分组功能,可以在入参验证时,根据不同的分组采用不同的验证机制
@Validated:可以用在类型、方法和方法参数上。但是不能用在成员属性(字段)上
两者是否能用于成员属性(字段)上直接影响能否提供嵌套验证的功能

浙公网安备 33010602011771号