目录
一、引子
二、如何优雅地校验参数
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工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
3 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

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

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

Java 中的平方根 Java 中的平方根 Aug 30, 2024 pm 04:26 PM

Java 中的平方根指南。下面我们分别通过例子和代码实现来讨论平方根在Java中的工作原理。

Java 中的完美数 Java 中的完美数 Aug 30, 2024 pm 04:28 PM

Java 完美数指南。这里我们讨论定义,如何在 Java 中检查完美数?,示例和代码实现。

Java 中的随机数生成器 Java 中的随机数生成器 Aug 30, 2024 pm 04:27 PM

Java 随机数生成器指南。在这里,我们通过示例讨论 Java 中的函数,并通过示例讨论两个不同的生成器。

Java中的Weka Java中的Weka Aug 30, 2024 pm 04:28 PM

Java 版 Weka 指南。这里我们通过示例讨论简介、如何使用weka java、平台类型和优点。

Java 中的史密斯数 Java 中的史密斯数 Aug 30, 2024 pm 04:28 PM

Java 史密斯数指南。这里我们讨论定义,如何在Java中检查史密斯号?带有代码实现的示例。

Java Spring 面试题 Java Spring 面试题 Aug 30, 2024 pm 04:29 PM

在本文中,我们保留了最常被问到的 Java Spring 面试问题及其详细答案。这样你就可以顺利通过面试。

突破或从Java 8流返回? 突破或从Java 8流返回? Feb 07, 2025 pm 12:09 PM

Java 8引入了Stream API,提供了一种强大且表达力丰富的处理数据集合的方式。然而,使用Stream时,一个常见问题是:如何从forEach操作中中断或返回? 传统循环允许提前中断或返回,但Stream的forEach方法并不直接支持这种方式。本文将解释原因,并探讨在Stream处理系统中实现提前终止的替代方法。 延伸阅读: Java Stream API改进 理解Stream forEach forEach方法是一个终端操作,它对Stream中的每个元素执行一个操作。它的设计意图是处

Java 中的时间戳至今 Java 中的时间戳至今 Aug 30, 2024 pm 04:28 PM

Java 中的时间戳到日期指南。这里我们还结合示例讨论了介绍以及如何在java中将时间戳转换为日期。

See all articles