空@PathVariable导致ArgumentMismatchException

时间:2017-03-03 18:30:32

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

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

@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)'] ERROR类   com.xxxx.web.controller.custom.ExceptionHandlingController:   抛出RuntimeException:   org.springframework.web.method.annotation.MethodArgumentTypeMismatchException:   无法将'java.lang.String'类型的值转换为所需类型   'java.lang.Integer中';嵌套异常是   java.lang.NumberFormatException:对于输入字符串:“data”

处理此用例的最佳方法是什么?我担心将userId转换为String并捕获异常,这似乎是一个黑客攻击。我也不想依赖客户端总是发送正确的请求。我目前正在使用Spring-Boot v1.2.6.RELEASE,如果我知道将修复它,我愿意升级版本。

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:0)

您的请求映射中存在冲突。

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

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

如果您删除/users/{userId}(仅出于测试原因),您可能会收到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。