如何在Spring请求映射中接受多个可选参数,但一次只能接受一个?

时间:2020-03-27 11:50:12

标签: java spring rest http spring-mvc

编辑:我最终通过更多实验解决了自己的问题。该代码似乎很冗长,因此可能有一个更好的解决方案,它不涉及将字符串类型转换为其他内容。

下面发布的答案。


对于我的学校作业,我应该创建一个GET映射以接收特定类型的所有实体的列表。如果未提供任何参数,则此GET映射应仅返回所有实体,否则,它将在实体存储库中应用某些内容以使用JPQL查询,并使用提供的参数作为顺序查询参数来过滤返回的结果。

“如果未提供请求参数,则返回所有事件的现有功能 应该保留。 如果指定了多个请求参数,则应返回错误响应 返回,表示最多可以提供一个参数。 如果提供了“?status = XXX”参数,且其状态字符串值不 匹配AEventStatus枚举,应该是适当的错误响应 返回。”

我试图将GET映射更改为具有3个可选的@RequestParameter变量,但是我发现检查多个或不存在参数,然后根据存在的情况再次执行操作是很繁琐的逻辑操作其中有哪个参数。

相反,我尝试了此操作(我处于此过程的中间,但还不完整):

  @RequestMapping(
    value="/aevents",
    method = RequestMethod.GET)
  public ResponseEntity<Object> getAllAEvents(HttpServletRequest request) {
    if (request.getParameterMap().size() == 0) {
      return ResponseEntity.status(HttpStatus.OK).body(repository.findAll());
    }
    if (request.getParameterMap().size() > 1) {
      return new ResponseEntity<>("Can only handle one request paramter: title=, status= or minRegistrastions=", HttpStatus.BAD_REQUEST);
    }
    //incomplete from here
  }

现在我不确定这是正确的方法还是只是忽略了某些内容。我想我也许可以检查请求中提供的参数的名称,如果发现无效参数,则可以再次返回错误的请求响应。但是我不确定如何检查参数映射中的参数名称,或者参数映射是否按照我的想法进行。

提供的参数应该是int,枚举值或字符串。

我是否忽略了一种更简单的方法?即一种检查签名中参数数量和参数是否存在的方法:

  @GetMapping("/aevents")
  public List<AEvent> getAllAEvents(@RequestParam(required = false) String title,
                                    @RequestParam(required = false) AEventStatus status,
                                    @RequestParam(required = false) int minRegistrations) {
                                        //Do something here
                                  }

或者我当前的方法可行吗?如果可以,我该如何继续?

2 个答案:

答案 0 :(得分:1)

是的,不过您可能会按照自己的方式进行:

  1. 您可以直接在Spring中注入参数图。
  2. 抛出ResponseStatusException(从Spring 5开始可用),而不是在ResponseEntity周围摸索。

    @GetMapping("/aevents")
    public List<AEvent> getAllAEvents( @RequestParam Map<String, String> allRequestParams){
    
      if(allRequestParams.size() >1){
          throw new ResponseStatusException(
                HttpStatus.BAD_REQUEST,"too many params");
      }
    
      // do something
      return list;
    }
    

答案 1 :(得分:0)

解决后回答我自己的问题:

什么是参数映射? parameterMap实际上是字符串键和字符串数组的映射。要获取参数名称(键)的值,您可以获取该键的值,然后像数组一样对其进行访问。 但是,不需要使用parameterMap。取而代之的是,最好只使用内置的Spring方法,即使用@RequestParam批注并在方法正文中仅使用@RequestParam Map<String, String> params

https://stackoverflow.com/users/2255293/marco-behler致谢,以使我有所了解并提供了引发异常的更好方法。

  @GetMapping("/aevents")
  public List<AEvent> getAllAEvents(@RequestParam Map<String, String> params) {
    if (params.size() == 0) { //Default case, no params
      return repository.findAll();
    }
    if (params.size() > 1) { //Refuse to handle more than one provided param
      throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Can only handle one request parameter: title=, status= or minRegistrations=");
    }
    if (params.containsKey("title")) {
      String value = params.get("title");
      return repository.findByQuery("AEvent_find_by_title", ("%" + value + "%"));
    }
    if (params.containsKey("status")) {
      String stringValue = params.get("status").toUpperCase();
      for (AEventStatus e : AEventStatus.values()) {
        if (e.name().equals(stringValue)) {
          AEventStatus value = AEventStatus.valueOf(stringValue);
          return repository.findByQuery("AEvent_find_by_status", value);
        }
      }
      throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "status=" + stringValue + " is not a valid AEvent status value.");
    }
    if (params.containsKey("minRegistrations")) {
      int value;
      try {
        value = Integer.parseInt(params.get("minRegistrations"));
      } catch (NumberFormatException e) {
        throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Provided request parameter was not a valid number.");
      }
      return repository.findByQuery("AEvent_find_by_minRegistrations", value);
    }
    throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Invalid query parameters.");
  }