1.创建一个统一返回结果集
@Data
public class JsonResult implements Serializable {
private static final long serialVersionUID = -1946193220290386110L;
public static final boolean SUCCESS = true;
public static final boolean FAIL = false;
private boolean status;
private int code;
private String msg;
private Object data;
public JsonResult(boolean status, int code, String msg, Object data) {
this.status = status;
this.code = code;
this.msg = msg;
this.data = data;
}
public static JsonResult success(Object data) {
return new JsonResult(SUCCESS, 200, "ok", data);
}
public static JsonResult success(String msg) {
return new JsonResult(SUCCESS, 200, msg, null);
}
public static JsonResult fail(String msg) {
return fail(400, msg);
}
public static JsonResult fail(int code, String msg) {
return new JsonResult(FAIL, code, msg, null);
}
}
2.创建一个用于测试的用户类
@Data
public class User implements Serializable {
@Length(min = 5, max = 10, message = "用户名长度不合法")
@NotNull(message = "用户名不能为空")
private String username;
@Length(min = 6, max = 16, message = "密码长度不合法")
@NotNull(message = "密码不能为空")
private String password;
}
3.创建一个controller
@RestController
//在请求方法中校验需要在类上加该注解
@Validated
public class UserController {
//测试post请求
//@Validated用于校验参数,如果参数校验失败,错误信息封装到BindingResult
@PostMapping("/login")
public JsonResult login(@Validated @RequestBody User user, BindingResult bindingResult){
//判断BindingResult中是否有错误信息
if(bindingResult.hasErrors()){
return JsonResult.fail(bindingResult.getFieldError().getDefaultMessage());
}
return JsonResult.success("登陆成功");
}
//测试get请求
@GetMapping("/getLogin")
public JsonResult getLogin(@Validated User user, BindingResult bindingResult){
if(bindingResult.hasErrors()){
return JsonResult.fail(bindingResult.getFieldError().getDefaultMessage());
}
return JsonResult.success("登陆成功");
}
//测试请求方法中校验
//这种校验不支持封装到BindingResult中,需要自己做异常处理
@GetMapping("/getUser")
public JsonResult getUser(@NotNull(message = "用户名不能为空") String username){
User user = new User();
user.setUsername(username);
user.setPassword("123456");
return JsonResult.success(user);
}
}
4.测试
测试post请求,由于未写html页面,用postman进行测试
- 请求:post http://localhost:8080/login
- 参数:{"username":"admin", "password":"123"}
- 返回结果:{"status":false,"code":400,"msg":"密码长度不合法","data":null}
测试get请求
- 请求:get http://localhost:8080/getLogin?username=admin&password=123
- 返回结果:{"status":false,"code":400,"msg":"密码长度不合法","data":null}
测试请求方法中校验
- 请求:get http://localhost:8080/getUser
- 返回结果:springboot默认的错误信息
5.统一异常处理
@RestControllerAdvice
public class GlobalExceptionHandler {
/**
* post请求参数校验抛出的异常
* @param e
* @return
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public JsonResult methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e){
//获取异常中随机一个异常信息
String defaultMessage = e.getBindingResult().getFieldError().getDefaultMessage();
return JsonResult.fail(defaultMessage);
}
/**
* get请求参数校验抛出的异常
* @param e
* @return
*/
@ExceptionHandler(BindException.class)
public JsonResult bindExceptionHandler(BindException e){
//获取异常中随机一个异常信息
String defaultMessage = e.getBindingResult().getFieldError().getDefaultMessage();
return JsonResult.fail(defaultMessage);
}
/**
* 请求方法中校验抛出的异常
* @param e
* @return
*/
@ExceptionHandler(ConstraintViolationException.class)
public JsonResult constraintViolationExceptionHandler(ConstraintViolationException e){
//获取异常中第一个错误信息
String message = e.getConstraintViolations().iterator().next().getMessage();
return JsonResult.fail(message);
}
}
将所有的校验异常都在异常统一处理后,controller参数中就可以不写BindingResult,也不需要每个方法都校验是否有异常了
使用异常统一处理后的controller
@RestController
public class UserBetterController {
@PostMapping("/login")
public JsonResult login(@Validated @RequestBody User user){
return JsonResult.success("登陆成功");
}
@GetMapping("/getLogin")
public JsonResult getLogin(@Validated User user){
return JsonResult.success("登陆成功");
}
@GetMapping("/getUser")
public JsonResult getUser(@NotNull(message = "用户名不能为空") String username){
User user = new User();
user.setUsername(username);
user.setPassword("123456");
return JsonResult.success(user);
}
}
6.分组校验
- 创建用于分组的接口
//什么都不需要写,springboot根据类去分组校验
//用户校验添加角色校验
public interface Add {}
//用于校验修改角色校验
public interface Update {}
- 创建一个测试分组的实体类
@Data
public class Role {
//修改角色时,必须要有id
@NotNull(message = "修改角色必须有id", groups = Update.class)
private Long id;
//添加角色时必须要有name
@NotNull(message = "添加角色必须有name", groups = Add.class)
//添加修改都需要name的长度在1-10
@Length(min = 1, max = 10, message = "名称不合法", groups = {Add.class, Update.class})
private String name;
}
- 创建测试controller
@RestController
public class RoleController {
@GetMapping("add")
public JsonResult add(@Validated(Add.class) Role role){
return JsonResult.success("添加成功");
}
@GetMapping("update")
public JsonResult update(@Validated(Update.class) Role role){
return JsonResult.success("修改成功");
}
}
测试
测试添加角色
请求:get http://localhost:8080/add
返回结果:{"status":false,"code":400,"msg":"添加角色必须有name","data":null}测试修改角色
请求:get http://localhost:8080/update
返回结果:{"status":false,"code":400,"msg":"修改角色必须有id","data":null}
7.自定义校验注解
- 创建自定义校验注解
@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
@Retention(RUNTIME)
//用于校验手机号的逻辑类
@Constraint(validatedBy = PhoneValidator.class)
public @interface Phone {
//手机号的校验格式
String regexp() default "^[1][3-9][0-9]{9}$";
//出现错误返回的信息
String message() default "手机号格式错误";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
@Documented
public @interface List {
Phone[] value();
}
}
- 创建校验注解的类
//校验注解的类必须实现ConstraintValidator,第一个泛型是注解,第二个泛型是校验参数的类型(手机号是String类型)
public class PhoneValidator implements ConstraintValidator<Phone, String> {
private String regexp;
//初始化方法
@Override
public void initialize(Phone constraintAnnotation) {
//获取校验的手机号的格式
this.regexp = constraintAnnotation.regexp();
}
//value是@Phone注解所注解的字段值
//校验,返回true则通过校验,返回false则校验失败,错误信息为注解中的message
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if(value == null){
return true;
}
return value.matches(regexp);
}
}
- 测试
@RestController
@Validated
public class PhoneController {
@GetMapping("/sendPhone")
public JsonResult sendPhone(@Phone @NotNull(message = "手机号不能为空") String phone){
return JsonResult.success("正确的手机号");
}
}
请求:get http://localhost:8080/sendPhone?phone=123
返回结果:{"status":false,"code":400,"msg":"手机号格式错误","data":null}
常用的校验注解自行搜索引擎
作者公众号