package javax.validation.constraints;
1.给字段添加注解
2.通知springmvc需要校验
3.给校验的bean后紧跟一个BindResult,就可以获取校验的结果
可以根据结果判断
效果:
小案例
![](https://i-blog.csdnimg.cn/blog_migrate/32c8cb7c56b0d15a9a3231915795bc2f.png)
统一异常
问题:每一个controller方法都要写校验代码
@ControllerAdvice
1、状态码枚举类
/**
* 状态码
* @author 江南大学1033190417
* @date 2022/6/7 0:18
*/
/**
* 错误码和错误信息定义类
* 1. 错误码定义规则为5为数字
* 2. 前两位表示业务场景,最后三位表示错误码。例如:100001。10:通用 001:系统未知异常
* 3. 维护错误码后需要维护错误描述,将他们定义为枚举形式
* 错误码列表:
* 10: 通用
* 001:参数格式校验
* 11: 商品
* 12: 订单
* 13: 购物车
* 14: 物流
*
*
*/
public enum BizCodeEnum {
UKOWN_EXCEPTION(10000,"系统位置异常"),
VALID_EXCEPTION(10001,"参数格式校验失败");
private Integer code;
private String msg;
BizCodeEnum(Integer code,String msg){
this.code=code;
this.msg=msg;
}
public Integer getCode() {
return code;
}
public String getMsg() {
return msg;
}
}
2、统一异常处理类
import com.atguigu.common.exception.BizCodeEnum;
import com.atguigu.common.utils.R;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.crypto.ec.ECElGamalDecryptor;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.util.HashMap;
import java.util.Map;
/**
* 几种处理所有异常
*
* @author 江南大学1033190417
* @date 2022/6/7 0:04
*/
@Slf4j
@ResponseBody
@ControllerAdvice(basePackages = "com.atguigu.gulimall.product.controller")
//@RestControllerAdvice可以替换上面两个
public class GulimallExceptionControllerAdvice {
//处理数据校验异常
@ExceptionHandler(value = MethodArgumentNotValidException.class)
public R handleValidException(MethodArgumentNotValidException e){
log.error("数据校验出现问题{},异常类型{}",e.getMessage(),e.getClass());
BindingResult result = e.getBindingResult();
Map<String,Object> map=new HashMap<>();
result.getFieldErrors().forEach((item)->{
String message = item.getDefaultMessage();//错误信息
String field = item.getField();//错误字段
map.put(field,message);
});
return R.error(BizCodeEnum.VALID_EXCEPTION.getCode(),BizCodeEnum.VALID_EXCEPTION.getMsg()).put("data",map);
}
//处理其他异常
@ExceptionHandler(value = Throwable.class)
public R handleException(Throwable throwable){
return R.error(BizCodeEnum.UKOWN_EXCEPTION.getCode(), BizCodeEnum.UKOWN_EXCEPTION.getMsg());
}
}
分组校验
1、新建分组
接口不同实现,空操作
/**
* 新增组接口 标识而已
* @author 江南大学1033190417
* @date 2022/6/7 0:35
*/
public interface AddGroup {
}
2、校验注解中指定分组
3、控制层指定分组
注意:
控制层指定分组校验时(@Validdated({AddGroup.calss})):其他添加校验注解且未指定分组的不会被校验,所以要为其他注解都添加分组
如果控制层未指定分组,就会生效
自定义校验注解
想要的效果,showStatus必须是vals指定的值
1、编写一个自定义校验注解
可以模仿 package javax.validation.constraints; 下的其他注解
1)注解类
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE_USE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Documented;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.util.Arrays;
import javax.validation.Constraint;
import javax.validation.Payload;
import javax.validation.constraints.NotBlank.List;
/**
* 自定义校验注解
*
* @author 江南大学1033190417
* @date 2022/6/7 1:02
*/
@Documented
@Constraint(validatedBy = {})//用什么校验器来校验
@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
@Retention(RUNTIME)
public @interface ListValue {
String message() default "{com.atguigu.common.valid.ListValue.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
int[] vals() default {};//新添加属性
}
2)com.atguigu.common.valid.ListValue.message 提示消息的配置文件
参考原本自带的ValidationMessages.properties设置,在idea中可以双击shift键来搜索
在resources下创建一个ValidationMessages.properties文件
配置文件内容:对应 String message() default "{com.atguigu.common.valid.ListValue.message}"; 代码的内容
如果有中文可以在设置中设置防止乱码:
2、编写一个自定义的校验器
编写的校验器就是自定义注解 @Constraint(validatedBy = {})//用什么校验器来校验 中validatedBy 所需要的值
在idea中我们可以 Ctrl+左击 的方式查看参数的类型,如下:
再Ctrl+左击 ConstraintValidator查看发现其是个接口,由此我们自定义的校验器必须是一个或多个实现 ConstraintValidator的类,然后我们重写方法实现自己的业务需求
具体校验器代码:
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.HashSet;
import java.util.Set;
/**
* 自定义的校验器
*
* @author 江南大学1033190417
* @date 2022/6/7 1:11
*/
//ConstraintValidator<ListValue,Integer>: 值1:自定义接口,值2:需要校验的数据类型 意思来源可以在ConstraintValidator的解释中看到
public class ListValueConstraintValidator implements ConstraintValidator<ListValue, Integer> {
private Set<Integer> set = new HashSet<>();
//初始化方法
@Override
public void initialize(ListValue constraintAnnotation) {
int[] vals = constraintAnnotation.vals();
for (int val : vals) {
set.add(val);
}
}
//判断是否校验成功
/**
*
* @param value 需要校验的值
* @param context 上下文环境
* @return
*/
@Override
public boolean isValid(Integer value, ConstraintValidatorContext context) {
return set.contains(value);
}
}
3、关联自定义注解和自定义校验器
在自定义注解的 @Constraint(validatedBy={}) 中添加校验器
扩:一些其他的校验器,在idea中在 ConstraintValidator 上Ctrl+h可以查看其所有实现
![](https://i-blog.csdnimg.cn/blog_migrate/fe0a1c94d4d0c2c2c796f02cb68632ab.png)
例如
![](https://i-blog.csdnimg.cn/blog_migrate/560888ec4f05e79bd1ab1029eb296553.png)
大意:@Negative 这个注解可以用于校验数字是否为负数