空 @PathVariable 导致 ArgumentMismatchException

Empty @PathVariable results in ArgumentMismatchException

我的控制器中有一个端点配置如下:

@RequestMapping(value = "/users/{userId}/data", method = RequestMethod.GET)
public void getUserData(@PathVariable("userId") @Valid @NotNull Integer userId, HttpServletRequest request) {

}

如果客户端使用空白 userId 向此端点发送请求,我假设 Spring 将 URL 解释为 /users//data,因为会抛出此异常:

2017-03-03 11:13:41,259 [[ACTIVE] ExecuteThread: '3' for queue: 'weblogic.kernel.Default (self-tuning)'] ERROR class com.xxxx.web.controller.custom.ExceptionHandlingController: RuntimeException thrown: org.springframework.web.method.annotation.MethodArgumentTypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'java.lang.Integer'; nested exception is java.lang.NumberFormatException: For input string: "data"

处理此用例的最佳方法是什么?我对将 userId 转换为 String 并捕获异常持谨慎态度,这似乎是一种 hack。我也不想依赖客户端总是发送正确的请求。我目前正在使用 Spring-Boot v1.2。6.RELEASE 如果我知道可以修复它,我愿意升级版本。

你可以创建一个class来处理全局异常并用@ControllerAdvice注解。

@ControllerAdvice
public class CustomRestExceptionHandler extends ResponseEntityExceptionHandle { 

    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    public ResponseEntity<Object> handleMethodArgumentTypeMismatch(
        MethodArgumentTypeMismatchException ex, WebRequest request) {

        //Handle your exception here...

    }
}

这是一篇很好的文章,介绍了如何使用 @ControllerAdivce

做很多事情

http://www.baeldung.com/global-error-handler-in-a-spring-rest-api

您的请求映射存在冲突。

您很可能还有 /users/{userId} 的 GET 映射。这是应用的映射,而不是您问题中的映射。

问题是您通过单斜线请求 /users//data,Web 服务器 automatically replaces 双斜线。结果请求与此模式 /users/{userId} 完全匹配,但与您发布的不匹配。最后 spring 无法将 data 转换为整数。

如果您删除 /users/{userId}(仅出于测试原因),您可能会收到请求相同 url.

的 404 错误代码

编辑:

事实上,您不应该关心有人向您的 REST 发送了错误的请求 API。 REST API 是一个契约,双方都应该遵守这个契约。作为后端点,您应该只处理请求并提供适当的错误代码和良好的描述,以防请求错误。 data 从来都不是正确的用户 ID

一种可能的解决方案是使用模式验证 ID。 在您的情况下,它将如下所示:

@RequestMapping(value = "/users/{userId:\d+}/data", method = GET)
@RequestMapping(value = "/users/{userId:\d+}", method = GET)

在这种情况下spring 将自动过滤非数字 ID 并为其提供 HTTP 404。