インターフェースパラメータの検証

方法 1: Hibernate-validator アノテーション メソッドのパラメーター検証を使用する


似たようなフレームワークが多すぎます。欠点: 返されるプロンプト情報の順序はあまり確実ではありません。

ドキュメント: https://hibernate.org/validator/documentation/

参考: https://blog.csdn.net/weixin_45080272/article/details/128413908

<dependency>
  <groupId>org.hibernate.validator</groupId>
  <artifactId>hibernate-validator</artifactId>
</dependency>

①エンティティクラスのフィールドに @Max、@Min、@NotNull などの検証ルールなどのパラメータ検証アノテーションを追加します。

/**
 * 模板类型:1-同城寄,2-省内寄,3-经济区互寄,4-跨省
 */
@ApiModelProperty(value = "模板类型:1-同城寄,2-省内寄,3-经济区互寄,4-跨省", required = true)
@Max(value = 4, message = "类型值必须是1、2、3、4")
@Min(value = 1, message = "类型值必须是1、2、3、4")
@NotNull(message = "模板类型不能为空")
private Integer templateType;

② @@Validated アノテーションを対応するコントローラー クラスに追加して、パラメーターの検証が有効であることを示します。

@Slf4j
@Validated // 开启参数校验
@RestController
@Api(tags = "运费管理")
@RequestMapping("/carriages")
public class CarriageController {
    
    
    ......
}    

フォームおよび URL パラメーターを検証するには、コントローラー メソッドの入力パラメーターに検証ルールを追加します。

画像.png
一般的な検証の注釈:

  • @Null 注釈が付けられた要素は null である必要があります
  • @NotNull 注釈が付けられた要素は null であってはなりません
  • @AssertTrue 注釈付き要素は true である必要があります
  • @AssertFalse 注釈付き要素は false である必要があります
  • @Min(value) 注釈が付けられた要素は数値である必要があり、その値は指定された最小値以上である必要があります
  • @Max(value) 注釈が付けられた要素は数値である必要があり、その値は指定された最大値以下である必要があります
  • @DecimalMin(value) 注釈が付けられた要素は数値である必要があり、その値は指定された最小値以上である必要があります
  • @DecimalMax(value) 注釈が付けられた要素は数値である必要があり、その値は指定された最大値以下である必要があります
  • @Size(max=, min=) 注釈付き要素のサイズは指定された範囲内である必要があります
  • @Digits (整数、分数) 注釈付きの要素は数値である必要があり、その値は許容範囲内である必要があります
  • @Past 注釈が付けられた要素は過去の日付である必要があります
  • @Future アノテーション付き要素は将来の日付である必要があります
  • @Pattern(regex=,flag=) 注釈付き要素は、指定された正規表現に準拠する必要があります
  • Hibernate Validator によって提供される検証アノテーション:
    • @NotBlank(message =) 文字列が null ではなく、長さが 0 より大きい必要があることを確認します。
    • @Email 注釈が付けられた要素は電子メール アドレスである必要があります
    • @Length(min=,max=) 注釈付き文字列のサイズは指定された範囲内である必要があります
    • @NotEmpty 注釈付きの文字列は空であってはなりません
    • @Range(min=,max=,message=) 注釈付き要素は適切な範囲内にある必要があります

コントローラー メソッド パラメーターのエンティティ クラス内での検証: (エンティティ クラスのフィールド検証ルールを有効にするには、メソッド パラメーターの前に @Valid アノテーションを追加する必要があります)

@PostMapping
public CarriageDTO saveOrUpdate(@Valid @RequestBody CarriageDTO carriageDto) {
    
    
    return carriageService.saveOrUpdate(carriageDto);
}

ただし、この操作は結合されすぎているため、使用するたびに仮パラメータ オブジェクトに注釈を追加する必要があります。

補足: メソッドのパラメータ入力時にリクエストボディオブジェクトのパラメータ検証を行うには、AOP アスペクトメソッドを使用します。

/**
 * 请求参数校验切面,统一对Controller中@RequestBody映射的对象进行校验,在Controller方法中无需单独处理
 */
@Aspect // 声明当前类为切面
@Slf4j
@EnableAspectJAutoProxy // 开启AOP注解功能
@Component
public class ValidatedAspect {
    
    

    @Resource
    private Validator validator; //javax提供的参数校验

