el-form的表单校验
- <el-form :model="ruleForm" status-icon :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
- <el-form-item label="密码" prop="pass">
- <el-input type="password" v-model="ruleForm.pass" autocomplete="off"></el-input>
- </el-form-item>
- <el-form-item label="确认密码" prop="checkPass">
- <el-input type="password" v-model="ruleForm.checkPass" autocomplete="off"></el-input>
- </el-form-item>
- <el-form-item label="年龄" prop="age">
- <el-input v-model.number="ruleForm.age"></el-input>
- </el-form-item>
- <el-form-item>
- <el-button type="primary" @click="submitForm('ruleForm')">提交</el-button>
- <el-button @click="resetForm('ruleForm')">重置</el-button>
- </el-form-item>
- </el-form>
- <script>
- export default {
- data() {
- var checkAge = (rule, value, callback) => {
- if (!value) {
- return callback(new Error('年龄不能为空'));
- }
- setTimeout(() => {
- if (!Number.isInteger(value)) {
- callback(new Error('请输入数字值'));
- } else {
- if (value < 18) {
- callback(new Error('必须年满18岁'));
- } else {
- callback();
- }
- }
- }, 1000);
- };
- var validatePass = (rule, value, callback) => {
- if (value === '') {
- callback(new Error('请输入密码'));
- } else {
- if (this.ruleForm.checkPass !== '') {
- this.$refs.ruleForm.validateField('checkPass');
- }
- callback();
- }
- };
- var validatePass2 = (rule, value, callback) => {
- if (value === '') {
- callback(new Error('请再次输入密码'));
- } else if (value !== this.ruleForm.pass) {
- callback(new Error('两次输入密码不一致!'));
- } else {
- callback();
- }
- };
- return {
- ruleForm: {
- pass: '',
- checkPass: '',
- age: ''
- },
- rules: {
- pass: [
- { validator: validatePass, trigger: 'blur' }
- ],
- checkPass: [
- { validator: validatePass2, trigger: 'blur' }
- ],
- age: [
- { validator: checkAge, trigger: 'blur' }
- ]
- }
- };
- },
- methods: {
-
- }
- }
- </script>
自定义校验器
- <el-form
- :model="dataForm"
- :rules="dataRule"
- ref="dataForm"
- @keyup.enter.native="dataFormSubmit()"
- label-width="140px"
- >
- </el-form>
- data() {
- return {
- visible: false,
- dataForm: {
- brandId: 0,
- name: "",
- logo: "",
- descript: "",
- showStatus: "",
- firstLetter: "",
- sort: "",
- },
- dataRule: {
- name: [{required: true, message: "品牌名不能为空", trigger: "blur"}],
- logo: [
- {required: true, message: "品牌logo地址不能为空", trigger: "blur"},
- ],
- descript: [
- {required: true, message: "介绍不能为空", trigger: "blur"},
- ],
- showStatus: [
- {
- required: true,
- message: "显示状态[0-不显示;1-显示]不能为空",
- trigger: "blur",
- },
- ],
- firstLetter: [
- {
- validator: (rule, value, callback) => {
- if (value == "") {
- callback(new Error("请输入首字母"));
- } else if (!(/^[a-zA-Z]$/).test(value)) {
- callback(new Error("请输入英文字母"));
- } 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"
- }],
- },
- };
- },
后端的校验注解:
代码:
- package com.atguigu.gulimall.product.entity;
-
- import com.atguigu.common.valid.AddGroup;
- import com.atguigu.common.valid.ListValue;
- import com.atguigu.common.valid.UpdateGroup;
- import com.baomidou.mybatisplus.annotation.TableId;
- import com.baomidou.mybatisplus.annotation.TableName;
-
- import java.io.Serializable;
- import java.util.Date;
-
- //import com.sun.istack.internal.NotNull;
- import lombok.Data;
- import org.hibernate.validator.constraints.URL;
-
- import javax.validation.constraints.*;
-
- /**
- * 品牌
- *
- * @author pansd
- * @email 1152777670@qq.com
- * @date 2022-02-23 16:02:02
- */
- @Data
- @TableName("pms_brand")
- public class PmsBrandEntity implements Serializable {
- private static final long serialVersionUID = 1L;
-
- /**
- * 品牌id
- */
- @TableId
- @Null(message = "新增时不能填写品牌id",groups = {AddGroup.class}) //实现分组检验;
- @NotNull(message = "修改时必须填写品牌id",groups = {UpdateGroup.class})
- private Long brandId;
- /**
- * 品牌名
- */
- @NotBlank(message = "品牌名不能为空",groups = {AddGroup.class,UpdateGroup.class}) //不能是一个空格,至少是一个非空字符;如果仅仅在此处标准,默认是不起作用的。得在controller@Valid//响应状态码为400,是校验不通过的。
- private String name;
- /**
- * 品牌logo地址
- */
- @URL //如果没有增加分组的校验,那么它的注解是不起作用的。@Validated({AddGroup.class})
- private String logo;
- /**
- * 介绍
- */
- private String descript;
- /**
- * 显示状态[0-不显示;1-显示]
- */
- @ListValue(vals = {0,1})
- private Integer showStatus;
- /**
- * 检索首字母
- */
- @Pattern(regexp = "^[a-zA-Z]$",message = "检索首字母必须是一个字母")
- private String firstLetter;
- /**
- * 排序
- */
- @Min(value = 0)
- @NotNull //sort字段是一个Integer字段,不能使用notEmpty来标注
- private Integer sort;
-
- }
注意:此时在实体类中增加的校验是不起作用的。需要在controller中配置@Valid才能使用
代码如下:
- @RequestMapping("/save2")
- public R save2(@Valid @RequestBody PmsBrandEntity brandEntity){
- pmsBrandService.save(brandEntity);
- return R.ok();
- }
此时,返回的错误信息较为杂乱,为了方便处理,需要返回统一的异常处理。
针对于某个接口进行特定的处理方式:
- @RequestMapping("/save")
- public R save(@Valid @RequestBody PmsBrandEntity pmsBrand, BindingResult bindingResult){ //获取校验结果的信息,从而对错误信息进行封装
- //在json后边,紧跟着一个校验的结果。BindingResult bindingResult,拿到校验的结果,就可以封装。
- boolean b = bindingResult.hasErrors(); //是否有错误
- if(b){
- Map<String,Object> map = new HashMap<>();
- //获取校验数据的结果
- bindingResult.getFieldErrors().forEach((item)->{
- //获取校验字段的名字
- String field = item.getField();
- //获取校验信息
- String defaultMessage = item.getDefaultMessage();
- map.put(field,defaultMessage);
- });
- return R.error(400,"提交的数据不合法!").put("data",map);
- }
- pmsBrandService.save(pmsBrand);
- return R.ok();
- }
全局进行处理,代码如下:
- @RequestMapping("/save2")
- public R save2(@Valid @RequestBody PmsBrandEntity brandEntity){
- pmsBrandService.save(brandEntity);
- return R.ok();
- }
-
- package com.atguigu.gulimall.product.exception;
-
- import com.atguigu.common.exception.BizCodeEnum;
- import com.atguigu.common.utils.R;
- import lombok.extern.slf4j.Slf4j;
- 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 pshdhx
- * @date 2022-03-04 11:12
- * @Des 统一标准来处理异常的
- */
- @Slf4j
- //@ControllerAdvice
- //@ResponseBody
- @RestControllerAdvice(basePackages = "com.atguigu.gulimall.product.controller")
- public class PshdhxGuliControllerAdvice {
-
- @ExceptionHandler(value = MethodArgumentNotValidException.class)
- public R handleValidException(MethodArgumentNotValidException e){
- BindingResult bindingResult = e.getBindingResult();
- Map<String,Object> map = new HashMap<>();
- bindingResult.getFieldErrors().forEach(item->{
- //...
-
- //获取校验字段的名字
- String field = item.getField();
- //获取校验信息
- String defaultMessage = item.getDefaultMessage();
- map.put(field,defaultMessage);
- });
- log.error("数据校验出现问题{},异常类型{}",e.getMessage(),e.getClass());
- return R.error(BizCodeEnum.VAILD_EXCEPTION.getCode(),BizCodeEnum.VAILD_EXCEPTION.getMsg()).put("data",map);
- //return R.error(BizCodeEnum.VAILD_EXCEPTION.getCode(),BizCodeEnum.VAILD_EXCEPTION.getMsg()).put("data",map);
-
- }
-
- @ExceptionHandler(value = Throwable.class)
- public R handleException(Throwable throwable){
- log.error("错误:",throwable);
- return R.error(BizCodeEnum.UNKNOW_EXCEPTION.getCode(),BizCodeEnum.UNKNOW_EXCEPTION.getMsg());
- }
- }
为了统一自定义异常编码,指定了枚举类型。
- package com.atguigu.common.exception;
-
- /**
- * @author pshdhx
- * @date 2022-03-04 11:25
- */
- public enum BizCodeEnum {
- UNKNOW_EXCEPTION(10000,"系统未知异常"),
- VAILD_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;
- }
- }
结果如下:
比如说id这个字段,在新增时,不需要它;在修改时,必须要它,那么就需要对其进行分组处理
- @Data
- @TableName("pms_brand")
- public class PmsBrandEntity implements Serializable {
- private static final long serialVersionUID = 1L;
-
- /**
- * 品牌id
- */
- @TableId
- @Null(message = "新增时不能填写品牌id",groups = {AddGroup.class}) //实现分组检验;
- @NotNull(message = "修改时必须填写品牌id",groups = {UpdateGroup.class})
- private Long brandId;
- package com.atguigu.common.valid;
-
- public interface AddGroup {
- }
- package com.atguigu.common.valid;
-
- public interface UpdateGroup {
- }
定义俩空接口即可。但是,要想使其生效,则必须在控制器中使用注解@Validated
- //实现分组校验,这是添加是要校验的内容
- @RequestMapping("/save4")
- public R save4(@Validated({AddGroup.class}) @RequestBody PmsBrandEntity brandEntity){
- pmsBrandService.save(brandEntity);
- return R.ok();
- }
但是,如果其他字段没有增加上相关的分组,则字段上的注释会失效。
我想让某个字段只输入0和1,需要自定义注解
- @ListValue(vals = {0,1})
- private Integer showStatus;
1、自定义校验规则
- package com.atguigu.common.valid;
- /*
- 自定义校验规则
- */
- 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.atguigu.common.valid.ListValue.message}";
-
- Class<?>[] groups() default { };
-
- Class<? extends Payload>[] payload() default { };
-
- int[] vals() default { };
- }
2、自定义校验器
- package com.atguigu.common.valid;
- /**
- * 自定义校验器
- */
-
- 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<>();
- //初始化方法
- @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、关联校验规则和校验器
- @Documented
- @Constraint(validatedBy = { ListValueConstraintValidator.class }) //关联
- @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
- @Retention(RUNTIME)
- public @interface ListValue {
4、校验信息定义
ValidationMessages.properties
com.atguigu.common.valid.ListValue.message=必须提交指定的值