Springboot 参数校验@Valid @Validated(最新最全)
提示:统一参数校验,异常处理
文章目录
前言
表单提交,后端做数据校验
一、统一参数校验(普通)
1.引入依赖
提示:实操过程发现,引入validation-api 不好使,需要引入hibernate-validator
依赖如下:
<!-- 自定义注解
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
</dependency>
-->
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
2.创建Control
如下:
package com.xjw.mytest.control;
import com.alibaba.fastjson.JSONObject;
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;
import javax.validation.Valid;
@RestController
@RequestMapping("/user")
public class UserControl {
@PostMapping("/add")
public R add(@Valid @RequestBody UserDto data) {
System.out.println("data is "+ JSONObject.toJSONString(data));
return R.ok();
}
}
2.创建Advice
如下:
package com.xjw.mytest.control;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.util.HashMap;
import java.util.Map;
@RestControllerAdvice(basePackages = "com.xjw")
public class ExceptionControllerAdvice {
@ExceptionHandler(value = MethodArgumentNotValidException.class)
public R handleVaildException(MethodArgumentNotValidException e) {
BindingResult bindingResult = e.getBindingResult();
Map<String, String> errorMap = new HashMap<>();
bindingResult.getFieldErrors().forEach(bean->{
errorMap.put(bean.getField(), bean.getDefaultMessage());
});
return R.error("400", "数据校验问题").put("data",errorMap);
}
@ExceptionHandler(value = Exception.class)
public R handleVaildException(Exception e) {
return R.error("500", "系统内部错误");
}
}
3.统一返回参数
如下:
package com.xjw.mytest.control;
import java.util.HashMap;
import java.util.Map;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
/**
* 返回数据
*/
public class R extends HashMap<String, Object> {
/** 未知异常 **/
public static final String UN_KNOW_ERROR = "-1";
public static final String SUCCESS_CODE = "200";// 成功
public static final String ERROR_CODE = "500";// 失败
public static final String MSG_SUCESS = "success";
public static final String MSG_ERROR = "error";
public static final String DATA = "data";
public static final String DATAS = "datas";
public static final String CODE = "code";
public static final String MSG = "message";
private static final long serialVersionUID = 1L;
public <T> T getData(String key, TypeReference<T> typeReference) {
Object data = get(key);
String s = JSON.toJSONString(data);
return JSON.parseObject(s, typeReference);
}
public <T> T getData(TypeReference<T> typeReference) {
Object data = get(DATA);
String s = JSON.toJSONString(data);
return JSON.parseObject(s, typeReference);
}
public R setData(Object data) {
put(DATA, data);
return this;
}
public R setDatas(Object data) {
put(DATAS, data);
return this;
}
public R() {
put(CODE, SUCCESS_CODE);
put(MSG, MSG_SUCESS);
}
public static R error(String code) {
return error(code, MSG_ERROR);
}
public static R error(String code, String msg) {
R r = new R();
r.put(CODE, code);
r.put(MSG, msg);
return r;
}
public static R ok(String msg) {
R r = new R();
r.put(CODE, SUCCESS_CODE);
r.put(MSG, msg);
return r;
}
public static R ok(Map<String, Object> map) {
R r = new R();
r.putAll(map);
return r;
}
public static R ok() {
R r = new R();
r.put(CODE, SUCCESS_CODE);
r.put(MSG, MSG_SUCESS);
return r;
}
public R put(String key, Object value) {
super.put(key, value);
return this;
}
public Integer getCode() {
return (Integer) this.get(CODE);
}
public String getmsg() {
return (String) this.getOrDefault(MSG, "");
}
public String getcode() {
return (String) this.getOrDefault(CODE, "");
}
}
4.创建Dto
如下:
package com.xjw.mytest.control;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Null;
public class UserDto {
private String id;
@NotNull(message = "名称不能为空"})
private String userName;
@NotNull(message = "年龄不能为空")
private Integer age;
private Integer status;
}
二、统一参数校验(分组)
提示:就是创建两个空接口
1.创建分组接口
代码如下(示例):
package com.xjw.mytest.control;
public interface AddGroup {
}
package com.xjw.mytest.control;
public interface UpdateGroup {
}
2.创建Control
提示:接口中的注解修改了,修改@Validated(value = {AddGroup.class})
代码如下(示例):
package com.xjw.mytest.control;
import com.alibaba.fastjson.JSONObject;
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;
import javax.validation.Valid;
@RestController
@RequestMapping("/userGroup")
public class UserGroupControl {
@PostMapping("/add")
public R add(@Validated(value = {AddGroup.class}) @RequestBody UserDto data) {
System.out.println("data is "+ JSONObject.toJSONString(data));
return R.ok();
}
@PostMapping("/update")
public R update(@Validated(value = {UpdateGroup.class}) @RequestBody UserDto data) {
System.out.println("data is "+ JSONObject.toJSONString(data));
return R.ok();
}
}
3.修改Dto
提示:Dto中的注解修改了,增加了Control
代码如下(示例):
package com.xjw.mytest.control;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Null;
public class UserDto {
@NotNull(message = "新增必须为空", groups = {AddGroup.class})
@Null(message = "更新必须不为空", groups = {UpdateGroup.class})
private String id;
@NotNull(message = "名称不能为空", groups = {AddGroup.class, UpdateGroup.class})
private String userName;
@NotNull(message = "年龄不能为空",groups = {AddGroup.class, UpdateGroup.class})
private Integer age;
private Integer status;
}
二、统一参数校验(自定义注解)
提示:就是创建两个空接口
1.创建注解类
代码如下(示例):
package com.xjw.mytest.control;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.ElementType.TYPE_USE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Documented
@Constraint(validatedBy = {ListValueConstraintValidator.class })
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
public @interface ListValue {
String message() default "{com.xjw.validation.listValue.message}";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
int[] vals() default {};
}
2.创建校验器
提示:接口中的注解修改了,修改@Validated(value = {AddGroup.class})
代码如下(示例):
package com.xjw.mytest.control;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.HashSet;
import java.util.Set;
public class ListValueConstraintValidator implements ConstraintValidator<ListValue, Integer> {
private Set<Integer> set = new HashSet<>();
//初始化方法(设置注解中的只,例如状态(1,2)此时就可以获取注解中的1,2)
@Override
public void initialize(ListValue constraintAnnotation) {
int[] vals = constraintAnnotation.vals();
for (int val : vals){
set.add(val);
}
}
// 校验是否成功
/**
* value 就是提交上来的数据
* @param value object to validate
* @param context context in which the constraint is evaluated
*
* @return
*/
@Override
public boolean isValid(Integer value, ConstraintValidatorContext context) {
return set.contains(value);
}
}
3.添加配置文件
提示:文件名称ValidationMessages.properties ,路径resources下
代码如下(示例):
com.xjw.validation.listValue.message = 必须提交指定值
3.修改Dto
提示:文件名称ValidationMessages.properties ,路径resources下
代码如下(示例):
package com.xjw.mytest.control;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Null;
public class UserDto {
@NotNull(message = "新增必须为空", groups = {AddGroup.class})
@Null(message = "更新必须不为空", groups = {UpdateGroup.class})
private String id;
@NotNull(message = "名称不能为空", groups = {AddGroup.class, UpdateGroup.class})
private String userName;
@NotNull(message = "年龄不能为空",groups = {AddGroup.class, UpdateGroup.class})
private Integer age;
@ListValue(vals = {1,2}, groups = {AddGroup.class})
private Integer status;
}
提示:如果ValidationMessages.properties 中的提示信息乱码,可以如下处理
总结
例如:以上三种校验规则基本满足日常开发中的各种表单校验规则