Springboot项目javax.validation使用方法详解包含组合bean和list特殊情况无法使用_import javax.validation.constraints.notblank;_Angus博客的博客-程序员宅基地

技术标签: java  J2EE  validation  

 

javax.validation 是基于JSR-303标准开发出来的,使用注解方式实现,及其方便,但是这只是一个接口,没有具体实现。

Hibernate-Validator是一个hibernate独立的包,可以直接引用,他实现了javax.validation同时有做了扩展,比较强大。SpringBoot在内部集成了hibernate-validation,可以直接使用。

常用注解:

代码 说明
@Null 被注解的元素必须为null
@NotNull 被注解的元素必须不为null
@AssertTrue 被注解的元素必须为true
@AssertFalse 被注解的元素必须为false
@Min(value) 被注解的元素必须为数字,其值必须大于等于最小值
@Max(value) 被注解的元素必须为数字,其值必须小于等于最小值
@Size(max,min) 被注解的元素的大小必须在指定范围内
@Past 被注解的元素必须为过去的一个时间
@Future 被注解的元素必须为未来的一个时间
@Pattern 被注解的元素必须符合指定的正则表达式

bean

package me.yanand.pojo;
import javax.validation.constraints.Max;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
public class User {
  @NotBlank(message = "姓名不能为空")
  private String name;
  @NotNull(message = "年龄不能为空")
  @Max(value = 100,message = "年龄太大")
  private Integer age;
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public Integer getAge() {
    return age;
  }
  public void setAge(Integer age) {
    this.age = age;
  }

 controller

package me.yanand.controller;
import me.yanand.pojo.User;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
@RestController
public class TestController {
  @RequestMapping("/")
  String hello(@RequestBody @Valid User user, BindingResult bindingResult){
    if(bindingResult.hasErrors()){
      return bindingResult.getFieldError().getDefaultMessage();
    }
    return "ok";
  }
}

postman请求

@Valid 和 BindingResult 是一一对应的,如果有多个@Valid,那么每个@Valid后面跟着的BindingResult就是这个@Valid的验证结果,顺序不能乱

以上是基础实现参考的脚本之家代码  文章地址  https://www.jb51.net/article/185660.htm

然后特殊情况比如,多个bean组合的DTO,或者list存储的bean  发现@Valid失效了,无法起到作用,查询文章发现有多种方式可以实现

方法1:对List进行Wrapper

既然List不是JavaBean,那我们就把它封装成JavaBean,我们定义一个ListWrapper类如下:

package com.wyq.firstdemo.util;
 
import lombok.Getter;
import lombok.Setter;
 
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
 
@Setter
@Getter
public class ListWrapper<E> {
    @Valid
    private List<E> list;
 
    public ListWrapper() {
        list = new ArrayList<>();
    }
 
    public  ListWrapper(List<E> list) {
        this.list = list;
    }
 
}

同时修改一下controller对应的方法:

    // 使用包装类对list进行验证
    @PostMapping("/insert/all")
    public ServerResponse<String> insertList(@Valid @RequestBody ListWrapper<UserEntity> listWrapper, BindingResult bindingResult) {
        if(bindingResult.hasErrors()) {
            log.error(bindingResult.getFieldError().toString());
            return ServerResponse.createByErrorMessage(bindingResult.getFieldError().getDefaultMessage());
        }
 
        userService.insertList(listWrapper.getList());
        return ServerResponse.createBySuccess();
    }

这样相当于把list做了一层封装,,,。。。

方法2:使用@Validated+@Valid

在controller类上面增加@Validated注解,并且删除方法参数中的BindingResult bindingResult(因为这个参数已经没有用了,异常统一有controller返回了)

然后我们运行一下测试一下

可以看到可以对参数进行校验了,但还还有一个问题,那就是这个不是我们想要的返回格式,它controller自己返回的格式,所以我们需要做一个统一异常处理。这个不做过多解释

方法3:自定义一个List

先上代码后说明,先定义一个ValidList

package com.wyq.firstdemo.util;
 
 
import javax.validation.Valid;
import java.util.*;
 
public class ValidList<E> implements List<E> {
 
    @Valid
    private List<E> list;
 
    public ValidList() {
        this.list = new ArrayList<>();
    }
 
    public ValidList(List<E> list) {
        this.list = list;
    }
 
    public List<E> getList() {
        return list;
    }
 
    public void setList(List<E> list) {
        this.list = list;
    }
 
    @Override
    public int size() {
        return list.size();
    }
 
    @Override
    public boolean isEmpty() {
        return list.isEmpty();
    }
 
