【问题标题】:Empty @PathVariable results in ArgumentMismatchException空 @PathVariable 导致 ArgumentMismatchException
【发布时间】:2017-07-23 23:42:45
【问题描述】:

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

@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' 用于队列: 'weblogic.kernel.Default (self-tuning)'] 错误类 com.xxxx.web.controller.custom.ExceptionHandlingController: 抛出运行时异常: org.springframework.web.method.annotation.MethodArgumentTypeMismatchException: 无法将“java.lang.String”类型的值转换为所需类型 'java.lang.Integer';嵌套异常是 java.lang.NumberFormatException:对于输入字符串:“数据”

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

【问题讨论】:

    标签: java spring web-services spring-boot request-mapping


    【解决方案1】:

    您的请求映射有冲突。

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

    问题是您请求/users//data,网络服务器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。

    【讨论】:

    • 这是真的,但这不是常见的 REST 设计吗?如果我有一个用户对象,并且用户与汽车和房屋相关联,那么模式可能是/users/{userId}/cars/users/{userId}/houses。将变量名称更改为{userIdForCars}{userIdForHouses} 会起作用吗?还是有更好的解决方案?
    • 这是绝对正确的 URI 设计,您只需为您的客户提供可以理解的错误代码/消息。我更新了答案。
    【解决方案2】:

    您可以创建一个类来处理全局异常并使用@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

    【讨论】:

      猜你喜欢
      • 2019-10-30
      • 1970-01-01
      • 1970-01-01
      • 2023-03-08
      • 2012-04-10
      • 1970-01-01
      • 2014-10-31
      • 2014-06-14
      • 1970-01-01
      相关资源
      最近更新 更多