【问题标题】:Spring returns 404 when using MethodValidationPostProcessorSpring 在使用 MethodValidationPostProcessor 时返回 404
【发布时间】:2021-01-16 16:24:51
【问题描述】:

我的测试 Spring Boot 应用有问题。它工作得很好,但是当我通过添加依赖项等并添加 @Configuration 启用 Spring 验证时:

@Configuration
public class TestConfiguration {

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

我的测试端点得到 404。

{
    "timestamp": 1601507037178,
    "status": 404,
    "error": "Not Found",
    "message": "No message available",
    "path": "/test"
}

我已经应用了一些类似问题的解决方案/建议(例如herehere),但没有成功。

这是我的代码: https://github.com/zolv/error-handling-test

API接口:

@Validated
public interface TestApi {

  @PostMapping(
      value = "/test",
      produces = {"application/json"},
      consumes = {"application/json"})
  @ResponseBody
  ResponseEntity<TestEntity> getTest(@Valid @RequestBody(required = false) TestEntity request);
}

TestEntity 只是为了发送一些东西:

@Data
public class TestEntity {
  @JsonProperty("test")
  @NotNull
  private String test;
}

控制器实现:

@RestController
@RequiredArgsConstructor
@Validated
public class TestController implements TestApi {
  @Override
  @ResponseBody
  public ResponseEntity<TestEntity> getTest(@Valid @RequestBody TestEntity request) {
    return ResponseEntity.ok(request);
  }
}

我的控制器建议:

@ControllerAdvice
public class DefaultErrorHandlerAdvice extends ResponseEntityExceptionHandler {

  @ExceptionHandler(value = {ConstraintViolationException.class})
  @ResponseStatus(value = HttpStatus.BAD_REQUEST)
  @ResponseBody
  public ResponseEntity<String> handleValidationFailure(ConstraintViolationException ex) {
    StringBuilder messages = new StringBuilder();

    for (ConstraintViolation<?> violation : ex.getConstraintViolations()) {
      messages.append(violation.getMessage());
    }

    return ResponseEntity.badRequest().body(messages.toString());
  }

  @Override
  @ResponseBody
  @ResponseStatus(HttpStatus.BAD_REQUEST)
  protected ResponseEntity<Object> handleMethodArgumentNotValid(
      MethodArgumentNotValidException ex,
      HttpHeaders headers,
      HttpStatus status,
      WebRequest request) {
    return ResponseEntity.status(HttpStatus.BAD_REQUEST)
        .contentType(MediaType.APPLICATION_PROBLEM_JSON)
        .body("problem");
  }
}

应用:

@SpringBootApplication
@EnableWebMvc
@ComponentScan(basePackages = "com.test")
public class TestApplication {

  public static void main(String[] args) {
    SpringApplication.run(TestApplication.class, args);
  }
}

我使用的一个测试,但使用 Postman 也失败了:

@SpringJUnitConfig
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class TestControllerTest {

  @Autowired protected TestRestTemplate restTemplate;

  @Test
  void registrationHappyPath() throws Exception {
    /*
     * Given
     */
    final TestEntity request = new TestEntity();

    /*
     * When/
     */
    final ResponseEntity<String> response =
        restTemplate.postForEntity("/test", request, String.class);

    /*
     * Then
     */
    Assertions.assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode());

    final String body = response.getBody();
    Assertions.assertNotNull(body);
  }
}

如果我注释掉 TestConfiguration,那么一切正常。 提前感谢您的帮助。

【问题讨论】:

    标签: java spring-boot validation http-status-code-404


    【解决方案1】:

    您应该设置MethodValidationPostProcessor#setProxyTargetClass(true),因为默认情况下MethodValidationPostProcessor 使用JDK 代理,这会导致您的控制器在Spring 上下文中丢失。

    AbstractHandlerMethodMapping#processCandidateBean被调用时,isHandler(Class&lt;?&gt; beanType)会返回false,因为JDK代理不包含@RestController注解。

      public MethodValidationPostProcessor methodValidationPostProcessor() {
        MethodValidationPostProcessor mvProcessor = new MethodValidationPostProcessor();
        mvProcessor.setProxyTargetClass(true);
        return mvProcessor;
      }
    
    

    【讨论】:

    • 谢谢,它有效!但是我会理解为什么我需要设置它但是来自类似问题的 2 个类似示例没有它?它与JDK版本相关联吗?我正在使用 14
    • 我相信它不依赖于 JDK。我无法完全回答您的问题,因为我没有运行这些示例。旧的 Spring 版本可能可以与 JDK 代理一起使用。要检查它需要查看 Spring 版本的代码
    • 另外,如果您查看答案 here 下的 cmets,您会发现他们遇到了与您相同的问题。我猜github.com/wololock/rest-validation-demo 没有MethodValidationPostProcessor#setProxyTargetClass(true) 就无法工作
    猜你喜欢
    • 1970-01-01
    • 2018-01-26
    • 1970-01-01
    • 2019-10-22
    • 1970-01-01
    • 2019-09-18
    • 2017-05-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多