当@PathParam无效时,为什么我的@ExceptionHandler注释方法没有被调用?

时间:2018-01-15 08:10:01

标签: java spring spring-boot bean-validation

使用Spring Boot,我有一个接口,其中包含声明为

的方法
@GET
@Path("/{name}")
ProductResponse find( @Size(min = 3) @PathParam("name") String name) throws BusinessException;

和一个用@Validated注释的Rest控制器,实现上述接口 控制器还实现了方法

@ExceptionHandler(value = { ConstraintViolationException.class })
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
public String handleResourceNotFoundException(ConstraintViolationException e) {
     Set<ConstraintViolation<?>> violations = e.getConstraintViolations();
     StringBuilder strBuilder = new StringBuilder();
     for (ConstraintViolation<?> violation : violations ) {
           strBuilder.append(violation.getMessage() + "\n");
     }
     return strBuilder.toString();
}

@configuration注释类还包括方法

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

这适用于所有请求,但问题是当请求包含不符合约束的名称时,不会调用方法handleResourceNotFoundException。

然而,在控制台中我看到了ConstraintViolationException

    [some omitted]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_121]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_121]
    at java.lang.Thread.run(Thread.java:745) [na:1.8.0_121]
Caused by: javax.validation.ConstraintViolationException: null
    at org.springframework.validation.beanvalidation.MethodValidationInterceptor.invoke(MethodValidationInterceptor.java:136) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) [spring-aop-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at com.ncr.nep.sdk.service.aspect.PayloadValidationInterceptor.invoke(PayloadValidationInterceptor.java:103) ~[nep-sdk-service-1.19.0-GA.jar:1.19.0-GA]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) [spring-aop-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at com.ncr.nep.sdk.service.aspect.ExceptionInterceptor.invoke(ExceptionInterceptor.java:41) ~[nep-sdk-service-1.19.0-GA.jar:1.19.0-GA]
    ... 95 common frames omitted

那么为什么没有调用处理方法并且返回500作为响应代码?我错过了什么?

1 个答案:

答案 0 :(得分:1)

您正在使用JAX-RS(@GET@Path@PathParam,...)和Spring @ExceptionHandler。我的猜测是,这种组合不起作用。所以要么你应该使用Spring重写你的控制器:

@GetMapping("/{name}") // Replacement of @Path and @GET
// @PathVariable replaces @PathParam
ProductResponse find( @Size(min = 3) @PathVariable("name") String name) throws BusinessException {
    // ...
}

请注意,并非所有Spring注释都适用于接口,因此您可能需要将它们移动到实际实现中。

或者,您可以使用JAX-RS的ExceptionMapper

@Component
public class ConstraintViolationExceptionMapper implements ExceptionMapper<ConstraintViolationException> {

    @Override
    public Response toResponse(ConstraintViolationException e) {
        Set<ConstraintViolation<?>> violations = e.getConstraintViolations();
        StringBuilder strBuilder = new StringBuilder();
        for (ConstraintViolation<?> violation : violations ) {
            strBuilder.append(violation.getMessage() + "\n");
        }
        return Response.status(Response.Status.BAD_REQUEST).entity(strBuilder.toString()).build();
    }
}

在这种情况下,如果您使用的是Jersey,请务必在ResourceConfig实施中注册异常映射器。