java如何优雅的实现参数非空校验,快速实现参数非空校验,使用@valid实现参数非空校验

在java项目接口中,有些必传参数需要进行非空校验,如果参数过多,代码会繁杂且冗余,如何优雅的对参数进行非空校验,下面是实现流程

一、整体思路

用实体类接收参数,使用非空注解编辑参数内容
使用 @Valid 注解对参数进行拦截,整体进行非空校验

二、引入依赖

1、SpringBoot项目

如果是SpringBoot项目,引入web开发包,就不需要再单独引入@valid依赖了、因为他存在于Web开发包中的最核心之中

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.0.5.RELEASE</version>
</dependency>

2、其他框架项目

如果不是SpringBoot项目,要在Maven的Pom中显式引入@valid依赖

<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <version>1.1.0.Final</version>
</dependency>
 
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>5.4.1.Final</version>
</dependency>

三、编辑入参实体类

将接口入参使用实体类接收,在实体类中定义参数字段,并使用对应的注解进行注释

  • String类型使用@NotBlank
  • List类型使用@NotEmpty
  • 其他类型使用@NotNull
  • message中是如果字段为空返回的提示内容
@Data
public class aaa {
    @NotBlank(message = "testStr不能为空")
    private String testStr;
    
    @NotNull(message = "testInt不能为空")
    private Integer testInt;
    
    @NotEmpty(message = "testList不能为空")
    private List<Long> testList;
}

四、定义返回的实体类

package com.test;

import lombok.Data;

/**
 * @author
 * @title 响应实体类
 * @param <T>
 */
@Data
public class Result<T> {
    private String code;//返回码
    private String msg;//消息
    private T data;//返回数据


    /**
     * @title 成功消息
     * @param
     * @return
     */
    public static <T> Result<T> OK() {
        return rspMsg(ResponseEnum.SUCCESS);
    }


    /**
     * @title 失败消息
     * @param
     * @return
     */
    public static <T> Result<T> error() {
        return rspMsg(ResponseEnum.SERVER_INNER_ERR);
    }

    /**
     * @title 失败消息
     * @param
     * @return
     */
    public static <T> Result<T> error(String msg) {
        Result<T> message = new Result<T>();
        message.setCode(ResponseEnum.FAIL.code);
        message.setMsg(msg);
        return  message;
    }


    public static <T> Result<T> waring(String msg) {
        Result<T> message = new Result<T>();
        message.setCode("2");
        message.setMsg(msg);
        return  message;
    }

    /**
     * @title 自定义消息
     * @param
     * @return
     */
    public static <T> Result<T> rspMsg(ResponseEnum responseEnum) {
        Result<T> message = new Result<T>();
        message.setCode(responseEnum.getCode());
        message.setMsg(responseEnum.getMsg());
        return message;
    }


    /**
     * @title 返回数据
     * @param data
     * @return
     */
    public static <T> Result<T> OK(T data) {
        Result<T> responseData = new Result<T>();
        responseData.setCode(ResponseEnum.SUCCESS.getCode());
        responseData.setData(data);
        responseData.setMsg(ResponseEnum.SUCCESS.getMsg());
        return responseData;
    }

    /**
     * @title 返回数据
     * @param data
     * @return
     */
    public static <T> Result<T> ok(T data) {
        Result<T> responseData = new Result<T>();
        responseData.setCode(ResponseEnum.SUCCESS.getCode());
        responseData.setData(data);
        responseData.setMsg(ResponseEnum.SUCCESS.getMsg());
        return responseData;
    }

    /**
     * @title 返回数据-自定义code
     * @param data
     * @return
     */
    public static <T> Result<T> OK(String code , T data) {
        Result<T> responseData = new Result<T>();
        responseData.setCode(code);
        responseData.setData(data);
        return responseData;
    }



    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }



    /**
     * @author
     * @title 响应消息枚举
     */
    public enum ResponseEnum {
        // 可以根据自己的实际需要增加状态码
        SUCCESS("0", "操作成功"),
        FAIL("1", "操作失败"),
        SERVER_INNER_ERR("500","未知异常,请联系管理管"),
        PARAM_LACK("100" , "非法参数"),
        ;

        private String code;
        private String msg;

        ResponseEnum(String code, String msg) {
            this.code = code;
            this.msg = msg;
        }

        public String getCode() {
            return code;
        }

        public void setCode(String code) {
            this.code = code;
        }

        public String getMsg() {
            return msg;
        }

        public void setMsg(String msg) {
            this.msg = msg;
        }
    }

}

五、Controller层参数校验

在Controller层加上 @RequestBody 和 @Valid 注解,并且加上 BindingResult res 对参数进行捕获

@PostMapping("/test")
public Result test(@RequestBody @Valid aaa dto, BindingResult res) {
   if (res != null) {
   		//获取校验内容是否为空
        if (res.hasErrors()) {
            List<ObjectError> errorList = res.getAllErrors();
            List<String> resultList = new ArrayList<>();
            for (ObjectError error : errorList) {
            	//获取所有校验错误信息
                resultList.add(error.getDefaultMessage());
            }
            //将错误信息返回
            return Result.error(String.join(",", resultList));
        }
    }
    
    //接口其他逻辑操作
    return Result.ok("非空参数都有值");
}

六,测验结果

如果调用此接口,全部参数都为空,则会返回下面内容

{
    "msg": "testStr不能为空,testInt不能为空,testList不能为空",
    "code": 1
}

七、拦截器补充

其实到上面第六步就已经完成了,但是如果接口过多,每个接口里面都要写这一长串拦截的内容,代码过于冗余,于是加上了一个拦截器

1、加拦截器内容

整个项目加上一个拦截器,拦截器内容如下

package com.test.interceptor;

import com.test.common.Result;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.ArrayList;
import java.util.List;

@ControllerAdvice
public class ControllerExceptInterceptor {

    @ResponseBody
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result handleValidException(MethodArgumentNotValidException e) {
        //日志记录错误信息
       // log.error(Objects.requireNonNull(e.getBindingResult().getFieldError()).getDefaultMessage());
        BindingResult bindingResult= e.getBindingResult();
        if (bindingResult != null) {
            if (bindingResult.hasErrors()) {
                List<ObjectError> errorList = bindingResult.getAllErrors();
                List<String> resultList = new ArrayList<>();
                for (ObjectError error : errorList) {
                    resultList.add(error.getDefaultMessage());
                }
                return Result.error(String.join(",", resultList));
            }
        }

        return Result.error();
    }
}

2、修改Controller层内容

去掉controller层中的 BindingResult res 内容,去掉参数非空校验代码,但是必须要加 @RequestBody @Valid 才有效,如下

@PostMapping("/test")
public Result test(@RequestBody @Valid aaa dto) {
    //接口其他逻辑操作
    return Result.ok("非空参数都有值");
}

八、补充

非springboot项目,注解要引入下面的包,否则会报错:
@notnull 注解引用包为 javax.validation.constraints.NotNull;
@NotBlank 注解引用包为 org.hibernate.validator.constraints.NotBlank;
@NotEmpty 注解引用包为 org.hibernate.validator.constraints.NotEmpty;

结束:上面是文章全部内容,如果接口数量少,直接前六步就行,接口过多,可以使用拦截器,如有问题和建议欢迎留言评论。

  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值