有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Javax验证不适用于值为数组或列表的Hashmap

我正在用spring boot开发Kotlin

我有一个实体Hours

data class Hours(
         @get: Max(value=3) val value : Long)

在我的构造函数中,我有以下内容

fun postHours(@RequestBody @Valid hours: @Valid LinkedHashMap<String,  Array<Hours>>): String {
        return service.addHours(hours)
    }

但验证根本不起作用

我可以用value > 3发送请求,尽管我已将最大值设置为3。而且没有错误

有人能告诉我这里怎么了吗


共 (1) 个答案

  1. # 1 楼答案

    我有一个类似的案例正在Java中工作(您可以重写为Kotlin)。请尝试:

    在用@configuration注释的配置类中定义一个新bean:

    @Bean
    public MethodValidationPostProcessor methodValidationPostProcessor() {
        return new MethodValidationPostProcessor();
    }
    

    为控制器添加以下注释:

    @RestController
    @Validated
    

    然后,您可以通过以下方式验证您的类:

    postHours(@RequestBody LinkedHashMap<String, @Valid Hours> hours)
    

    -修改以提供完整示例-

    你可以使用这个完整的例子。我正在使用:spring boot starter web 2.2.6和lombok

    下面是要验证的类:

    @Data
    public class Foo {
        @Max(value = 3)
        private Integer count;
    }
    

    控制器:

    @RestController
    @Validated
    public class FooController {
        @PostMapping("/validate")
        public String validate(@RequestBody LinkedHashMap<String, List<@Valid Foo>> foos) {
            return "foo";
        }
    }
    

    配置类:

    @Configuration
    public class AppConfig {
        @Bean
        public MethodValidationPostProcessor methodValidationPostProcessor() {
            return new MethodValidationPostProcessor();
        }
    }
    

    控制器建议(以json形式发送异常):

    @ControllerAdvice
    public class CustomResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {
        @Data
        @AllArgsConstructor
        class ApiError {
            private HttpStatus status;
            private String message;
            private List<String> errors;
        }
    
        @ExceptionHandler({ ConstraintViolationException.class })
        public ResponseEntity<Object> handleConstraintViolation(ConstraintViolationException ex, WebRequest request) {
            List<String> errors = new ArrayList<>();
            for (ConstraintViolation<?> violation : ex.getConstraintViolations()) {
                errors.add(violation.getRootBeanClass().getName() + " " +
                        violation.getPropertyPath() + ": " + violation.getMessage());
            }
    
            ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST, ex.getLocalizedMessage(), errors);
            return new ResponseEntity<>(apiError, new HttpHeaders(), apiError.getStatus());
        }
    }
    

    测试等级:

    @WebMvcTest(FooController.class)
    public class FooControllerTest {
    
        @Autowired
        private MockMvc mockMvc;
    
        @Autowired
        private ObjectMapper objectMapper;
    
        @Test
        public void test() throws Exception {
            LinkedHashMap<String, Foo> foos = new LinkedHashMap<>();
            Foo foo = new Foo();
            foo.setCount(4);
            foos.put("foo", foo);
            this.mockMvc.perform(post("/validate")
                    .contentType(MediaType.APPLICATION_JSON)
                    .content(objectMapper.writeValueAsString(bars)))
                    .andExpect(status().isBadRequest())
                    .andExpect(content().string(containsString("validate.foos[foo].<map value>[0].count: must be less than or equal to 3")));
        }
    }
    

    单元测试表明linkedhashmap内部的验证是有效的