    /**
     * 定义切面---在controller方法入参时对请求体对象进行参数校验(校验规则在实体类中)
     *
     * @param proceedingJoinPoint 切入点对象
     * @return
     * @throws Throwable
     */
    // @Around: 环绕通知,可以在目标方法执行前后进行一些处理,方法参数与原方法一致, 返回值类型与原方法返回值类型一致
    // 切点表达式: "execution(* com.sl..controller.*Controller.*(..))",匹配所有controller方法
    @Around("execution(* com.sl..controller.*Controller.*(..))")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
    
    
        // 获取@RequestBody映射的对象:请求体对象
        Object body = AspectUtil.getBody(proceedingJoinPoint);
        // 不为空的body进行拦截校验
        if (!ObjectUtil.isEmpty(body)) {
    
    
            // 进行校验
            // validator.validate(body):验证实体对象中的所有约束,他把校验失败的字段信息封装成一个Set集合返回
            Set<ConstraintViolation<Object>> validateResult = validator.validate(body);
            if (CollUtil.isNotEmpty(validateResult)) {
    
    
                //如果校验结果不为空,表示没有通过校验,则抛出异常,由统一异常处理机制进行处理,响应400
                String info = JSONUtil.toJsonStr(validateResult.stream()
                        .map(ConstraintViolation::getMessage).collect(Collectors.toList()));
                throw new SLException(info, HttpStatus.BAD_REQUEST.value());
            }
        }
        //校验通过,执行原方法:roceedingJoinPoint.proceed(传原方法的入参)
        return proceedingJoinPoint.proceed(proceedingJoinPoint.getArgs());
    }
}
/**
 * 切面工具类
 * 
 * @author 白豆五
 * @date 2023/09/04
 * @since JDK8
 */
@Slf4j
public class AspectUtil {
    
    

    /**
     * 获取被拦截方法对象
     * @param pjp {@link ProceedingJoinPoint}
     * @return {@link Method}
     */
    public static Method getMethod(ProceedingJoinPoint pjp) {
    
    
        //获取参数的类型
        Signature sig = pjp.getSignature();
        if (sig instanceof MethodSignature) {
    
    
            MethodSignature methodSignature = (MethodSignature) sig;
            return methodSignature.getMethod();
        } else {
    
    
            throw new IllegalArgumentException("It's not method");
        }
    }

    /**
     * 解析SPEL表达式
     *
     * @param key key
     * @param method {@link   Method}
     * @param args {@code Object[]}
     * @return key
     */
    public static String parse(String key, Method method, Object[] args) {
    
    
        if (StringUtils.isNotBlank(key) && key.indexOf("#") > -1) {
    
    
            Pattern pattern = Pattern.compile("(\\#\\{([^\\}]*)\\})");
            Matcher matcher = pattern.matcher(key);
            List<String> keys = new ArrayList<>();
            while (matcher.find()) {
    
    
                keys.add(matcher.group());
            }
            if (!CollectionUtils.isEmpty(keys)) {
    
    
                LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
                String[] paraNameArr = u.getParameterNames(method);
                ExpressionParser parser = new SpelExpressionParser();
                StandardEvaluationContext context = new StandardEvaluationContext();
                for (int i = 0; i < paraNameArr.length; i++) {
    
    
                    context.setVariable(paraNameArr[i], args[i]);
                }
                for (String tmp : keys) {
    
    
                    key = key.replace(tmp, parser.parseExpression("#" + tmp.substring(2, tmp.length() - 1)).getValue(context, String.class));
                }
                return key;
            }
        }
        return key;
    }

    /**
     * 获取请求体
     *
     * @param pjp {@link ProceedingJoinPoint}
     * @return {@code Object}
     */
    public static Object getBody(ProceedingJoinPoint pjp) {
    
    
        Object[] args = pjp.getArgs();
        Method method = getMethod(pjp);

        if (ObjectUtil.isNotEmpty(args)) {
    
    
            Annotation[][] parameterAnnotations = method.getParameterAnnotations();
            for (int count = 0; count < parameterAnnotations.length; count++) {
    
    
                for (Annotation annotation : parameterAnnotations[count]) {
    
    
                    if (annotation instanceof RequestBody) {
    
    
                        return args[count];
                    }
                }
            }
        }
        return null;
    }
}


方法 2: プログラム内で if ステートメントを使用してパラメータを検証する


最も大雑把な方法。

public boolean updateStatus(List<String> ids) {
    
    
    if(CollUtil.isEmpty(ids)){
    
    
         return false;       
    }
}

おすすめ

転載: blog.csdn.net/qq_46921028/article/details/132678979