目录
一、引子
二、如何优雅地校验参数
2.1 官方指导意见
2.2 注解用法说明
首页 Java java教程 Java如何实现优雅的参数校验

Java如何实现优雅的参数校验

May 19, 2023 pm 07:43 PM
java

一、引子

要对方法的参数进行校验,最简单暴力的写法是这个样子:

    public static void utilA(String a,BigDecimal b){
        if (StringUtils.isEmpty(a)){
            System.out.println("a不可为空");
            return;
        }
        if (b == null){
            System.out.println("b不可为空");
            return;
        }
        if (b.compareTo(BigDecimal.ZERO) != 1){
            System.out.println("b的取值范围不正确");
            return;
        }
        System.out.println("do something");
    }

这样做从功能角度来说一点问题也没有。

但是从代码的长期维护性上来说,代码复用率低,校验规则一旦多起来很难维护,而且怎么看怎么显得笨拙,对于有一点追求的工程师来说,这么一大坨还是挺难接受的。

虽然有一些诸如 Preconditions(com.google) 的解决方案,但很难适应所有的场景,用起来也没到非常得心应有的地步。

二、如何优雅地校验参数

Spring官方推荐的,语义清晰的优雅的方法级别校验(入参校验、返回值校验)

2.1 官方指导意见

Spring官方在SpringBoot文档中,关于参数校验(Validation)给出的解决方案是这样的:

@Service
@Validated
public class MyBean {
 
    public Archive findByCodeAndAuthor(@Size(min = 8, max = 10) String code,
            Author author) {
        ...
    }
 
}

Spring Boot 官网文档 《37. Validation》

也就是说,使用 JSR-303 规范,直接利用注解进行参数校验。

(JSR-303 是 JAVA EE 6 中的一项子规范,叫做 Bean Validation,官方参考实现是 Hibernate Validator)

2.2 注解用法说明

2.2.1.注解简介

对于简单类型参数(非Bean),直接在参数前,使用注解添加约束规则。注解如下所示:

@AssertTrue / @AssertFalse

验证适用字段:boolean

注解说明:验证值是否为true / false

@DecimalMax / @DecimalMin

验证适用字段:BigDecimal,BigInteger,String,byte,short,int,long

注解说明:验证值是否小于或者等于指定的小数值,要注意小数存在精度问题

@Digits

验证适用字段:BigDecimal,BigInteger,String,byte,short,int,long

注解说明:验证值的数字构成是否合法

属性说明:integer:指定整数部分的数字的位数。fraction: 指定小数部分的数字的位数。

@Future / @Past

验证适用字段:Date,Calendar

注解说明:验证值是否在当前时间之后 / 之前

属性说明:公共

@Max / @Min

验证适用字段:BigDecimal,BigInteger,String,byte,short,int,long

注解说明:验证值是否小于或者等于指定的整数值

属性说明:公共

注意事项:建议使用在Stirng,Integer类型,不建议使用在int类型上,因为表单提交的值为“”时无法转换为int

@NotNull / @Null

验证适用字段:引用数据类型

注解说明:验证值是否为非空 / 空

属性说明:公共

@NotBlank 检查约束字符串是不是Null还有被Trim的长度是否大于0,只对字符串,且会去掉前后空格.

@NotEmpty 检查约束元素是否为Null或者是EMPTY.

@NotBlank 与 @NotEmpty 的区别:空格(" ")对于 NotEmpty 是合法的,而 NotBlank 会抛出校验异常

@Pattern

验证适用字段:String

注解说明:验证值是否配备正则表达式

属性说明:regexp:正则表达式flags: 指定Pattern.Flag 的数组,表示正则表达式的相关选项。

@Size

验证适用字段:String,Collection,Map,数组

注解说明:验证值是否满足长度要求

属性说明:max:指定最大长度,min:指定最小长度。

@Length(min=, max=):专门应用于String类型

@Valid

验证适用字段:递归的对关联对象进行校验

注解说明:如果关联对象是个集合或者数组,那么对其中的元素进行递归校验,如果是一个map,则对其中的值部分进行校验(是否进行递归验证)

属性说明:无

@Range(min=, max=) 被指定的元素必须在合适的范围内

@CreditCardNumber信用卡验证

@Email 验证是否是邮件地址,如果为null,不进行验证,算通过验证。

@URL(protocol=,host=, port=,regexp=, flags=)

2.2.2使用

1.引入依赖

 <!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator -->
        <dependency>
            <groupId>org.hibernate.validator</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>6.1.5.Final</version>
        </dependency>

2.在对应字段上添加注解,方法被调用时,如果传入的实际参数与约束规则不符,会直接抛出 ConstraintViolationException ,表明参数校验失败。

import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotEmpty;
 
/**
 * @Author: wangxia
 * @Date: 2021/10/20 16:30
 */
public class TestPerson {
 
    @NotEmpty(message = "用户名不能为空")
    private String username;
 
    @Min(value = 0,message = "年龄不能小于0岁")
    @Max(value =150,message = "年龄不能大于150岁")
    private int age;
 
    public String getUsername() {
        return username;
    }
 
    public void setUsername(String username) {
        this.username = username;
    }
 
    public int getAge() {
        return age;
    }
 
    public void setAge(int age) {
        this.age = age;
    }
}

3..对于Bean类型的参数,在Bean内部的各个字段上面追加约束注解,然后在方法的参数前面添加 @Validated或@Valid注解即可。示例:

@RequestMapping("/")
@RestController
public class TestValidatController {
 
