javax.validation.Valid 优雅校验数据

使用javax.validation进行优雅的数据校验
文章介绍了在接口开发中如何利用javax.validation.Valid进行数据校验,以避免手动编写臃肿的校验代码。它提到了对于单个对象和列表集合两种情况的处理方式,通过@Valid注解可以方便地进行校验,并展示了如何处理校验错误。

如何优雅的数据校验

序:最近做接口开发,需要做一些校验,但如果手写代码校验,代码臃肿不说,还不是很好维护,于是在网上搜索了一下,发现javax.validation.Valid 很好的解决了这个问题。且单个对象和list集合对象有不同的用法,下面就分别说一下。

1、单个对象

@RequestBody @Valid 通过@Valid 修饰 controller如下

public IfcResponseData cx(@RequestBody @Valid ZcVlRCxMidT ZcVlRCxMidT, BindingResult result, HttpServletRequest request)  

对象属性需要用不同注解修饰

@NotNull(message = "车型编码不能为空")
private String carType;
@NotNull(message = "车型简称不能为空")
private String abbreviation;

具体crontroller和对象

    @RequestMapping(value = "/cx",
            method = {RequestMethod.GET, RequestMethod.POST}, produces = "application/json;charset=UTF-8")
    @ResponseBody
    public IfcResponseData cx(@RequestBody @Valid ValidableList<ZcVlRCxMidT> records, BindingResult result, HttpServletRequest request) {
        IExtensionRequest createExtensionRequestContext = createRequestContext(request);
        if(result.hasErrors()){
            String defaultMessage = result.getFieldError().getDefaultMessage();
            IfcResponseData ifcResponseData = new IfcResponseData(defaultMessage);
            return ifcResponseData;
        }
        return vlPubAcceptService.cx(createExtensionRequestContext.getIRequest(), records);
    }
package com.dfwl.tms.zc.vo.vl;


import javax.validation.constraints.NotNull;

public class ZcVlRCxMidT extends ZcVlRBaseMidT{

    private String id;

    private String interfaceId;

    @NotNull(message = "车型编码不能为空")
    private String carType;
    @NotNull(message = "车型简称不能为空")
    private String abbreviation;

    private String typeName;

    private String typeKind;

    private String flag;

    private String brand;

    private String note;


    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id == null ? null : id.trim();
    }

    public String getInterfaceId() {
        return interfaceId;
    }

    public void setInterfaceId(String interfaceId) {
        this.interfaceId = interfaceId == null ? null : interfaceId.trim();
    }

    public String getCarType() {
        return carType;
    }

    public void setCarType(String carType) {
        this.carType = carType == null ? null : carType.trim();
    }

    public String getAbbreviation() {
        return abbreviation;
    }

    public void setAbbreviation(String abbreviation) {
        this.abbreviation = abbreviation == null ? null : abbreviation.trim();
    }

    public String getTypeName() {
        return typeName;
    }

    public void setTypeName(String typeName) {
        this.typeName = typeName == null ? null : typeName.trim();
    }

    public String getTypeKind() {
        return typeKind;
    }

    public void setTypeKind(String typeKind) {
        this.typeKind = typeKind == null ? null : typeKind.trim();
    }

    public String getFlag() {
        return flag;
    }

    public void setFlag(String flag) {
        this.flag = flag == null ? null : flag.trim();
    }

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand == null ? null : brand.trim();
    }

    public String getNote() {
        return note;
    }

    public void setNote(String note) {
        this.note = note == null ? null : note.trim();
    }
}

2、list集合

list集合不能直接使用应该使用自定义ValidableList

package com.dfwl.tms.zc.vo;

import javax.validation.Valid;
import java.util.*;

/**
 * @program: tms-web
 * @description:
 * @author: jiny
 * @create: 2023-03-16 13:35
 */
public class ValidableList <E> implements List<E> {

    @Valid
    private List<E> list = new LinkedList<>();

    @Override
    public int size() {
        return list.size();
    }

    @Override
    public boolean isEmpty() {
        return list.isEmpty();
    }

    @Override
    public boolean contains(Object o) {
        return list.contains(o);
    }

    @Override
    public Iterator<E> iterator() {
        return list.iterator();
    }

    @Override
    public Object[] toArray() {
        return list.toArray();
    }

    @Override
    public <T> T[] toArray(T[] a) {
        return list.toArray(a);
    }

    @Override
    public boolean add(E e) {
        return list.add(e);
    }

    @Override
    public boolean remove(Object o) {
        return list.remove(o);
    }

    @Override
    public boolean containsAll(Collection<?> c) {
        return list.containsAll(c);
    }

    @Override
    public boolean addAll(Collection<? extends E> c) {
        return list.addAll(c);
    }

    @Override
    public boolean addAll(int index, Collection<? extends E> c) {
        return list.addAll(index, c);
    }

    @Override
    public boolean removeAll(Collection<?> c) {
        return list.removeAll(c);
    }

    @Override
    public boolean retainAll(Collection<?> c) {
        return list.retainAll(c);
    }

    @Override
    public void clear() {
        list.clear();
    }

    @Override
    public E get(int index) {
        return list.get(index);
    }

    @Override
    public E set(int index, E element) {
        return list.set(index, element);
    }

    @Override
    public void add(int index, E element) {
        list.add(index, element);
    }

    @Override
    public E remove(int index) {
        return list.remove(index);
    }

    @Override
    public int indexOf(Object o) {
        return list.indexOf(o);
    }

    @Override
    public int lastIndexOf(Object o) {
        return list.lastIndexOf(o);
    }

