收集 Java 程序员在处理接口的参数校验时觉得麻烦的例子,收集无法使用 @NotNull 等注解来校验参数的例子

235 天前
 sticki

对于 Java 程序员来说,接口的参数校验一般是通过 @NotNull 、 @NotBlank 、 @Size(min = 0, max = 255) 等这些注解来校验的。

但是有一些情况下,这些注解无法满足校验的需求,比如下面这段代码:

public class Test {

	/**
	 * 状态,值必须为枚举类 Status 中的 code
	 */
	Integer status;

	/**
	 * 是否开启语音提示
	 */
	Boolean enableVoice;

	/**
	 * 语音提示内容
	 */
	String voiceContent;

}

这里涉及到两种参数校验是现有的注解无法满足的:

  1. 状态的 Int 值必须存在于枚举类中
  2. 当开启语音提示时,内容必须不为空,本质上是上下文关联的参数校验

这里我只是进行举例,我主要是想收集一下大家遇到的类型情况,然后我想做一个组件,能够尽可能的解决这些问题。

其实我已经有一个这样的组件了,但是担心自己考虑到的情况还不太够,所以想收集一下大家的建议,之后完善一下然后开源出来给大家使用。

6548 次点击
所在节点    Java
30 条回复
gitdoit
235 天前
你是否在寻找 javax.validation.constraints.AssertTrue
liaojl
235 天前
复杂的参数校验直接 service 里写了,上下文关联的,有些还要查数据库校验的,很难做到一个组件通吃的。
sticki
235 天前
@gitdoit 看起来并不是
sticki
235 天前
@liaojl 我只做那些不用查库的,另外我只是想收集这些例子🤡
cheng6563
235 天前
简单解决下常用问题就行了,别搞太复杂。
你是可以搞个解决所有问题的 DSL 来做参数验证,但到了那阶段还不如直接敲程序解决了
JoeDH
235 天前
之前碰到一个,前端传入状态值的,我想用判断状态值是否在已有枚举中,或者在集合里面,我找了下好像没有支持这个情形的注解?
walle1530
235 天前
你是否在寻找 javax.validation.ConstraintValidator
sticki
235 天前
@eastjoehan 是的,我就是想收集这些无法使用现有注解来进行校验的情况

其实我是只希望大家告诉我这些情况就好了,不用跟我说其他劝退的话😅(这句不是跟 @eastjoehan 说的)
sticki
235 天前
@walle1530 ConstraintValidator 可以解决一部分问题,但不够通用,比如我上面举例的第 2 点,enable 的那个,用 ConstraintValidator 是无法解决的
walle1530
235 天前
@sticki #9 理论上来说应该是可以的,定义注解的目标参数和依赖参数,然后定义 Validator 来写检查逻辑,但除非你有大量此类的依赖参数需要检查,如果只是一两个的话,这样更麻烦了。
pxcking
235 天前
public class NotIncludeNullValidator implements ConstraintValidator<NotIncludeNull, Collection<?>> {
@Override
public void initialize(NotIncludeNull constraintAnnotation) {

}

@Override
public boolean isValid(Collection<?> value, ConstraintValidatorContext context) {
// 不校验空集合
if (CollectionUtils.isEmpty(value)) {
return true;
}
for (Object next : value) {
if (next == null) {
return false;
}
}
return true;
}
}
Ashe007
235 天前
没必要,我参数检验选择使用 spring 自带的断言 Assert ,写在参数类中,通过参数对象调用即可

不明白为啥那么多写 jar 包的,特别是写一些垃圾代码的。让人看着就想喷
Ashe007
235 天前
@Ashe007 比如 Java bean 属性用基本类型,工具类是某个 apache 工具类套壳,或者内部本身存在 bug 或非常不合理的逻辑
chihiro2014
234 天前
RedBeanIce
234 天前
加油,

需要查库等的复杂逻辑,我一般写在代码中。
mmdsun
234 天前
这个校验注解可以自定义,加类上都可以
yosoroAida
234 天前
你这可以在参数里面写个方法,并加上 @NotNull 注解 ,参考下我这例子

```java
@Setter
class ExampleParam{
private Integer code;

@NotNull(message = "你的业务逻辑提示")
public ExampleEnum getCodeEnum() {
// 根据 code 去获取 ExampleEnum ,然后返回
return ExampleEnum.getByValue(code);
}
}

@AllArgsConstructor
@Getter
enum ExampleEnum{
;
private final Integer code;

public static ExampleEnum getByValue(Integer value){
for (ExampleEnum exampleEnum : ExampleEnum.values()) {
if(exampleEnum.getCode().equals(value)){
return exampleEnum;
}
}
return null;
}
}
```
yosoroAida
234 天前
@yosoroAida
这样的话,在 Validate 框架去做校验的时候,也会去校验上面个的 getCodeEnum() 是否返回为空,如果返回为空的话,就会把 @NotNull 的 message 的信息给返回回去,这样就免去你在业务逻辑里面做参数校验了。
这样也体现了面向对象编程的优势对吧?
JackCh3ng
234 天前
如果 status 是枚举值,为什么不把 Integer 直接换成枚举类呢?有什么问题吗?
halov
234 天前
不是可以增加自定义的验证注解吗 ,通过 aop 的方式 复杂的业务验证也可以实现

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1036488

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX