前台防君子,后端防小人。
为了我们服务器的安全性,我们要将传过来的数据进行第二次校验。
先导包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
其实springboot-web包已经包含了validation包。不过,如果没有导进去的,还是可以通过这个包来导一下。
这个主要是在实体类上面,加入你需要验证的,比如这个实体类
@Data
@TableName("pms_brand")
public class BrandEntity implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 品牌id
*/
@TableId
@NotNull(message = "修改必须指定品牌id",groups = {UpdateGroup.class})
@Null(message = "新增不能指定id",groups = {AddGroup.class})
private Long brandId;
/**
* 品牌名
*/
@NotBlank(message = "品牌名必须提交")
private String name;
/**
* 品牌logo地址
*/
@NotNull(groups = AddGroup.class)
@URL(message = "logo必须是一个合法的url地址",groups = {AddGroup.class,UpdateGroup.class})
private String logo;
/**
* 介绍
*/
private String descript;
/**
* 显示状态[0-不显示;1-显示]
*/
@NotNull(groups = {AddGroup.class, UpdateStatusGroup.class})
@ListValue(vals = {0,1},groups = {AddGroup.class, UpdateStatusGroup.class})
private Integer showStatus;
/**
* 检索首字母
*/
@Pattern(regexp = "^[a-zA-Z]$",message = "检索首字母必须是一个字母",groups = {AddGroup.class,UpdateGroup.class})
private String firstLetter;
/**
* 排序
*/
private Integer sort;
}
注意,加完这些注解还不是完结,只是开始。
需要在controller层,你具体要验证的字段上添加@Validated注解
如
@RequestMapping("/update")
public R update(@Validated(UpdateGroup.class)@RequestBody BrandEntity brand){
brandService.updateDateil(brand);
return R.ok();
}
统一异常处理
使用SpringMVC提供的ControllerAdivce
@Slf4j
@RestControllerAdvice
public class GulimallExceptionControllerAdvice {
@ExceptionHandler(value = MethodArgumentNotValidException.class)
public R handleVaildException(MethodArgumentNotValidException e){
log.error("数据校验出现问题{},异常类型: {}",e.getMessage(),e.getClass());
BindingResult bindingResult = e.getBindingResult();//获取到到错误校验的数据结果
Map<String,String> errormap = new HashMap<>();
//查看哪个方法哪个字段出现问题
bindingResult.getFieldErrors().forEach((fieldError)->{
errormap.put(fieldError.getField(),fieldError.getDefaultMessage());
});
return R.error(BizCodeEnume.VATLD_EXCEPTION.getCode(),BizCodeEnume.VATLD_EXCEPTION.getMsg()).put("data",errormap);
}
@ExceptionHandler(value = Throwable.class)
public R handleException(Throwable throwable){
log.error("错误:",throwable);
return R.error(BizCodeEnume.UNKNOW_EXCEPTION.getCode(),BizCodeEnume.UNKNOW_EXCEPTION.getMsg());
}
}
@ExceptionHandler(value = Throwable.class)
public R handleException(Throwable throwable){
log.error("错误:",throwable);
return R.error(BizCodeEnume.UNKNOW_EXCEPTION.getCode(),BizCodeEnume.UNKNOW_EXCEPTION.getMsg());
}
上面的BizCodeEnume是对一些错误消息的封装
有错误,直接按照这个来找就好
public enum BizCodeEnume {
UNKNOW_EXCEPTION(10000,"系统未知异常"),
VATLD_EXCEPTION(10001,"参数格式校验失败"),
ROO_MANY_REQUEST(10003,"服务出现异常,请稍后再试"),
TOO_MANY_REQUEST(10008,"请求流量过大,请稍后再试"),
SMS_CODE_EXCEPTION(10004,"验证码获取频率太高,请稍后再试"),
PRODUCT_UP_EXCEPTION(11000,"商品上架异常"),
USER_EXIST_EXCEPTION(15001,"用户已存在"),
PHONE_EXIST_EXCEPTION(15002,"手机号已存在"),
NO_STOCK_EXCEPTION(21000,"商品库存不足"),
LOGINACCT_PASSWORD_INVAILD_EXCEPTION(15003,"账号密码错误");
private Integer code;
private String msg;
BizCodeEnume(Integer code, String msg){
this.code = code;
this.msg = msg;
}
public Integer getCode() {
return code;
}
public String getMsg() {
return msg;
}
}
分组校验
在字段上指定具体分组
只有到你这个分组的时候,他才会进行校验。
如,这个实体类的字段
@NotNull(message = "修改必须指定品牌id",groups = {UpdateGroup.class})
@Null(message = "新增不能指定id",groups = {AddGroup.class})
private Long brandId;
可以先来几个分组接口。什么都不写就行,但一个接口。
然后Controller层调用的时候,可以有选择的添加分组。
如
@Validated(xxx.class)
@RequestMapping("/info/{brandId}")
public R info(@PathVariable("brandId") Long brandId){
BrandEntity brand = brandService.getById(brandId);
return R.ok().put("brand", brand);
}
@RequestMapping("/update")
public R update(@Validated(UpdateGroup.class)@RequestBody BrandEntity brand){
brandService.updateDateil(brand);
return R.ok();
}
只有调用到这个实体类中字段中包含的分组,它才会触发这个校验规则。
也就是update,会触发这个brandId的校验规则。
自定义校验
可以先点进去一个注解。看看它的结构
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(
validatedBy = {}
)
public @interface ListValue {
String message() default "{com.atguigu.common.valid.ListValue.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
int[] vals()default { };
}