springBoot @Valid 参数校验

项目中的接口一般都是需要进行参数校验的,这里简单记录一下springboot项目中使用 @Validated和@Valid注解实现接口入参的校验;

maven pom文件所需依赖

springboot 在2.3.0版本之后就没有引入validation对应的包,需要收到添加

        <!-- 参数校验注解 @Valid 所需依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>

第一步:创建用于接收参数的实体类

package com.zhh.demo.entity.ro.user;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.hibernate.validator.constraints.Range;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

/**
 * @Description: 创建用户接口的请求实体
 * @Author: zhaoheng
 */

@Data
@ApiModel("创建用户接口的入参请求实体")
public class CreateUserRO {

    @ApiModelProperty(value = "姓名")
    @Size(message = "姓名应为{min}至{max}个字符", min = 1, max = 10)
    @NotBlank(message = "姓名不能为空")
    private String name;

    @ApiModelProperty(value = "年龄")
    @NotNull(message = "年龄不能为空")
    @Range(message = "年龄范围为 {min} 到 {max} 之间", min = 1, max = 100)
    private Integer age;

    @ApiModelProperty(value = "地址")
    private String address;
}

第二步:创建controller类

package com.zhh.demo.controller;

import com.zhh.demo.common.response.Response;
import com.zhh.demo.common.response.ResponseFactory;
import com.zhh.demo.entity.common.ResponsePage;
import com.zhh.demo.entity.dto.user.UserDTO;
import com.zhh.demo.entity.ro.user.CreateUserRO;
import com.zhh.demo.entity.ro.user.QueryUserListRO;
import com.zhh.demo.service.user.IUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
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;
import java.util.ArrayList;
import java.util.List;

/**
 * @Description: 用户
 * @Author: zhaoheng
 */
@Api(tags = "用户管理-api")
@RequestMapping("/api/user")
@RestController
@Validated // 开启入参校验
public class UserController {

    @Autowired
    private IUserService iUserService;

    @ApiOperation("添加用户")
    @PostMapping("/save")
    public Response<UserDTO> saveUser(@Valid @RequestBody CreateUserRO createUserRO){
        UserDTO userDTO1 = iUserService.saveUser(createUserRO);
        return ResponseFactory.success(userDTO1);
    }

}

第三步:创建全局返回对象

@Data
@ApiModel("接口出参统一响应实体")
public class Response<T> implements Serializable {
    private static final long serialVersionUID = 3692286106860121474L;

    @ApiModelProperty(value = "状态码")
    private String code;

    @ApiModelProperty(value = "说明")
    private String message;

    private T data;

    public Response(){}

    public Response(String code, String message) {
        this.code = code;
        this.message = message;
    }

    public Response(String code, String message, T data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }
}

public class ResponseFactory {

    /**
     * 默认成功
     * @param t
     * @param <T>
     * @return
     */
    public static <T> Response<T> success(T t){
       return new Response<T>(ResponseCode.OK.getCode(),ResponseCode.OK.getMsg(),t);
    }

    /**
     * 成功
     * @param responseCode  响应code和说明
     * @param t
     * @param <T>
     * @return
     */
    public static <T> Response<T> success(ResponseCode responseCode, T t){
        return new Response<T>(responseCode.getCode(),responseCode.getMsg(),t);
    }

    /**
     * 成功
     * @param responseCode  响应code和说明
     * @return
     */
    public static <T> Response<T> success(ResponseCode responseCode){
        return new Response<T>(responseCode.getCode(),responseCode.getMsg());
    }

    /**
     * 默认失败
     * @param <T>
     * @return
     */
    public static <T> Response<T> error(){
        return new Response<T>(ResponseCode.FAIL.getCode(),ResponseCode.FAIL.getMsg());
    }

    /**
     * 失败
     * @param responseCode  响应code和说明
     * @param t
     * @param <T>
     * @return
     */
    public static <T> Response<T> error(ResponseCode responseCode, T t){
        return new Response<T>(responseCode.getCode(),responseCode.getMsg(),t);
    }

    /**
     * 失败
     * @param responseCode  响应code和说明
     * @return
     */
    public static <T> Response<T> error(ResponseCode responseCode){
        return new Response<T>(responseCode.getCode(),responseCode.getMsg());
    }

    /**
     * 失败
     * @param code  错误码
     * @param msg   说明
     * @param t     响应数据
     * @param <T>
     * @return
     */
    public static <T> Response<T> error(String code, String msg, T t){
        return new Response<T>(code,msg,t);
    }

    /**
     * 失败
     * @param code  错误码
     * @param msg   说明
     * @return
     */
    public static <T> Response<T> error(String code, String msg){
        return new Response<T>(code,msg);
    }

    public static <T> ResponsePage pageResult(List<T> list, int total){
        return new ResponsePage<T>(list,total);
    }

}


public enum ResponseCode {

    /** 通用码 **/
    FAIL("-1", "系统错误"),
    OK("200", "成功"),

    /**
     * 参考阿里巴巴开发手册
     * 错误码为字符串类型,共5位,分两部分组成:错误标识+4位数字编号。
     * 例:A0001,A1001,B0001,C0001... A、B、分别代表不通业务或者来源
     **/

    /** 参数校验不通过 **/
    PARAMETER_CHECK_FAILS("A0001","参数校验不通过"),

    /** 用户相关 A1xxx **/
    USER_NAME_NONSTANDARD("A1002", "用户名不合规");

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

    @Getter
    private String code;

    @Getter
    private String msg;
}

第三步,创建全局异常处理类

@Slf4j
@RestControllerAdvice
public class ExceptionHandle {

    /**
     * 处理Exception异常
     * @param exception 异常类型
     * @return
     */
    @ExceptionHandler(value = Exception.class)
    public Response<?> ExceptionHandle(Exception exception){
        log.error("系统出现异常:",exception);
        return ResponseFactory.error(ResponseCode.FAIL);
    }


    /**
     * 入参校验异常,校验不通过,抛出异常信息
     * @param exception Valid 入参校验异常
     * @return
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public Response<?> methodArgumentNotValidExceptionHandle(MethodArgumentNotValidException exception){
        log.error("入参校验不通过",exception);
        BindingResult bindingResult = exception.getBindingResult();
        List<FieldError> fieldErrorList = bindingResult.getFieldErrors();
        fieldErrorList.forEach(fieldError -> {
            log.info("字段:{},message:{}",fieldError.getField(),fieldError.getDefaultMessage());
        });
        // 一个一个给调用方返回提示
        String message = fieldErrorList.get(0).getDefaultMessage();
        return ResponseFactory.error(ResponseCode.PARAMETER_CHECK_FAILS.getCode(), message);
    }

}

执行结果:

{
  "code": "A0001",
  "message": "年龄不能为空",
  "data": null
}

注意点:

controller类上面需要添加注解:@Validated

接口方法的参数前面添加注解:@Valid

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值