    @Override
    public ListIterator<E> listIterator() {
        return list.listIterator();
    }

    @Override
    public ListIterator<E> listIterator(int index) {
        return list.listIterator(index);
    }

    @Override
    public List<E> subList(int fromIndex, int toIndex) {
        return list.subList(fromIndex, toIndex);
    }

    public List<E> getList() {
        return list;
    }

    public void setList(List<E> list) {
        this.list = list;
    }
}

通过代码中的

 if(result.hasErrors()){
            String defaultMessage = result.getFieldError().getDefaultMessage();
            IfcResponseData ifcResponseData = new IfcResponseData(defaultMessage);
            return ifcResponseData;
	}
<think>根据用户的问题,用户询问javax.validation.Valid注解在Java中的使用和功能。结合提供的引用,我将整理回答。 首先,引用[1]提到javax.validation常用注解,并说明在实际开发中,我们可以将这些注解应用在Java Bean的属性上,然后使用Validator进行验证。如果验证失败,Validator将会返回一个包含错误信息的集合。这里虽然没有直接提到@Valid,但提到了验证的整体流程。 引用[2]则明确指出Validator在bean的校验中扮演非常重要的角色,用于主动校验bean实例是否符合规范(如@NotEmpty, @Email等)。这里提到了使用Validator接口进行校验,而@Valid通常用于触发校验。 引用[3]提到@NotBlank注解以及相关依赖的问题,虽然用户的问题是@Valid,但这里说明了使用验证注解时可能遇到的依赖问题。 引用[4]提到了validation-api的jar包,以及如何通过BindingResult获取错误信息,这通常与@Valid一起使用。 综合以上引用,我们可以知道: 1. @Valid注解通常用于标记需要被校验Java Bean(如方法参数、对象属性等),以触发校验。 2. 校验基于JSR 380(Bean Validation 2.0)规范,常用注解有@NotNull, @NotBlank, @Email, @Size等。 3. 在Spring框架中,通常将@Valid注解用于Controller的方法参数上,配合BindingResult来获取校验结果。 因此,回答将围绕@Valid的作用、使用方式以及相关注意事项展开。 同时,根据系统指令,回答需使用中文,行内数学表达式用$...$,独立公式用$$...$$(但此问题可能不涉及数学公式),并生成相关问题。 另外,注意在回答中引用段落末尾添加引用标识。</think>### javax.validation.Valid 注解在 Java 中的使用与功能 #### 一、核心功能 `@Valid` 是 Java Bean Validation 规范(JSR 380)的核心注解,**用于触发级联验证**: 1. **对象图验证**: 当注解标记在方法参数(如 Controller 的入参对象)或对象属性上时,会递归验证该对象及其内部所有被 `@NotNull`、`@Size` 等约束注解标记的属性[^1][^2]。 ```java public class UserController { public void createUser(@Valid User user) { // 触发User对象的级联验证 // ... } } ``` 2. **级联嵌套验证**: 若对象包含其他关联对象(如 `User` 包含 `Address`),需在关联字段上额外添加 `@Valid` 以启用嵌套验证[^4]: ```java public class User { @NotBlank(message = "用户名不能为空") private String name; @Valid // 启用Address对象的验证 private Address address; } ``` #### 二、使用场景 1. **Spring MVC 参数校验**: 在 Controller 层直接标记入参,结合 `BindingResult` 捕获错误: ```java @PostMapping("/create") public String create(@Valid User user, BindingResult result) { if (result.hasErrors()) { return "error"; // 返回验证失败信息 } // 业务逻辑 } ``` 2. **手动触发验证**: 通过 `Validator` 接口手动调用[^2]: ```java ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); Validator validator = factory.getValidator(); Set<ConstraintViolation<User>> violations = validator.validate(user); // 触发验证 ``` #### 三、依赖配置 需确保项目中包含 Bean Validation 实现(如 Hibernate Validator)和 API 依赖[^3]: ```xml <!-- Jakarta Validation API --> <dependency> <groupId>jakarta.validation</groupId> <artifactId>jakarta.validation-api</artifactId> <version>2.0.2</version> </dependency> <!-- 实现库(如 Hibernate Validator) --> <dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>6.2.5.Final</version> </dependency> ``` #### 四、常见问题 1. **校验失效**: - 未添加实现库(仅引入 API 无法工作)[^3]; - 嵌套对象缺少 `@Valid` 注解[^4]; - Spring Boot 版本与 Jakarta Validation 不兼容(建议使用 Spring Boot ≥ 2.3.x)。 2. **错误处理**: 通过 `BindingResult` 或 `ConstraintViolation` 获取错误详情[^4]: ```java violations.forEach(v -> { System.out.println(v.getMessage()); // 输出:用户名不能为空 }); ``` --- ### 相关问题 1. `@Valid` 和 `@Validated` 注解有什么区别? 2. 如何自定义 Bean Validation 约束注解(如 `@Phone` 验证手机号格式)? 3. 在 Spring Boot 中全局处理校验失败异常的最佳实践是什么? 4. 为什么 `@Valid` 对集合类型(如 `List<User>`)无效?如何解决? [^1]: javax.validation 常用注解,如 `@NotNull`、`@Size`,需配合 `@Valid` 触发级联验证。 [^2]: Validator 在主动校验 Bean 实例时依赖 `@Valid` 标记需要递归验证的对象。 [^3]: 依赖冲突或版本不匹配是导致 `@Valid` 失效的常见原因,需确保 API 与实现库版本兼容。 [^4]: 嵌套对象验证必须显式添加 `@Valid`,否则关联对象内的约束注解不会被触发。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

心系代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值