空 @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。
我的控制器中有一个端点配置如下:
@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.
编辑:
事实上,您不应该关心有人向您的 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。