0

这是一个相当小众的问题,但希望有人知道答案:

我有一个带有 GetMapping 的 SpringFramework RestController,它使用 javax.validation 注释进行了一些参数验证。我想使用在 application.yml 中定义的属性作为 url 参数的最大值,但是我得到编译器错误,即该变量应该是一个常量。见代码:

@RestController
@Validated
public class AssetController {
  
    private final int maxWaitMillis;

    @Autowired
    public AssetController(@Value("${maxWaitMillis}") int maxWaitMillis) {
        this.maxWaitMillis = maxWaitMillis;
    }

    @GetMapping(value = "/asset", produces = MediaType.IMAGE_JPEG_VALUE)
    @ResponseBody
    public ResponseEntity<byte[]> getAsset(@RequestParam
                                           @NotBlank(message = "id should not be empty") String id,
                                           @RequestParam(defaultValue = "100", name = "timeout-ms")
                                           @Min(value = 0, message = "minimum timeout is 0 ms")
                                           @Max(value = maxWaitMillis, message = "max timeout is " + 

maxWaitMillis) int timeoutMs) {
... 
}

应用程序.yml:

maxWaitMillis: 5000

在@Max(value = maxWaitMillis,它说 maxWaitMillis 应该是常量,因为我猜注释中的检查是在构造函数从 application.yml 获取值之前完成的。

如果我检查maxWaitMillis构造函数或方法体中的值,它的值确实是 5000。

有谁知道是否有办法在验证注释中使用 application.yml 中的值?

谢谢!

4

2 回答 2

1

创建一个自定义验证器,如下所示

@Target({ElementType.PARAMETER})
@Retention(RUNTIME)
@Constraint(validatedBy = MaxWaitMillisValidator.class)
@Documented
public @interface MaxWaitMillis {
    String message() default "Invalid max wait";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

public class MaxWaitMillisValidator implements ConstraintValidator<MaxWaitMillis, Integer> {
    @Value("${maxWaitMillis}")
    private int maxWaitMillis;

    @Override
    public boolean isValid(Integer value, ConstraintValidatorContext context) {
        return value <= maxWaitMillis;
    }
}

然后,您可以在控制器中使用 @MaxWaitMillis 代替 @Max。

于 2021-01-10T18:03:02.117 回答
0

valuefor anannotation必须是一个编译时间常数,所以没有简单的方法可以做你想做的事情。

这是一个常量变量,一种常量表达式

private final int maxWaitMillis = 5000;

这不是:

private final int maxWaitMillis;

@Autowired
public AssetController(@Value("${maxWaitMillis}") int maxWaitMillis) {
    this.maxWaitMillis = maxWaitMillis;
}
于 2021-01-08T14:41:45.593 回答