借助swagger注解 对参数进行优雅校验

一.通过swagger注解定义校验规则

swagger注解再项目中常常用到,我们可以通过定义value值来实现参数校验

1.定义工具类方法

package com.ruoyi.common.verily;

import com.ruoyi.common.exception.ServiceException;
import io.swagger.annotations.ApiModelProperty;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Field;
import java.util.List;


public class ApiVerify {
    /**
     * 依据注解进行入参校验
     * @param bizDesc       校验业务描述
     * @param obj           入参DTO
     * @param bInsert       是否是新增进行全变量检查
     * @param noEmptyFields 本次检查不容许为空的属性列表,用,分隔
     * @return void
     */
    public static void verifyApiModelProperty(String bizDesc, Object obj, boolean bInsert, String noEmptyFields) {
        if (null == obj) {
            return;
        }
        if (obj instanceof List) {
            for (Object o : (List<?>) obj) {
                for (Field field : o.getClass().getDeclaredFields()) {
                    verifyApiFieldProperty(bizDesc, o, field, bInsert, noEmptyFields);
                }
            }
            return;
        }
        for (Field field : obj.getClass().getDeclaredFields()) {
            verifyApiFieldProperty(bizDesc, obj, field, bInsert, noEmptyFields);
        }
    }


    /**
     * 依据注解进行入参数据域校验
     * @param bizDesc       校验业务描述
     * @param obj           入参DTO
     * @param field         入参数据域
     * @param bInsert       是否是插入进行全变量检查
     * @param noEmptyFields 本次检查不容许为空的属性列表,用,分隔
     * @return void
     */
    private static void verifyApiFieldProperty(String bizDesc, Object obj, Field field, boolean bInsert, String noEmptyFields)  {
        if (null == field) {
            return;
        }
        if (StringUtils.isBlank(noEmptyFields)) {
            noEmptyFields = "";
        } else {
            noEmptyFields = "," + noEmptyFields + ",";
        }

        Object oValue = null;
        String fName = "";
        try {
            field.setAccessible(true);
            fName = field.getName();
            oValue = field.get(obj);
        } catch (Exception ex) {
            return;
        }
        //取得注解的内容
        ApiModelProperty property = field.getAnnotation(ApiModelProperty.class);
        if (null == property) {
            return;
        }
        //分析注解信息
        String propValue = property.value();
        VerifyDTO verifyProp = getVerifyProper(propValue);
        if (null == verifyProp) {
            return;
        }
        String ename = verifyProp.getEname();
        String cname = verifyProp.getCname();
        int maxLen = verifyProp.getMaxLen();
        int minLen = verifyProp.getMinLen();

        //空值校验
        String sName = "," + fName + ",";
        boolean bVerifyEmpty = false;
        //修改noEmptyFields.indexOf(sName) >= 0  原来是>,改成>=
//        if (noEmptyFields.indexOf(sName) >= 0 || (bInsert && minLen > 0)) {
        if (noEmptyFields.contains(sName) || (bInsert && minLen > 0)) {
            bVerifyEmpty = true;
        }
        if (null == oValue || StringUtils.isBlank(oValue.toString())) {
            if (bVerifyEmpty) {
                throw new ServiceException(bizDesc + " " + cname + "[" + ename + "]不能为空");
            }
            return;
        }

        //最大长度校验
        String strValue = null;
        if (oValue instanceof String) {
            strValue = oValue.toString();
            if (maxLen > 0 && strValue.length() > maxLen) {
                //修改提示,原来是minLen,改成maxLen
                throw new ServiceException(bizDesc + " " + cname + "[" + ename + "]长度不能超过"+maxLen);
            }
        }
    }

    /**
     * 依据数据域注解分析校验信息,cn=黑名单标志|en=bklsFlag|minlen=0|maxLen=3|type=date
     * @param expr 注解表达式
     * @return VerifyDTO 校验信息
     */
    private static VerifyDTO getVerifyProper(String expr) {
        VerifyDTO res = null;
        if (StringUtils.isBlank(expr)) {
            return null;
        }
        String tmpExpr;
        int iPos;
        String fKey, fValue;
        while (!"".equals(expr)) {
            iPos = expr.indexOf("|");
            if (iPos < 0) {
                tmpExpr = expr;
                expr = "";
            } else {
                tmpExpr = expr.substring(0, iPos);
                expr = expr.substring(1 + iPos);
            }
            iPos = tmpExpr.indexOf("=");
            if (iPos < 0) {
                continue;
            }
            fKey = tmpExpr.substring(0, iPos);
            fValue = tmpExpr.substring(1 + iPos);
            fKey = fKey.trim();
            fValue = fValue.trim();
            if (null == res) {
                res = new VerifyDTO();
            }
            res.setProp(fKey, fValue);
        }
        return res;
    }
}

package com.ruoyi.common.verily;

import org.apache.commons.lang3.StringUtils;

import java.io.Serializable;


