品牌管理前端页面校验功能
表单校验&自定义校验器
错误记录:启动第三方服务的时候报了个错
错误:
Error creating bean with name 'configDataContextRefresher' defined in class path resource
出现原因:版本冲突
解决方案:将cloud的版本改为Hoxton.SR12
测试品牌管理的新增功能
开关按钮需要动态绑定0/1而不是true/false
品牌新增成功之后,logo地址应显示图片而不是图片访问的路径
使用table的自定义模板
使用el-image组件显示图片
出现问题: el-image组件没有注入
解决方案: 将el-image组件注入进来
将其内容复制到项目的src\element-ui\index.js中,导入的内容:只要导入组件和使用组件即import和use
出现问题:有些组件找不到
解决方案: 将其删除
出现问题:contain为定义
解决方案:不需要动态绑定fit,将其写死
图片还是无法正常显示,使用el-image组件失败
改用原生的img来实现效果
新增功能改善,添加校验功能
默认的校验功能就是不能为空,显然,不符合我们需求 。其中,检索首字母必须是a-zA-Z中的一个并且个数只能是一个,排序必须是数字等等
为表单动态绑定校验规则
设置规则
required:true 即必须的,message:提示信息,trigger:触发条件 ,trigger:'blur'即失去焦点触发
自定义校验器
通过使用validator来自定义校验器
为检索首字母和排序自定义校验器
给sort和showStatus一个默认值
自定义校验器
测试
JSR303数据校验
JSR303是后端校验数据的一种规范
使用JSR303数据校验的步骤:
①导入SpringBoot整合JSR303的依赖
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-validation -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
常用JSR303注解的作用:
Bean Validation 中内置的constraint
Hibenate Validator中额外附加的 constriant
每个注解注释文档中都有其作用和适用类型,我们标记注解时可以参考注释文档
②为实体类字段标记注解
例如:品牌名不能是个空字符串,我们可以标记@NotEmpty并且可以自定义校验信息
message默认使用的是ValidationMessages_zh_CN.properties中的配置信息,我们可以自定义校验信息
③告诉SpringMVC我们要校验的实体类,通过使用@Valid,如果不使用此注解则我们标记的校验注解不会生效
进行一个测试,看校验注解是否生效
看到status:400就应该知道,这个是校验失败的报错信息。但是,响应体的信息显然并不符合我们的要求,没有错误提示
③使用BindingResult获取校验的信息
/**
* 保存
*/
@RequestMapping("/save")
//@RequiresPermissions("product:brand:save")
public R save(@Valid @RequestBody BrandEntity brand, BindingResult bindingResult){
if (bindingResult.hasErrors()){
Map<String,String> map=new HashMap<>();
// 获取所有的校验错误结果并且进行遍历
bindingResult.getFieldErrors().forEach((item)->{
// 1.获取校验错误的字段名
String name=item.getField();
//2.获取校验错误信息
String message=item.getDefaultMessage();
map.put(name,message);
});
return R.error(400,"提交数据不合法").put("data",map);
}else{
brandService.save(brand);
return R.ok();
}
}
为BrandEntity的属性设置校验注解
统一异常处理
上面讲述了普通校验,如果我们每个方法都写一个普通校验异常信息返回的方法,代码量将会很大。因此,我们需要将controller出现的异常统一处理。
①创建一个统一异常处理的异常类,可以处理任何异常
② 使用ControllerAdvice注解,该注解的作用就是处理controller抛出的异常,并且告诉SpringMVC处理那个包下的controller抛出的异常
③使用Exception注解,该注解的作用是指定处理那个异常类的异常,通过value属性指定
④ 使用Slf4j打印异常信息
将controller中BindingResult删除,因为BindingResult会接受异常对象,删除之后controller出现异常将会自动抛出异常对象
查看打印的log,获取到了精确的异常类
异常对象class org.springframework.web.bind.MethodArgumentNotValidException
将异常类的类型精确
⑤将异常信息以jason格式返回
由于每个处理异常的方法最后都是要以jason的格式返回,所以将ResponseBody注解标注在类上
最后,RestControllerAdvice=ResponseBody+ControllerAdvice
在实际开发中我们需要去定义一个通用的错误码,例如
1.错误码为5位数字
2.错误码前两位表示业务场景,后三位表示错误类型。例如:10001,10:通用 001:表示参数格式校验
3.光有错误码还不够,还需要错误信息,我们将错误信息以枚举类的形式定义
10:通用 11:商品 12:订单 13:购物车 14:物流
错误码首先是通用的,因此,在common模块中创建错误码枚举类
将统一异常处理类的进行修改
JSR3030分组校验(多场景的复杂校验)
分组校验的作用:在不同场景下校验的规则肯定是不同的,例如BrandId在新增场景下必须为Null由于主键自增而在修改情况下必须携带,分组属性的作用就是区分不同情况下的校验规则。
①在common中创建接口,无需实现,用于标识校验场景
② 使用注解中的group属性,标识校验的场景
③使用@Validated注解确定校验场景
测试:
排序字段未标识分组情况,因此,校验注解不生效。
说明:未标识分组情况的注解并不生效,只有在@Validated注解未标识group属性时生效
将排序字段标识校验场景
JSR303自定义校验注解
自定义注解的作用:showStatus属性的值要么0要么1,一种选择是使用正则表达式,但很多时候正则表达式并不能解决我们需求的校验功能,因此,需要自定义校验
自定义校验的步骤:
1.编写一个自定义注解
可以参考JSR303规范的注解,例如:NotNull
Target注解:用于指定此注解可以标记在什么位置
Retention注解:指定此注解的生命周期
Constraint注解:用于关联此注解和校验器
①导入自定义校验需要的依赖
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
②自定义注解首先要满足JSR303的规范,即要有message、groups、Payload三个属性
② 自定义注解
③编写一个配置文件,配置message默认信息
message默认是从以下这个配置文件获取默认信息的
我们可以自己编写一个配置文件
自定义信息可以在注解的message属性中自己编写
2.编写一个自定义校验器
①自定义校验器要实现ConstraintValidator接口,接口中的两个泛型分别指:需要校验的注解和注解需要校验的数据类型
因此,编写ZeroOrOne注解的校验器,第一个泛型指的是ZeroOrOne注解,第二泛型指的是需要校验的数据类型即Integer
编写ZeroOrOne注解的校验器
接口定义了两个方法,一个是初始化方法,一个是校验方法 。其中,初始化方法的参数是一个ZeroOrOne注解的对象也就可以获取对象的属性,校验方法的第一个参数就是传递进来需要校验的数据
完善校验器功能
public class ZeroOrOneConstraintValidator implements ConstraintValidator<ZeroOrOne,Integer> {
HashSet<Integer> set=new HashSet<>();
// 初始化方法
@Override
public void initialize(ZeroOrOne constraintAnnotation) {
ConstraintValidator.super.initialize(constraintAnnotation);
int[] arrs=constraintAnnotation.value(); // 获取value的值,这里是指0,1
for (int i:arrs){
set.add(i); // 将value的值封装进set中
}
}
// 返回校验是否正确的校验方法
@Override
public boolean isValid(Integer integer, ConstraintValidatorContext constraintValidatorContext) {
if (integer != null){ // 对integer进行一个非空判断
if (set.contains(integer)){ // 判断校验的数值是不是在set中
return true;
}else {
return false;
}
}else {
return false;
}
}
}
3.关联校验器和注解
说明: 目前我们只编写了对Integer数据的校验的校验器,如果需要对其它类型的数据进行校验的话,只需要编写相对应的校验器和进行注解和校验器关联即可,说直白一点就是你写了不同功能的校验器你往关联注解中加就行,至于用哪个校验器就不用我们操心了