    ...
 
}

对比方法3和方法1,有没有觉得代码有点相似,新建一个类,并且让他实现List接口,使这个类即具有了JavaBean的特性,又具有了List的特性,比方法1简单优雅很多。

只需要把List换成ValidList就可以了,还不需要多统一异常处理。

特殊情况单个参数处理,这样基本上就不用写过多的非空判断的代码了。

在这里插入图片描述
 

参考文章:https://blog.csdn.net/qq_37209293/article/details/85613319

https://www.jb51.net/article/185660.htm

https://stackoverflow.com/questions/28150405/validation-of-a-list-of-objects-in-spring/36313615#36313615

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/onceing/article/details/110119877

智能推荐

Python-四则运算-蔡晓晴,杜婷萱-程序员宅基地

github链接:https://github.com/Amy-CC/Arithmetic-Operation一、需求  1.使用-n 参数控制生成题目的个数  2.使用-r 参数控制题目中数值(自然数、真分数和真分数分母)的范围  3.生成的题目中计算过程不能产生负数  4. 生成的题目中如果存在形如e1 ÷ e2的子表达式,那么其结果应是真分数。  5. 每道题目中出现的运算符个数不...

EXCEL实现一维转二维_excel offset 一维区域转变二维数组_catie。的博客-程序员宅基地

如图1中的一维表想要转换成二维表,该怎么实现呢?图1公式如下:{=INDEX(C:C:C:C,SMALL(IF($B1:1:1:B11=11=11=F2,ROW($1:$11),20),{1}))}INDEX索引函数,返回指定行、列的值:INDEX(数组或区域,行号,列号)SMALL函数,返回一组数据中的第K个数据值:SMALL(单元格区域或数组,K)ROW函数,返回指定单元格的行号:ROW(A1)=1COLUMN函数,返回指定单元格列号:COLUMN(B1)=2图2图3:小技巧-使用_excel offset 一维区域转变二维数组

Mybatis Generator最完整配置详解_mybatisgenerator-程序员宅基地

背景:通过mybatis插件自动生成代码是否要使用代码生成工具?有些声音说使用代码生成工具不好,理由诸如:会不利于个人学习成长,生成的代码不好,可能使得一些初学者望而却步!我要说,还是那句老话:工欲善其事必先利其器,善于使用工具可以大大提高工作效率,再现今社会效率就是王道。事情都是怎么简单怎么做,偷懒使社会进步。一些琐碎的事情,能交给工作去做就使用工具做,只有从琐碎的重复的劳动中摆脱出来..._mybatisgenerator

Unity数据的持久化保存 ☞ 二进制方式保存_柚子味的小柠檬的博客-程序员宅基地

Unity数据的持久化保存 ☞ 二进制方式保存要保存的数据using System.Collections;using System.Collections.Generic;using UnityEngine;[System.Serializable]//可序列号特性public class Save{ public List<int> livingTagetPositions = new List<int>(); public List<int> l

ROS探索总结(十四)——move_base(路径规划)-程序员宅基地

https://blog.csdn.net/hcx25909/article/details/9470297

android软键盘改为搜索,Android手机软键盘enter改为搜索-程序员宅基地

需求Android 搜索 把软键盘上的回车键改为搜索。当客户聚焦EditText时弹出键盘,键盘右下角示意为“搜索”按钮;当客户输入内容后,点击搜索按钮将进行关键词搜索,当客户没有输入内容点击搜索按钮,将收起键盘。实现(EditText)1、设置属性设置属性①:android:imeOptions="actionSearch",在该Editview取得焦点的时候将“回车”键改为“搜索”设置属性②a..._android 软键盘改搜索

随便推点

matlab 画散点图 不同标记,『echart散点图问题:如何在散点图中特别标出某一个特定的点,如[120,70]』散点图特殊点标记...-程序员宅基地

matlab中画散点图时怎样在每个点上标记符号?首先需要建立M文件写代码,由于是离散数据,计算保一维矩阵中,如示:%calculatethefirstlinex1=0:1:10;y1=x1.^2;由于要绘制散点图,所以不能用plot函数,该函数是绘制连续曲线的!要用stem函数代替,如下所示:%绘制离散点会填色,实心stem(x1,y1,'fill');当然也可以写成这样子:%绘制离散点空心,不填..._matlab散点图标记特殊点

Vue+Element组件el-table添加表头全选文字_就叫小黄好了鸭的博客-程序员宅基地

html部分: <el-table v-if="showTable" class="inter_table" :data="apiList.slice((currentPage-1)*pagesize,currentPage*pagesize)" style="width: 100% !important;" border @selection-change="handleSel

sklearn svm 调参_Python机器学习笔记:SVM(4)——sklearn实现-程序员宅基地

上一节我学习了SVM的推导过程,下面学习如何实现SVM,具体的参考链接都在第一篇文章中。对SVM的概念理清楚后,下面我们对其使用sklearn进行实现。1,Sklearn支持向量机库概述  我们知道SVM相对感知器而言,它可以解决线性不可分的问题,那么它是如何解决的呢?其思想很简单就是对原始数据的维度变换,一般是扩维变换,使得原样本空间中的样本点线性不可分,但是在变维之后的空间中样本点是线性可分的...

【MySQL】load data语句详解(一)-程序员宅基地

作者 罗小波沃趣科技高级MySQL数据库工程师 load data语句详解1、语法解析1.1. 必选子句或关键字1.2. 可选子句或关键字1.2.1. LOW_PR...

python基础面试常见题-程序员宅基地

1、为什么学习Python? Python是目前市面上,我个人认为是最简洁、最优雅、最有前途、最全能的编程语言,没有之一。2、通过什么途径学习的Python?通过自学,包括网上查看一些视频,购买一些相关专业的书籍。3、Python和Java、PHP、C、C#、C++等其他语言相比?Python:轻量级、易学、自由/开放源码软件、可移植性、支持面向对象、丰...

最佳调度问题(C语言)--回溯法-程序员宅基地

N后问题转载于: https://blog.csdn.net/qq_35524157/article/details/79048737 的JAVA版本题目描述有n个任务由k个可并行工作的机器完成。完成任务i需要的时间为Ti。找出完成这n个任务的最佳调度,使得完成全部任务的时间最少。用文件导入每个任务所需要的时间Ti解题思路回溯法是从初始状态出发,在隐式图中以深度优先的方式搜索问题的..._最佳调度问题