验证不适用于RestController中的Map键

问题描述 投票:0回答:2

使用Spring Boot 2.2.6,并为此控制器指定:

@RestController
@Validated
class MyController {
    @GetMapping("foo")
    fun getFirmwareVersionDifference(
        @RequestParam @Valid versions: @Valid Map<
            @Pattern(regexp = "a|b|c")
            String, String>
    ): String {
       // …
    }
}

我希望请求foo?d=any抛出ConstraintViolationException,但通常会调用控制器。

我的上下文中有一个MethodValidationPostProcessor,它可用于其他验证。如果我将RequestParam更改为@RequestParam @Valid @Length(min=3) installedFirmwareVersion: String,则可以正常使用。

我想念什么?

spring-boot kotlin bean-validation
2个回答
1
投票

也许我的答案不是对您要寻找的答案的更正,但确实可以检查您要在控制器中进行的验证。

import in.silentsudo.validators.annotations.RequestMap;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.Map;

public class MapParamValidator implements ConstraintValidator<RequestMap, Map<String, String>> {

    @Override
    public boolean isValid(Map<String, String> stringStringMap, ConstraintValidatorContext constraintValidatorContext) {
        return stringStringMap.containsKey("a") || stringStringMap.containsKey("c") || stringStringMap.containsKey("b");
    }
}

import in.silentsudo.validators.MapParamValidator;

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Constraint(validatedBy = {MapParamValidator.class})
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestMap {
    String message() default "Invalid Request Map";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
}

控制器实现:

@GetMapping("foo")
    public String getFirmwareVersionDifference(
            @RequestParam @Valid
            @RequestMap
                    Map<String, String> versions) {

        return "OK";
    }

请确保像这样在控制器上添加@Validated

@RestController
@Validated
@RequestMapping("/somepath")
public class StatusController {
...
}

如果一切正常,您应该得到这样的东西

There was an unexpected error (type=Internal Server Error, status=500).
getFirmwareVersionDifference.versions: Invalid Request Map
javax.validation.ConstraintViolationException: getFirmwareVersionDifference.versions: Invalid Request Map
...

1
投票

这是kotlin编译器错误/缺少的功能:https://youtrack.jetbrains.com/issue/KT-13228

https://youtrack.jetbrains.com/issue/KT-35843中所述,在kotlin 1.3.70中已部分解决。

这里是如何在build.gradle.kts中设置编译器标志的方法>

tasks.withType<KotlinCompile> {
    kotlinOptions {
        freeCompilerArgs = listOf("-Xemit-jvm-type-annotations")
        jvmTarget = "11" // at least 8 should work, I only tested 11
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.