如何在Spring MVC控制器方法中检查未绑定的请求参数?

时间:2014-01-14 12:06:46

标签: java spring spring-mvc parameters controller

给出一个Spring-MVC控制器方法:

@RequestMapping(value = "/method")
public void method(ParamModel params) { /*...*/ }

使用模型类:

public class ParamModel { public int param1; }

以下两个结果符合预期/期望:

  • 请求param1=1method成功完成。
  • 请求param1=blahJBWEB000120: The request sent by the client was syntactically incorrect.

...然而

  • 如果请求使用其他参数(例如nonexistentparam=1),则没有错误

如果请求包含任何不属于此API的参数,是否有办法确保请求已经过验证和拒绝?

5 个答案:

答案 0 :(得分:1)

您可以使用过滤器检查无效参数

的web.xml

<filter>
    <filter-name>MyFilter</filter-name>
    <filter-class>com.mypackage.filter.MyFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>MyFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

MyFilter Class

import javax.servlet.Filter;
public class MyFilter implements Filter {

    public void destroy() {
    }

    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        String requestUrl = request.getParameter("param1");
    //here I am considering 'param1=1' as valid request rest of all are invalid
             if(!requestUrl.equals("1")) {
        logger.info("Invalid Request"); 
        //for invalid request redirect to error or login page
        response.sendRedirect("/error"");           
    } else {
        logger.info("Valid Request");   
    }
    }

    public void init(FilterConfig filterConfig) throws ServletException {
    }       

}

希望这能解决您的问题

答案 1 :(得分:0)

一个很好的做法是Bean-Validation(JSR-303)。这是Document

保持简单,你需要在你的spring配置中使用它:

<mvc:annotation-driven />

您可以在代码中使用此功能:

@RequestMapping(value = "/method")
public void method(@Valid ParamModel params, BindingResult result) {
    if(result.hasErrors()) {...}
    else {...}
}

public class ParamModel { 
    @SomeAnnotation // details see document 
    private int param1; 
}

答案 2 :(得分:0)

Spring的@RequestMapping采用“params”参数。

文档:

  

映射请求的参数,缩小主映射。

     

任何环境的格式相同:一系列“myParam = myValue”样式   表达式,只有在每个这样的参数都被映射时才会映射   发现有给定的价值。使用表达式可以取消表达式   “!=”运算符,如“myParam!= myValue”。 “myParam”风格表达   也支持,这些参数必须存在于   请求(允许有任何价值)。最后,“!myParam”风格   表达式表明不应该指定参数   出现在请求中。

另一种可能性是使用PathVariable(始终需要)或RequestParam参数 required = true

<强>更新

您可以通过继承RequestMappingHandlerMapping并覆盖getCustomMethodCondition / getCustomTypeCondition来创建自己的请求映射条件。

然而,不能使用XML配置<mvc:annotation-driven/>,因为它也声明了这个Bean,你最终会得到2个处理程序映射。 有关详细信息,请查看Adding custom RequestCondition's in Spring mvc 3.1

答案 3 :(得分:0)

最明显,最无聊和非弹性的选择是使用:

@RequestParam Map<String,String> allRequestParams

...并自行检查参数列表。它当然要求您解析(到整数等)并手动验证值,而不是使用DTO和/或javax.validation注释。

完整示例(需要将InvalidParamsException映射到状态代码):

@GetMapping("/my_strict_api")
public void myStrictApi(@RequestParam Map<String,String> allRequestParams) {
  Set<String> allowed = new HashSet<>(Arrays.asList("cat", "dog"));
  if (!allowed.containsAll(allRequestParams.keySet())) {
    throw new InvalidParamsException("We only accept: " + allowed.toString());
  }
  // You should also validate the parameter values before using them
}

答案 4 :(得分:0)

有一种方法可以覆盖控制器请求方法调用:

@Bean
public WebMvcRegistrations mvcRegistrations() {
  return new WebMvcRegistrationsAdapter() {
    @Override
    public RequestMappingHandlerAdapter getRequestMappingHandlerAdapter() {
      return new RequestMappingHandlerAdapter() {
        private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();

        @Override
        protected ServletInvocableHandlerMethod createInvocableHandlerMethod(HandlerMethod handlerMethod) {
          return new ServletInvocableHandlerMethod(handlerMethod) {
            Set<String> boundParametersNames = Stream.of(getMethodParameters())
                .map(methodParameter -> {
                  methodParameter.initParameterNameDiscovery(parameterNameDiscoverer);
                  return methodParameter.getParameterName();
                })
                .collect(Collectors.toSet());

            @Override
            public Object invokeForRequest(NativeWebRequest request,
                                           ModelAndViewContainer mavContainer,
                                           Object... providedArgs) throws Exception {
              for (Iterator<String> iterator = request.getParameterNames(); iterator.hasNext(); ) {
                String parameterName = iterator.next();
                if (!boundParametersNames.contains(parameterName)) {
                  return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(null);
                }
              }
              return super.invokeForRequest(request, mavContainer, providedArgs);
            }
          };
        }
      };
    }
  };
}

在InvocableHandlerMethod中,可以轻松访问和验证请求参数和方法参数。