SpringBoot整合validation数据校验

news2024/11/15 9:47:55

1. 首先引入依赖 

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>

点标识进去可以发现是通过Hibernate Validator使用 Java Bean Validation

2. 属性上添加校验注解

    @NotBlank(message = "姓名不能为空")
    private String username;

    @NotBlank(message = "密码不能为空")
    @Length(min = 6, max = 16, message = "密码长度为6-16位")
    private String password;

    @Pattern(regexp = "0?(13|14|15|17|18|19)[0-9]{9}", message = "手机号格式不正确")
    private String phone;

    @NotBlank(message = "邮箱不能为空")
    @Email(message = "邮箱格式不合理")
    private String email;

    // 嵌套验证必须加 @Valid,否则嵌套中的验证不生效,list中也算嵌套
    @Valid
    @NotNull(message = "userinfo不能为空")
    private UserInfo userInfo;

在方法入参上配合注解@Valid提供嵌套验证功能

public AjaxResult editSave(@Validated @RequestBody GenTable genTable) {

@Validated:用在方法入参上无法单独提供嵌套验证功能。不能用在成员属性(字段)上,也无法提示框架进行嵌套验证。

@Valid:用在方法入参上无法单独提供嵌套验证功能。能够用在成员属性(字段)上,提示验证框架进行嵌套验证。

3. Validation常用的校验注解

验证注解验证的数据类型说明
@AssertFalseBoolean,boolean验证注解的元素值是false
@AssertTrueBoolean,boolean验证注解的元素值是true
@NotNull任意类型验证注解的元素值不是null
@Null任意类型验证注解的元素值是null
@Min(value=值)BigDecimal,BigInteger, byte,short, int, long,等任何Number或CharSequence(存储的是数字)子类型验证注解的元素值大于等于@Min指定的value值
@Max(value=值)和@Min要求一样验证注解的元素值小于等于@Max指定的value值
@DecimalMin(value=值)和@Min要求一样验证注解的元素值大于等于@ DecimalMin指定的value值
@DecimalMax(value=值)和@Min要求一样验证注解的元素值小于等于@ DecimalMax指定的value值
@Digits(integer=整数位数, fraction=小数位数)和@Min要求一样验证注解的元素值的整数位数和小数位数上限
@Size(min=下限, max=上限)字符串、Collection、Map、数组等验证注解的元素值的在min和max(包含)指定区间之内,如字符长度、集合大小
@Pastjava.util.Date,java.util.Calendar;Joda Time类库的日期类型验证注解的元素值(日期类型)比当前时间早
@Future与@Past要求一样验证注解的元素值(日期类型)比当前时间晚
@NotBlankCharSequence子类型验证注解的元素值不为空(不为null、去除首位空格后长度为0),不同于@NotEmpty,@NotBlank只应用于字符串且在比较时会去除字符串的首位空格
@Length(min=下限, max=上限)CharSequence子类型验证注解的元素值长度在min和max区间内
@NotEmptyCharSequence子类型、Collection、Map、数组验证注解的元素值不为null且不为空(字符串长度不为0、集合大小不为0)
@Range(min=最小值, max=最大值)BigDecimal,BigInteger,CharSequence, byte, short, int, long等原子类型和包装类型验证注解的元素值在最小值和最大值之间
@Email(regexp=正则表达式,flag=标志的模式)CharSequence子类型(如String)验证注解的元素值是Email,也可以通过regexp和flag指定自定义的email格式
@Pattern(regexp=正则表达式,flag=标志的模式)String,任何CharSequence的子类型验证注解的元素值与指定的正则表达式匹配
@Valid任何非原子类型指定递归验证关联的对象如用户对象中有个地址对象属性,如果想在验证用户对象时一起验证地址对象的话,在地址对象上加@Valid注解即可级联验证

4. 校验方式

在Controller方法参数前加@Valid注解,校验不通过时直接抛异常。

了解其他校验方式:在Controller方法参数前加@Valid注解,参数后面定义一个BindingResult类型参数——执行时会将校验结果放进bindingResult里面,用户自行判断并处理。

/**
 * 将校验结果放进BindingResult里面,用户自行判断并处理
 *
 * @param userInfo
 * @param bindingResult
 * @return
 */
@PostMapping("/testBindingResult")
public String testBindingResult(@RequestBody @Valid UserInfo userInfo, BindingResult bindingResult) {
    // 参数校验
    if (bindingResult.hasErrors()) {
        String messages = bindingResult.getAllErrors()
                .stream()
                .map(ObjectError::getDefaultMessage)
                .reduce((m1, m2) -> m1 + ";" + m2)
                .orElse("参数输入有误!");
        //这里可以抛出自定义异常,或者进行其他操作
        throw new IllegalArgumentException(messages);
    }
    return "操作成功!";
}

或者使用工具类,用户手动调用对应API执行校验,这种方法适用于校验任意一个有valid注解的实体类,并不仅仅是只能校验接口中的参数;

import org.springframework.util.CollectionUtils;

import javax.validation.ConstraintViolation;
import javax.validation.Valid;
import javax.validation.Validation;
import java.util.Set;

/**
 * 手动调用api方法校验对象
 */
public class MyValidationUtils {
    public static void validate(@Valid Object value) {
        Set<ConstraintViolation<@Valid Object>> validateSet = Validation.buildDefaultValidatorFactory()
                .getValidator()
                .validate(value);
        if (!CollectionUtils.isEmpty(validateSet)) {
            String messages = validateSet.stream()
                    .map(ConstraintViolation::getMessage)
                    // 归约实现字符串合并
                    .reduce((m1, m2) -> m1 + ";" + m2)
                    .orElse("参数输入有误!");
            throw new IllegalArgumentException(messages);
        }
    }
}

5. 全局异常处理器

@RestControllerAdvice //把信息转成json格式返回
public class GlobalExceptionHandler
{
    private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    /**
     * 请求方式不支持
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public AjaxResult handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException e,
            HttpServletRequest request)
    {
        String requestURI = request.getRequestURI();
        log.error("请求地址'{}',不支持'{}'请求", requestURI, e.getMethod());
        return AjaxResult.error(e.getMessage());
    }

    /**
     * 拦截未知的运行时异常
     */
    @ExceptionHandler(RuntimeException.class)
    public AjaxResult handleRuntimeException(RuntimeException e, HttpServletRequest request)
    {
        String requestURI = request.getRequestURI();
        log.error("请求地址'{}',发生未知异常.", requestURI, e);
        return AjaxResult.error(e.getMessage());
    }

    /**
     * 系统异常
     */
    @ExceptionHandler(Exception.class)
    public AjaxResult handleException(Exception e, HttpServletRequest request)
    {
        String requestURI = request.getRequestURI();
        log.error("请求地址'{}',发生系统异常.", requestURI, e);
        return AjaxResult.error(e.getMessage());
    }

    /**
     * 自定义验证异常
     */
    @ExceptionHandler(BindException.class) //作用于 @Validated @Valid 注解,仅对于表单提交有效,对于以json格式提交将会失效。
    public AjaxResult handleBindException(BindException e)
    {
        log.error(e.getMessage(), e);
        String message = e.getAllErrors().get(0).getDefaultMessage();
        return AjaxResult.error(message);
    }

    /**
     * 自定义验证异常
     */
    @ExceptionHandler(MethodArgumentNotValidException.class) //作用于 @Validated @Valid 注解,前端提交的方式为json格式有效
    public Object handleMethodArgumentNotValidException(MethodArgumentNotValidException e)
    {
        log.error(e.getMessage(), e);
        String message = e.getBindingResult().getFieldError().getDefaultMessage();
        return AjaxResult.error(message);
    }

    /**
     * 自定义验证异常
     */
    @ExceptionHandler(ConstraintViolationException.class) //作用于 @NotBlank @NotNull @NotEmpty 注解,校验单个String、Integer、Collection等参数异常处理。
    public Object handleConstraintViolationException(ConstraintViolationException e)
    {
        log.error(e.getMessage(), e);
        String message = e.getConstraintViolations()
        .stream()
        .map(ConstraintViolation::getMessage)
        .collect(Collectors.joining("; "));
        return AjaxResult.error(message);
    }

}

6. 自定义xss校验注解

自定义注解 

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 自定义xss校验注解
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(value = { ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.PARAMETER })
@Constraint(validatedBy = { XssValidator.class })
public @interface Xss
{
    String message()

    default "不允许任何脚本运行";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
}

实现ConstraintValidator接口 

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 自定义xss校验注解实现
 */
public class XssValidator implements ConstraintValidator<Xss, String>
{
    private static final String HTML_PATTERN = "<(\\S*?)[^>]*>.*?|<.*? />";

    @Override
    public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext)
    {
        if (value == null && value.equals("") && value.equals(" "))
        {
            return true;
        }
        return !containsHtml(value);
    }

    public static boolean containsHtml(String value)
    {
        Pattern pattern = Pattern.compile(HTML_PATTERN);
        Matcher matcher = pattern.matcher(value);
        return matcher.matches();
    }
}
    @Xss(message = "用户账号不能包含脚本字符")
    @NotBlank(message = "用户账号不能为空")
    @Size(min = 0, max = 30, message = "用户账号长度不能超过30个字符")
    public String getUserName() {
        return userName;
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1273376.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

中伟视界:AI盒子中的报警预录像功能能解决什么问题?实现原理是怎样的?

现代社会智能安防已成为各行各业的重要一环&#xff0c;而AI盒子中的报警预录像功能更是智能安防的一大利器。这一功能能够解决很多安防方面的难题&#xff0c;其实现原理更是技术创新的体现。 首先&#xff0c;让我们来看看AI盒子中的报警预录像功能能解决哪些问题。在传统的安…

基于PHP的校园兼职系统的设计与开发

基于PHP的校园兼职系统的设计与开发 摘要&#xff1a;从古代至今&#xff0c;教育都是国家培养人才的手段&#xff0c;在古代教育往往都是课堂式教育&#xff0c;在课堂内老师教导学生学习&#xff0c;而随着时间的推移&#xff0c;越来越多的在校大学生已经不满足于只在课堂上…

dapper+mysql查询报Error parsing column 0 (Id=<null>)

之前的分页接口都是正常的&#xff0c;突然就报错了Error parsing column 0 (Id<null>) {"error": {"code": null,"message": "Error parsing column 0 (Id<null>)","details": "DataException: Error pa…

vue.js ——Vuex

基本概念 vue进行开发过程中有没有遇到这样一种场景&#xff0c;就是有些时候一些数据是一种通用的共享数据&#xff08;比如登录信息&#xff09;&#xff0c;那么这类数据在各个组件模块中可能都会用到&#xff0c;如果每个组件中都去后台重新获取那么势必会造成性能浪费&am…

R语言30分钟入门

1. 环境&安装 R是支持win、linux合macos的 完整参考&#xff1a;https://zhuanlan.zhihu.com/p/596324321?utm_id0 主要是安装&#xff1a;1、R环境&#xff1b;2、rstudio开发环境&#xff08;后面主要是用rstudio&#xff0c;也可以用vscode&#xff09; 1.1. rstud…

异常 Exception 02

异常 Exception 02 六、异常处理1、基本介绍2、异常处理的方式3、示意图 try-catchthrows1、介绍2、注意事项 自定义异常1、基本概念2、自定义异常的步骤3、实例4、throw和throws的区别 六、异常处理 1、基本介绍 异常处理就是当异常发生时,对异常处理的方式。 2、异常处理的…

佳易王物流快运物流单打印登记查询系统软件操作教程

一、前言&#xff08;编程应用实例系列&#xff09;&#xff1a; 佳易王物流快运物流单打印登记查询系统软件操作教程 软件有试用版&#xff0c;可以下载试用&#xff0c;了解软件操作和软件功能。 软件试用版下载可以点击最下方官网卡片 软件为绿色免安装版&#xff0c;下载…

2023-简单点-yolox-pytorch代码解析(二)-nets/yolo.py

yolox-pytorch&#xff1a;nets/yolo.py yolox网络结构yolox-pytorch目录今天解析注释nets/yolo.py yolox网络结构 yolox-pytorch目录 nets目录 今天解析注释nets/yolo.py import torch import torch.nn as nnfrom .darknet import BaseConv, CSPDarknet, CSPLayer, DWConv##…

各种与梅洛相关的葡萄酒知识

梅洛葡萄是可以通过其松散的大浆果串来识别的&#xff0c;与赤霞珠葡萄相比&#xff0c;这种颜色的蓝色/黑色调更少&#xff0c;皮肤更薄&#xff0c;单宁更少。与赤霞珠相比&#xff0c;梅洛葡萄的糖含量往往更高&#xff0c;苹果酸含量较低。梅洛在寒冷的土壤中茁壮成长&…

【云原生系列】Kubernetes知识点

目录 概念 基础架构 单master节点 多master节点 组件 Master节点核心组件 其他组件 请求发送流程 插件 核心资源 调度资源 Pod 创建pod组件间调用流程 pod生命周期&#xff1a; 初始化容器 镜像拉取策略 重启策略 钩子函数 探针 探针的实现方式 DownwardAP…

【Qt基础之QPalette实例电子时钟】

# 简介 借助`QLCDNumber`实现电子时钟,可以随意拖拽到桌面任意位置,鼠标右键进行关闭,用于实践`QPalette`类、`QTimer`的使用以及`mousePressEvent`\`mouseMoveEvent`\`mouseDoubleClickEvent`事件处理函数的使用。可在此基础上扩展其他应用,参看Qt帮助手册。 # QPalette …

画中画视频剪辑:批量制作画中画,提升视频制作技能

在视频制作过程中&#xff0c;画中画是一种常见的视觉效果&#xff0c;它能够使多个视频片段在同一画面中展示&#xff0c;增加信息的丰富度和视觉的吸引力。这种效果通常用于增加信息的丰富度&#xff0c;如在新闻节目中&#xff0c;同时展示主持人和采访对象的画面。画中画也…

windows下使用iperf3

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、使用步骤1.下载2.解压3.测试1.作为服务器使用2.作为客户端使用 总结 前言 windows使用iperf3和linux是一样的&#xff0c;而且可以相互操作。 一、使用步骤…

Java最难的语法<泛型>

时间过得很快&#xff0c;我们马上就进入了&#xff0c;Java最难语法的学习&#xff0c;加油吧&#xff01; 1.包装类 想要学好泛型就要了解包装类。 在Java中&#xff0c;由于基本类型不是继承自Object&#xff0c;为了在泛型代码中可以支持基本类型&#xff0c;Java给每个…

Python入门06布尔值

目录 1 什么是布尔值2 怎么生成布尔值3 在控制程序中使用布尔值4 数据过滤、排序和其他高级操作总结 1 什么是布尔值 首先我们要学习一下布尔值的定义&#xff0c;布尔值是一种数据类型&#xff0c;它只有两个可能的值&#xff1a;True&#xff08;真&#xff09;或 False&…

scikit-opt几种数值模拟退火的代码示例,和参数详解,以及基础模拟退火的原理代码示例

python基础模拟退火原理示例 模拟退火的特性决定了一般可以用于算法的调参&#xff0c;相比较遗传算法来说&#xff0c;普遍更快一些&#xff0c;但是也更容易陷入局部最优。相对来说&#xff0c;遗传算法的更新解机制是在最每一个局部最优解附近盘旋游荡&#xff0c;则更容易…

View绘制

onDraw 绘制 canvas 画布 paint 画笔 坐标系 x y x 0 y 0 则屏幕左上角 y从上往下值增加 像素转换 dp2px 画线line drawLine 圆circle drawCircle drawPath: 在onSizeChanged 时候初始化 addCircle 添加圆 CW顺时针 CCW 逆时针 CW CCW填充规则不同 填充规则: 默认 …

NX二次开发UF_MTX2_vec_multiply_t 函数介绍

文章作者&#xff1a;里海 来源网站&#xff1a;https://blog.csdn.net/WangPaiFeiXingYuan UF_MTX2_vec_multiply_t Defined in: uf_mtx.h void UF_MTX2_vec_multiply_t(const double vec [ 2 ] , const double mtx [ 4 ] , double vec_product [ 2 ] ) overview 概述 Ret…

邮政快递物流查询,将指定某天签收的单号筛选出来

批量查询邮政快递单号的物流信息&#xff0c;将指定某天签收的单号筛选出来。 所需工具&#xff1a; 一个【快递批量查询高手】软件 邮政快递单号若干 操作步骤&#xff1a; 步骤1&#xff1a;运行【快递批量查询高手】软件&#xff0c;并登录 步骤2&#xff1a;点击主界面左…

python-nmap库使用教程(Nmap网络扫描器的Python接口)(功能:主机发现、端口扫描、操作系统识别等)

文章目录 Python-nmap库使用教程前置条件引入python-nmap创建Nmap扫描实例执行简单的主机发现&#xff08;nmap -sn&#xff09;示例&#xff0c;我有一台主机配置为不响应 ICMP 请求&#xff0c;但使用nmap -sn&#xff0c;仍然能够探测到设备&#xff1a; 端口扫描扫描特定端…