public class VerifyDTO implements Serializable {
    private String ename;
    private String cname;
    private int maxLen;
    private int minLen;

    public String getEname() {
        return ename;
    }

    @Override
    public String toString() {
        return "中文描述:" + cname + "|"
                + "属性名:" + ename + "|"
                + "最大长度:" + maxLen + "|"
                + "最小长度:" + minLen + "";
    }

    public void setEname(String ename) {
        this.ename = ename;
    }

    public String getCname() {
        return cname;
    }

    public void setProp(String name, String val) {
        if (StringUtils.isBlank(name) || StringUtils.isBlank(val)) {
            return;
        }
        name = name.toLowerCase().trim();
        if ("cn".equals(name)) {
            setCname(val);
            return;
        }
        if ("en".equals(name)) {
            ename = val;
            return;
        }
        int intVal = 0;
        try {
            intVal = Integer.parseInt(val);
        } catch (Exception ex) {
            return;
        }
        if ("minlen".equals(name)) {
            minLen = intVal;
            return;
        }
        if ("maxlen".equals(name)) {
            maxLen = intVal;
            return;
        }
    }

    public void setCname(String cname) {
        if (StringUtils.isBlank(cname)) {
            cname = "";
        }
        int iPos = cname.indexOf(" ");
        if (iPos < 0) {
            iPos = cname.indexOf("(");
        }
        if (iPos < 0) {
            iPos = cname.indexOf("(");
        }
        if (iPos < 0) {
            iPos = cname.indexOf("-");
        }
        if (iPos < 0) {
            iPos = cname.indexOf(" ");
        }
        if (iPos > 0) {
            cname = cname.substring(0, iPos);
        }
        this.cname = cname;
    }

    public int getMaxLen() {
        return maxLen;
    }

    public void setMaxLen(int maxLen) {
        this.maxLen = maxLen;
    }

    public int getMinLen() {
        return minLen;
    }

    public void setMinLen(int minLen) {
        this.minLen = minLen;
    }
}

2.测试

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二.常用注解校验

1 Maven依赖

 <!--第一种方式导入校验依赖-->
    <dependency>
        <groupId>javax.validation</groupId>
        <artifactId>validation-api</artifactId>
        <version>2.0.1.Final</version>
    </dependency>
    <!--第二种方式导入校验依赖-->
    <dependency>
        <groupId>org.hibernate.validator</groupId>
        <artifactId>hibernate-validator</artifactId>
    </dependency>

2 值校验
2.1 @Null注解
被注解的元素必须为null

@Null(message = "必须为null")
private String username;

2.2 @NotNull注解
被注解的元素必须不为null

@NotNull(message = "必须不为null")
private String username;

2.3 @NotBlank注解
验证注解的元素值不为空(不为null、去除首位空格后长度为0) ,并且类型为String。

@NotBlank(message = "必须不为空")
private String username;

2.4 @NotEmpty注解
验证注解的元素值不为null且不为空(字符串长度不为0、集合大小不为0) ,并且类型为String。

@NotEmpty(message = "必须不为null且不为空")
private String username;

2.5 @AssertTrue注解
被注解的元素必须为true,并且类型为boolean。

@AssertTrue(message = "必须为true")
private boolean status;

2.6 @AssertFalse注解
被注解的元素必须为false,并且类型为boolean。

@AssertFalse(message = "必须为false")
private boolean status;

3 范围校验
3.1 @Min注解
被注解的元素其值必须大于等于最小值,并且类型为int,long,float,double。

@Min(value = 18, message = "必须大于等于18")
private int age;

3.2 @Max注解
被注解的元素其值必须小于等于最小值,并且类型为int,long,float,double。

@Max(value = 18, message = "必须小于等于18")
private int age;

3.3 @DecimalMin注解
验证注解的元素值大于等于@DecimalMin指定的value值,并且类型为BigDecimal。

@DecimalMin(value = "150", message = "必须大于等于150")
private BigDecimal height;

3.4 @DecimalMax注解
验证注解的元素值小于等于@DecimalMax指定的value值 ,并且类型为BigDecimal。

@DecimalMax(value = "300", message = "必须大于等于300")
private BigDecimal height;

3.5 @Range注解
验证注解的元素值在最小值和最大值之间,并且类型为BigDecimal,BigInteger,CharSequence,byte,short,int,long。

@Range(max = 80, min = 18, message = "必须大于等于18或小于等于80")
private int age;

3.6 @Past注解
被注解的元素必须为过去的一个时间,并且类型为java.util.Date。

@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Past(message = "必须为过去的时间")
private Date createDate;

3.7 @Future注解
被注解的元素必须为未来的一个时间,并且类型为java.util.Date。

@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Future(message = "必须为未来的时间")
private Date createDate;

4 长度校验
4.1 @Size注解
被注解的元素的长度必须在指定范围内,并且类型为String,Array,List,Map。

