首页 > 其他分享 >springboot+vue+element-ui实现前后端的全部校验

springboot+vue+element-ui实现前后端的全部校验

时间:2022-11-24 15:03:57浏览次数:53  
标签:vue springboot 校验 value element callback import com public


1、前端校验

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"
}],
},
};
},

 

2、JSR303后端校验

后端的校验注解:

springboot+vue+element-ui实现前后端的全部校验_vue.js

代码:

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 [email protected]
* @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();
}

 此时,返回的错误信息较为杂乱,为了方便处理,需要返回统一的异常处理。

3、校验的统一异常处理

针对于某个接口进行特定的处理方式:

@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;
}
}

 

结果如下: 

 

springboot+vue+element-ui实现前后端的全部校验_vue.js_02

4、JSR303后端分组检验

比如说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();
}

 但是,如果其他字段没有增加上相关的分组,则字段上的注释会失效。

5、JSR303自定义校验规则

我想让某个字段只输入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=必须提交指定的值

标签:vue,springboot,校验,value,element,callback,import,com,public
From: https://blog.51cto.com/u_15890333/5884001

相关文章

  • Vue:要求录入数据用户和登录用户不一致时不允许修改数据
    在做项目时遇到了一个问题:要求录入数据用户和登录用户不一致时不允许修改数据最开始的时候我想的很简单直接验证就行:(其他内容不展示,只展示按钮)<div> <buttonclass="bu......
  • 求超大文件上传方案( vue )
    ​ 前言:因自己负责的项目(jetty内嵌启动的SpringMvc)中需要实现文件上传,而自己对java文件上传这一块未接触过,且对Http协议较模糊,故这次采用渐进的方式来学习文件上传的......
  • element ui 中引入自定义的图标
    1.去iconfont里找到要用的图标并加入到项目中2.在项目页面点击项目设置 按如图修改3.修改后保存 下载到本地4.在main.js中引入下载的 iconfont.css(在i......
  • 一个Nginx部署多个vue前端项目总结
    摘要:近来接手了一个二次开发的前后端分离模式的项目,其中在前端项目的部署上需要让2个前端项目都部署到一个IP地址和端口下,那么我们这里就要用到Nginx了,接下来我们看看如何在......
  • Vue 评论@人功能实现
       <template><divclass="content-container"><el-dialog:title="title":visible.sync="dialogVisible"width="540px":appe......
  • vue table直接定位到指定元素
    vue+element中的表格,直接定位到指定的元素。需求:点击某一个节点,弹窗,直接定位到点击的节点,高亮并显示数据。<el-tableref="highTable":data="treeData"highli......
  • springboot整合Elasticsearch
    springboot   2.2.5.RELEASEElasticsearch   7.17.6Elasticsearch下载地址https://www.elastic.co/cn/downloads/elasticsearch还有个大概的对应版本图: ......
  • ValueError:only one element tensors can be converted to Python scalars解决办法
    问题描述深度学习初学者的我在使用pytorchdebug深度神经网络模型的时候,list,tensor,array之间的转化太复杂了,总是傻傻分不清。这次又遇到问题:ValueError:onlyoneelement......
  • [未解决] vue 重启电脑后项目报错,某个全局变量未定义
    问题昨天上班还运行得好好的,今天启动就报错了,无法进入系统。尝试删除node_modules和package-lock.json,重新npminstall,无效;再次重启电脑,无效;清除浏览器缓存,清除cook......
  • vue表单必填项前面添加红色*
    vue表单必填项前面添加红色*和提示信息1.效果图2.实现代码(1)from表单定义:rules="rules",:model="headerForm"(2)文本框或者下拉框定义:rules="rules.XXXX",prop="XX......