Spring restController:当未知的@RequestParam在url中时如何出错

时间:2015-11-27 13:56:13

标签: spring-restcontroller

我使用spring 4.2创建了一些restfull webservices。 但我们意识到,当用户输错了其中一个非强制性@RequestParam时,我们不会得到他传递的参数未知的错误。

就像我们有@RequestParam(required=false, value="valueA")字符串值A一样,在通话中他使用'?valuueA = AA' - >我们想要一个错误。 但我似乎没有办法做到这一点,价值被忽略,用户也没有意识到这一点。

1 个答案:

答案 0 :(得分:3)

一种可能的解决方案是创建HandlerInterceptor的实现,该实现将验证传递给处理程序方法的所有请求参数是否在其@RequestParam带注释的参数中声明。

但是你应该考虑这种解决方案的缺点。在某些情况下,您可能希望允许传入某些参数,而不是将其声明为请求参数。例如,如果您有GET /foo?page=1&offset=0之类的请求,并且具有以下签名的处理程序:

@RequestMapping
public List<Foo> listFoos(PagingParams page);

PagingParams是一个包含pageoffset属性的类,通常会从请求参数映射。实现您想要的解决方案会干扰Spring MVC的功能。

话虽如此,这是我想到的一个示例实现:

public class UndeclaredParamsHandlerInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
                             Object handler) throws Exception {
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            checkParams(request, getDeclaredRequestParams(handlerMethod));
        }
        return true;
    }

    private void checkParams(HttpServletRequest request, Set<String> allowedParams) {
        request.getParameterMap().entrySet().forEach(entry -> {
            String param = entry.getKey();
            if (!allowedParams.contains(param)) {
                throw new UndeclaredRequestParamException(param, allowedParams);
            }
        });
    }

    private Set<String> getDeclaredRequestParams(HandlerMethod handlerMethod) {
        Set<String> declaredRequestParams = new HashSet<>();
        MethodParameter[] methodParameters = handlerMethod.getMethodParameters();
        ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();

        for (MethodParameter methodParameter : methodParameters) {
            if (methodParameter.hasParameterAnnotation(RequestParam.class)) {
                RequestParam requestParam = methodParameter.getParameterAnnotation(RequestParam.class);
                if (StringUtils.hasText(requestParam.value())) {
                    declaredRequestParams.add(requestParam.value());
                } else {
                    methodParameter.initParameterNameDiscovery(parameterNameDiscoverer);
                    declaredRequestParams.add(methodParameter.getParameterName());
                }
            }
        }
        return declaredRequestParams;
    }

}

基本上这将做我上面描述的。然后,您可以为它抛出的异常添加异常处理程序,并将其转换为HTTP 400响应。我在Github上添加了更多完整的示例,其中包括通过注释为各个处理程序方法选择性地启用此行为的方法。