    @PostMapping("/testValid")
    public String testValid(@Validated @RequestBody TestPerson testPerson){
        return "测试成功";
    }
 
}

4.优雅捕获异常,这一步可以省略,但是请求时会直接返回,400的异常提示,不太优雅。

@ControllerAdvice
@ResponseBody 
public class MethodArgumentNotValidHandel {
 
 
    @ExceptionHandler(value=MethodArgumentNotValidException.class)
    public JSONObject MethodArgumentNotValidHandler(HttpServletRequest request,
                                                    MethodArgumentNotValidException exception) throws Exception
    {
        JSONObject result=new JSONObject();
        result.put("code","fail");
        JSONObject errorMsg=new JSONObject();
        for (FieldError error : exception.getBindingResult().getFieldErrors()) {
            errorMsg.put(error.getField(),error.getDefaultMessage());
        }
        result.put("msg",errorMsg);
        return result;
    }
 
}

添加优雅捕获的异常提示:

Java如何实现优雅的参数校验

未添加优雅捕获的异常提示:

Java如何实现优雅的参数校验

以上是Java如何实现优雅的参数校验的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

热门话题

Laravel 教程
1602
29
PHP教程
1505
276
比较Java框架:Spring Boot vs Quarkus vs Micronaut 比较Java框架:Spring Boot vs Quarkus vs Micronaut Aug 04, 2025 pm 12:48 PM

前形式摄取,quarkusandmicronautleaddueTocile timeProcessingandGraalvSupport,withquarkusoftenpernperforminglightbetterine nosserless notelless centarios.2。

键盘上的音量键无法正常工作 键盘上的音量键无法正常工作 Aug 05, 2025 pm 01:54 PM

First,checkiftheFnkeysettingisinterferingbytryingboththevolumekeyaloneandFn volumekey,thentoggleFnLockwithFn Escifavailable.2.EnterBIOS/UEFIduringbootandenablefunctionkeysordisableHotkeyModetoensurevolumekeysarerecognized.3.Updateorreinstallaudiodriv

Edge PDF查看器不起作用 Edge PDF查看器不起作用 Aug 07, 2025 pm 04:36 PM

testthepdfinanotherapptoderineiftheissueiswiththefileoredge.2.enablethebuilt inpdfviewerbyTurningOff“ eflblyopenpenpenpenpenpdffilesexternally”和“ downloadpdffiles” inedgesettings.3.clearbrowsingdatainclorwearbrowsingdataincludingcookiesandcachedcachedfileresteroresoreloresorelorsolesoresolesoresolvereresoreorsolvereresoreolversorelesoresolvererverenn

如何比较Java中的两个字符串? 如何比较Java中的两个字符串? Aug 04, 2025 am 11:03 AM

使用.equals()方法比较字符串内容,因为==仅比较对象引用而非内容;1.使用.equals()比较字符串值是否相等;2.使用.equalsIgnoreCase()进行忽略大小写的比较;3.使用.compareTo()按字典顺序比较字符串,返回0、负数或正数;4.使用.compareToIgnoreCase()进行忽略大小写的字典序比较;5.使用Objects.equals()或安全调用方式处理null字符串,避免空指针异常。总之,应避免使用==进行字符串内容比较,除非明确需要检查对象是否相

Python记录到文件示例 Python记录到文件示例 Aug 04, 2025 pm 01:37 PM

Python的logging模块可通过FileHandler将日志写入文件,首先调用basicConfig配置文件处理器和格式,如设置level为INFO、使用FileHandler写入app.log;其次可添加StreamHandler实现同时输出到控制台;进阶场景可用TimedRotatingFileHandler按时间分割日志,例如设置when='midnight'实现每日生成新文件并保留7天备份,需确保日志目录存在;建议使用getLogger(__name__)创建命名logger,生产

python pandas造型数据框架示例 python pandas造型数据框架示例 Aug 04, 2025 pm 01:43 PM

在JupyterNotebook中使用PandasStyling可实现DataFrame的美观展示,1.使用highlight_max和highlight_min高亮每列最大值(绿色)和最小值(红色);2.通过background_gradient为数值列添加渐变背景色(如Blues或Reds)以直观显示数据大小;3.自定义函数color_score结合applymap为不同分数区间设置文字颜色(≥90绿色,80~89橙色,60~79红色,

计算的属性与VUE中的方法 计算的属性与VUE中的方法 Aug 05, 2025 am 05:21 AM

computed有缓存,依赖不变时多次访问不重新计算,而methods每次调用都执行;2.computed适用于基于响应式数据的计算,methods适合需要参数或频繁调用但结果不依赖响应式数据的场景;3.computed支持getter和setter,可实现数据的双向同步,methods不支持;4.总结:优先使用computed以提升性能,当需要传参、执行操作或避免缓存时使用methods,遵循“能用computed就不用methods”的原则。

如何在Java加入一系列字符串? 如何在Java加入一系列字符串? Aug 04, 2025 pm 12:55 PM

使用String.join()(Java8 )是连接字符串数组最简单推荐的方法,直接指定分隔符即可;2.对于旧版本Java或需要更多控制时,可使用StringBuilder手动遍历并拼接;3.StringJoiner适用于需要前缀、后缀等更灵活格式的场景;4.使用Arrays.stream()结合Collectors.joining()适合在连接前对数组进行过滤或转换等操作;综上所述,若使用Java8及以上版本,大多数情况下应首选String.join()方法,语法简洁易读,而对于复杂逻辑则推荐

See all articles