@Size(max = 11, min = 7, message = "长度必须大于等于7或小于等于11")
private String mobile;

4.2 @Length注解
验证注解的元素值长度在min和max区间内 ,并且类型为String。

@Length(max = 11, min = 7, message = "长度必须大于等于7或小于等于11")
private String mobile;

5 格式校验
5.1 @Digits注解
验证注解的元素值的整数位数和小数位数上限 ,并且类型为float,double,BigDecimal。

@Digits(integer=3,fraction = 2,message = "整数位上限为3位,小数位上限为2位")
private BigDecimal height;

5.2 @Pattern注解
被注解的元素必须符合指定的正则表达式,并且类型为String。

@Pattern(regexp = "\\d{11}",message = "必须为数字,并且长度为11")
private String mobile;

5.3 @Email注解
验证注解的元素值是Email,也可以通过regexp和flag指定自定义的email格式,类型为String。

 @Email(message = "必须是邮箱")
private String email;

————————————————

部分参考:https://blog.csdn.net/qq_38974638/article/details/115396937

  • 13
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
### 回答1: Swagger3 中的 `oneOf` 关键字用于定义一个对象可以具有多个属性中的一个。在参数校验方面,需要使用组合关键字 `anyOf` 来完成。 具体实现步骤如下: 1. 在 `parameters` 中定义一个 `schema` 对象,并在其中使用 `anyOf` 关键字以及多个 `properties` 对象。示例如下: ``` parameters: - in: body name: requestBody required: true schema: anyOf: - $ref: '#/components/schemas/Property1' - $ref: '#/components/schemas/Property2' ``` 2. 在 `components` 中定义多个 `schemas` 对象,分别对应 `anyOf` 中的每个 `properties` 对象。示例如下: ``` components: schemas: Property1: type: object properties: prop1: type: string maxLength: 10 Property2: type: object properties: prop2: type: integer maximum: 100 ``` 注意:对每个 `properties` 对象进行参数校验时,需要在其中添加相应的参数校验规则,例如 `maxLength` 和 `maximum`。 这样就完成了使用 `oneOf` 进行参数校验的实现。 ### 回答2: Swagger 3 是一个流行的 API 文档规范和工具,而 "oneof" 是一个用于定义参数的关键字。在 Swagger 3 中,可以使用一些技巧来进行参数校验。 首先,我们需要在 Swagger 3 的定义文件中使用 "oneof" 关键字来定义参数。这样可以确保参数的取值只能是定义中的一个。 例如,假设我们有一个接口需要传入一个身份型的参数,可以是 "学生" 或者 "教师"。我们可以在 Swagger 3 定义文件中,使用 "oneof" 关键字来定义该参数: ```yaml paths: /api/something: post: parameters: - name: identity in: query required: true schema: oneOf: - type: string enum: - 学生 - type: string enum: - 教师 ``` 上面的例子中,我们使用了 "oneOf" 嵌套了两个枚举型的参数。这样,在调用该接口时,只能选择其中一个身份型。 接下来,在服务器端代码中,我们可以通过检查参数的取值来进行校验。例如,我们可以使用以下伪代码: ```python def handle_request(identity): if identity == "学生": # 处理学生参数 elif identity == "教师": # 处理教师参数 else: # 参数错误,返回错误信息 ``` 通过以上方法,我们可以轻松实现 Swagger 3 中的参数校验。 需要注意的是,由于 Swagger 3 只是一个 API 规范和工具,实际的参数校验逻辑需要在服务器端代码中实现。 ### 回答3: 在 Swagger 3 中,我们可以使用 `oneOf` 关键字来定义一个参数的多种可能取值。在进行参数校验时,我们可以使用一些针对 `oneOf` 的校验规则。 首先,我们需要在 Swagger 规范中定义 `oneOf` 的内容。例如,假设我们有一个参数 `status`,它可以是 "active" 或 "inactive"。我们可以使用以下代码定义它的取值范围: ``` parameters: - name: status in: query schema: oneOf: - type: string enum: - active - type: string enum: - inactive ``` 通过上述定义,我们限定了 `status` 参数的取值范围为 "active" 或 "inactive"。当我们输入其他值时,Swagger 将会进行参数校验并返回相应的错误信息。 另外,我们还可以使用一些自定义的校验规则来对参数进行详细的校验。例如,我们可以通过正则表达式对参数进行进一步的限制。示例如下: ``` parameters: - name: status in: query schema: oneOf: - type: string pattern: ^(active|inactive)$ ``` 通过上述定义,Swagger 将会对 `status` 参数进行正则表达式的校验,只允许值为 "active" 或 "inactive"。当我们输入其他值时,Swagger 将会返回相应的错误信息。 总结起来,Swagger 3 中的 `oneOf` 可以帮助我们定义一个参数的多种可能取值范围,并可以通过自定义的校验规则对参数进行进一步的限制和校验

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小瞿码上有

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

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

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

打赏作者

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

抵扣说明:

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

余额充值