SpringBoot统一参数校验

原文链接

前言

在日常的开发中参数校验是非常重要的一个环节,严格参数校验会减少很多出bug的概率,增加接口的安全性。也会减少对接时不必要的沟通。比如说:在对接的时候前端动不动就甩个截图过来说接口有问题,你检查了半天发现前端传递的参数有问题。针对以上:今天给大家分享一下SpringBoot如何实现统一参数校验。

实现方式

使用 @Validated注解配合参数校验注解, 比如:@NotEmpty对参数进行校验。然后对抛出的异常ControllerAdvice进行捕获然后调整输出数据。

controller
    @PostMapping
    @Log("新增资产管理分类")
    @ApiOperation("新增资产管理分类")
    @PreAuthorize("@el.check('tAtomBusiCategory:add')")
    public ResponseEntity<Object> createTAtomBusiCategory(@Validated @RequestBody TAtomBusiCategory resources){
        if (resources.getId() != null) {
            throw new BadRequestException("A new "+ ENTITY_NAME +" cannot already have an ID");
        }
        tAtomBusiCategoryService.create(resources);
        return new ResponseEntity<>(HttpStatus.CREATED);
    }

接收的入参TAtomBusiCategory

package com.njry.modules.system.domain;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.njry.base.BaseEntity;
import lombok.Data;
import cn.hutool.core.bean.BeanUtil;
import io.swagger.annotations.ApiModelProperty;
import cn.hutool.core.bean.copier.CopyOptions;
import java.io.Serializable;
import java.util.Date;
import java.util.List;

import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import org.hibernate.validator.constraints.Length;

import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;

/**
* @description /
* @author WJ
* @date 2024-04-19
**/
@Data
@TableName("T_ATOM_BUSI_CATEGORY")
public class TAtomBusiCategory  extends BaseEntity implements Serializable {

    @NotNull(groups = BaseEntity.Update.class)
    @TableId(value="category_id", type = IdType.INPUT)
    @ApiModelProperty(value = "ID", hidden = true)
    private Long id;

    @ApiModelProperty(value = "业务类别ID")
    private Long categoryId;

    @NotEmpty(message = "业务类别名称不能为空")
    @Length(min = 1 , max = 40 , message = "名字长度1~40")
    @ApiModelProperty(value = "业务类别名称")
    private String categoryName;

    @ApiModelProperty(value = "上级ID")
    private Long superiorId;

    @ApiModelProperty(value = "层级")
    private Integer categoryLev;

    @ApiModelProperty(value = "排序")
    private Integer orderBy;

    @TableField(exist = false)
    private List<TAtomBusiCategory> children;

    @ApiModelProperty(value = "子业务分类数目", hidden = true)
    private Integer subCount = 0;

    @ApiModelProperty(value = "创建人ID")
    private String createId;

    @ApiModelProperty(value = "创建时间")
    private Date createDate;

    @Length(min = 1 , max = 10 , message = "业务类别英文名称长度1~10")
    @ApiModelProperty(value = "业务类别英文名称")
    private String categoryNameEn;
	//更新的时候用
    public void copy(TAtomBusiCategory source){
        BeanUtil.copyProperties(source,this, CopyOptions.create().setIgnoreNullValue(true));
    }
    //多给前端返回的参数
    public Boolean getHasChildren() {
        return subCount > 0;
    }

    public Boolean getLeaf() {
        return subCount <= 0;
    }

    public String getLabel() {
        return categoryName;
    }
}

不加校验@Length会一堆报错(如下图)
例如:@Length(min = 1 , max = 40 , message = “名字字节长度1~40”)
是因为我们Orcale表里这个字段是VARCHAR2(40),要根据数据库NLS_LENGTH_SEMANTICS和数据库字符集确定(如果是40个汉字,我肯定报错,暂时找不到解决办法)
了解oracle的字段
在这里插入图片描述
这个时候前端在对接的时候看到这样的错误信息,反手就是给你截个图告诉你接口有问题。所以这个时候就该使用 ControllerAdvice规范异常返回信息了。

我们项目处理

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
    /**
     * 处理所有接口数据验证异常
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<ApiError> handleMethodArgumentNotValidException(MethodArgumentNotValidException e){
        // 打印堆栈信息
        log.error(ThrowableUtil.getStackTrace(e));
        ObjectError objectError = e.getBindingResult().getAllErrors().get(0);
        String message = objectError.getDefaultMessage();
        if (objectError instanceof FieldError) {
            message = ((FieldError) objectError).getField() + ": " + message;
        }
        return buildResponseEntity(ApiError.error(message));
    }

    /**
     * 统一返回
     */
    private ResponseEntity<ApiError> buildResponseEntity(ApiError apiError) {
        return new ResponseEntity<>(apiError, HttpStatus.valueOf(apiError.getStatus()));
    }
}

我们定义一个ERROR类返回400
框架统一返回用org.springframework.http public class ResponseEntity
extends org.springframework.http.HttpEntity

@Data
class ApiError {

    private Integer status = 400;
    private Long timestamp;
    private String message;

    private ApiError() {
        timestamp = System.currentTimeMillis();
    }

    public static ApiError error(String message){
        ApiError apiError = new ApiError();
        apiError.setMessage(message);
        return apiError;
    }

    public static ApiError error(Integer status, String message){
        ApiError apiError = new ApiError();
        apiError.setStatus(status);
        apiError.setMessage(message);
        return apiError;
    }
}

常用注解参照原文
在这里插入图片描述
在这里插入图片描述

案例

@Data
public class ExampleForm {

    @NotEmpty(message = "姓名不能为空")
    @Length(min = 1 , max = 10 , message = "名字长度1~10")
    private String name;

    @Range(min = 1 , max = 99 , message = "年龄范围在1~99岁")
    private Integer age;

    @Pattern(regexp = "^[1][3,4,5,7,8][0-9]{9}$" , message = "电话号码有误")
    private String phone;

    @Email(message = "邮箱格式有误")
    private String email;

    @Valid
    @Size(min = 1 ,max =  10 , message = "列表中的元素数量为1~10")
    private List<RequestForm> requestFormList;

    @Future(message = "开始时间必须大于当前时间")
    private Date beginTime;
    
}

实现嵌套验证

在实际的开发中,前台会后台传递一个list,我们不仅要限制每次请求list内的个数,同时还要对list内基本元素的属性值进行校验。这个时候就需要进行嵌套验证了,实现的方式很简单。在list上添加@Vaild就可以实现了。

@Data
public class JsonRequestForm {
    
    @Vaild
    @Size(min = 1 ,max =  10 , message = "列表中的元素数量为1~10")
    private List<ExampleForm> requestFormList;
    
}

注解不是来自同一个依赖包(自己遇到麻烦@Length爆红)

@Size、@Max、@Min等注解是下面这个依赖包的

<dependency>
		<groupId>javax.validation</groupId>
		<artifactId>validation-api</artifactId>
		<version>2.0.2</version>
</dependency>

@Length、这个注解是下面这个依赖的

<dependency>
		<groupId>org.hibernate.validator</groupId>
		<artifactId>hibernate-validator</artifactId>
		<version>6.0.18.Final</version>
</dependency>
  • 23
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值