66
1、保存修改页面中更改显示状态信息。激活为1,不激活为0
在 <el-switch> 中,:active-value="1" :inactive-value="0"
2、logo上传成功后,在主页显示数据栏显示图片。用插槽,
<template slot-scope="scope">
	<img :src="scope.row.logo" style="width:100px; height:80px">
</template>
        3、表单自定义校验器。要求:首字母是一个字母,排序字段为数字
	firstLetter: [
          {
            validator: (rule, value, callback) => {
              if (value === "") {
                callback(new Error("首字母不能为空"));
              } else if (!/^[a-zA-z]$/.test(value)) {
                callback(new Error("首字母必须在a-z或者A-Z之间"));
              } else {
                callback();
              }
            },
            trigger: "blur",
          },
        ],
        sort: [{ validator: (rule, value, callback) => {
              if (value === "") {
                callback(new Error("排序不能为空"));
              } else if (!Number.isInteger(value) || value<0) {
                callback(new Error("排序必须不小于0"));
              } else {
                callback();
              }
            }, trigger: "blur" }],
而且改动 <el-input v-model.number=".....">
        4、默认显示状态是1,排序是0。
67 JSR303数据校验
1、导入注解时,注解所在的包名(防止导入错包):
输入查找 @NotNull 查看所在位置:javax.validation.constraints
2、
@NotNull 不能为空,must not be null。支持所有类型
@NotEmpty 不能为空且不能为empty。支持集合类,Array、Collection、Map、字符串CharSequence
@NotBlank 不能为空且至少包含一个字符。支持字符串CharSequence
        也就是 private Integer sort;要求不为空时,必须只能是 @NotNull
3、
(1)给bean添加校验注解,并定义自己的message提示,如 @Email @NotNull
要求:
首字母
@NotBlank
@Pattern(regexp = "^[a-zA-Z]$")
品牌名
@NotBlank
logo地址
@NotBlank
@URL(message = "logo必须是一个合法的URL地址")
排序 
@NotNull
@Min(value = 0, message = "排序必须大于等于0")
        (2)在controller里面方法保存数据时,开启校验功能。(@Valid...)
 效果:校验错误以后会有默认的相应
public R save(@Valid @RequestBody BrandEntity brand, BindingResult result)
        (3)在参数后加,给校验后的Bean紧跟 BindingResult result ,就可以获得校验的结果
		if(result.hasErrors()){
            Map<String, String> map =  new HashMap<>();
            result.getFieldErrors().forEach(item ->{
                // 获取校验结果错误的属性名和错误信息
                String message = item.getDefaultMessage();
                String field = item.getField();
                map.put(field, message);
            });
            return R.error(400, "提交数据不合法").put("data",map);
        }else {
            brandService.save(brand);
            return R.ok();
        }
        68 统一异常处理
1、将controller方法内BindingResult 和异常处理部分删除,但是@Valid字段要保留
2、在common模块,建立valid软件包,BizCodeEnum枚举类型。每个不同类型用逗号。
	UNKNOWN_EXCEPTION(10000,"系统未知异常"),
    VALID_EXCEPTION(10001,"参数格式校验异常");
    private int code;
    private String msg;
    BizCodeEnum(int code, String msg){
        this.code = code;
        this.msg = msg;
    }
    public int getCode() {
        return code;
    }
    public String getMsg() {
        return msg;
    }
        3、同controller建包exception,建类 GulimailExceptionHandleAdvice.class,注意命名规则。
类名上写由springMvc提供得到@ControllerAdvice处理
---->log打印,类名添加@SLF4j
----->返回类型以json形式,类名添加 @ResponseBody
------>ResponseBody + ControllerAdvice = RestControllerAdvice
        ExceptionHandler 感知报错,初始用 Exception.class
初始不知道error具体类型,通过打印 log.error("报错信息为{},异常类型为{}", e.getMessage(), e.getClass())获取
得到具体的类型后,发现 e 有了方法 getBindingResult()。同之前写法。
	@ExceptionHandler(value = MethodArgumentNotValidException.class)
    public R handleValidException(MethodArgumentNotValidException e){
        BindingResult bindingResult = e.getBindingResult();
        HashMap<String, String> map = new HashMap<>();
        bindingResult.getFieldErrors().forEach(item->{
            map.put(item.getField(), item.getDefaultMessage());
        });
        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.UNKNOWN_EXCEPTION.getCode(), BizCodeEnum.UNKNOWN_EXCEPTION.getMsg());
    }
        69 JSR303分组校验
品牌id在新增时默认自增,无需提交;但在修改时要求不为空。有不同的要求。
像logo、首字母、排序,新增时不为空,但在修改时允许未更改的数据不进行提交。
用途:标注什么情况下进行校验。
若它没有被分组会怎么样呢?是所有情况都被校验吗? nonono!默认不起作用
        1、注解存在参数 groups
2、在common模块,valid软件包下新建 AddGroup 和 UpdateGroup 接口
3、方法save中写明@Validated({AddGroup.class}),同理update
70 自定义校验器
功能:为显示状态定义ListValue(vals={0,1})只允许保存0和1
校验注解需要满足规范,3个属性 + 元信息数据
3个属性
1、String message() default "{com.atguigu.common.valid.ListValue.message}";
出错时的提示信息。需要创建配置文件,自定义配置信息。同名ValidationMessages.properties。
若提示信息文件格式错误,需要删除该文件,取消勾选。在设置----编辑器----文件编码----将properties改为UTF形式,并自动展现。
2、Class<?>[] groups() default { };
支持分组。
3、Class<? extends Payload>[] payload() default { };
自定义负载信息。需要导入
 		<dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>2.0.1.Final</version>
        </dependency>
        额外再加一个int数组 int[] vals() default { };
元信息数据
@Constraint(validatedBy = {ListValueConstraintValidator.class })
使用哪一个校验器获取,可以指定多个不同的校验器,适配不同类型的校验。
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
标注位置。方法、属性、构造器、参数
@Retention(RUNTIME)
时机,运行时获取到
@Repeatabel(List.class)
可重复注解
自定义校验器
class ListValueConstraintValidator implements ConstraintValidator<ListValue,Integer>
        继承接口,泛型指定注解和校验什么类型数据。
初始化方法 initialize
int[] vals = constraintAnnotation.vals();
        for (int val:vals){
            set.add(val);
        }
        判断是否校验成功 isValid
return set.contains(integer);
        自定义私有Set
   private Set<Integer> set = new HashSet<>();
        额外的,在java指定正则时,即检索首字母,^[a-zA-Z]$,不出现后面的\
因为修改update需要提交品牌名,可在修改状态给一个快速修改的方法,无需品牌名,只品牌ID和显示状态。
新增分组 UpdataStatusGroup.class
@NotNull(groups = {AddGroup.class,UpdataStatusGroup.class})
@ListValue(vals={0,1}, groups = {AddGroup.class,UpdataGroup.class, UpdataStatusGroup.class})
private Integer showStatus;
        并在前端页面 updateBrandStatus修改发送请求