【问题标题】:Is it possible to split request params in Spring controllers?是否可以在 Spring 控制器中拆分请求参数?
【发布时间】:2019-01-21 06:12:11
【问题描述】:

我有这样的要求:

example.com/search?sort=myfield1,-myfield2,myfield3

我想拆分这些参数以在我的控制器中绑定List<String> 排序或List<SortParam> 其中SortParam 是具有以下字段的类:name(字符串)和ask(布尔值)。

所以最终的控制器应该是这样的:

@RequestMapping(value = "/search", method = RequestMethod.GET)
public ResponseEntity<MyResponse> search(@RequestParam List<String> sort) {

    //...
}

@RequestMapping(value = "/search", method = RequestMethod.GET)
public ResponseEntity<MyResponse> search(@RequestParam List<SortParam> sort) {

    //...
}

有什么办法吗?

更新:

传递参数的标准方式不符合我的要求。 IE。我不能使用sort=myfield1&amp;sort=-myfield2&amp;sort=myfield3。我必须使用逗号分隔的名称。
另外,我明白我可以在我的控制器中接受@RequestParam String sort,然后像sort.split(",") 那样在控制器内拆分字符串,但这也不能解决上述问题。

【问题讨论】:

  • 正确的标准方法是使用/search?sort=myfield1&amp;sort=-myfield2&amp;sort=myfield3。但是用逗号分割也不是什么难事。
  • 是的,用逗号分割并不难。 IE。只是str.split(","),但我想知道是否可以在这些参数到达控制器(而不是控制器)之前拆分它们。
  • 我想在我的控制器中使用List&lt;String&gt; sort,但是传递参数的标准方式不能满足我的要求。我必须使用逗号分隔的名称。

标签: java spring spring-mvc spring-restcontroller spring-rest


【解决方案1】:

是的,你当然可以做到,你就快到了。

@RequestMapping(value = "/search", method = RequestMethod.GET)
public ResponseEntity<MyResponse> participants(@RequestParam("sort") List<String> sort) {

    //...
}

您现在应该可以像这样调用您的服务(如果搜索位于您的根目录,否则根据您的情况进行调整):

curl "localhost:8080/search?sort=sortField1&sort=sortField2&sort=sortField3"

希望这会有所帮助!

编辑 抱歉,我已经阅读了您的 cmets,并且您现在需要什么对我来说很清楚。我已经为您创建了一个解决方法,这几乎就是您想要的。

首先是一个 SortParams 类:

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class SortParams {
  private List<SortParam> sortParamList;

  public SortParams(String commaSeparatedString) {
    sortParamList = Arrays.stream(commaSeparatedString.split(","))
      .map(p -> SortParam.valueOf(p))
      .collect(Collectors.toList());
  }

  public List<SortParam> getSortParamList() {
    return this.sortParamList;
  }

  public enum SortParam {
    FOO, BAR, FOOBAR;
  }
}

那么你的控制器可能看起来像这样:

@RequestMapping(value = "/search", method = RequestMethod.GET)
public ResponseEntity<List<SortParams.SortParam>> search(@RequestParam("sort") SortParams sort) {
    return ResponseEntity.ok(sort.getSortParamList());
}

现在您的 SortParams 对象有一个 SortParam 列表:

curl "localhost:8080/search?sort=FOO,BAR"

["FOO","BAR"]

这样的东西是否符合您的要求?

【讨论】:

  • 感谢您的帮助,但此解决方案并不能解决上述问题。请检查问题下的 cmets。另外,我已经更新了问题,使其更加清晰。
  • 谢谢!这正是我所需要的!
  • 在构造函数中带有转换器逻辑的自定义“SortParams”类型工作得很好 - 但在那之后我看到了下一个答案,我认为实现 org.springframework.core.convert.converter.Converter&lt;Source, Target&gt; 接口是更清洁的方法。无需在该包装对象上调用.getSortParamList(),只需直接在控制器中获取您需要的内容。
【解决方案2】:

它只是一个简单的类型转换任务。 Spring定义了一个SPI(Service Provider Interface)来实现类型转换逻辑。对于您的具体问题,您可以通过实现Converter 接口来定义您的类型转换逻辑。

@Component
public class StringToListConverter implements Converter<String, List<String>> {

    @Override
    public List<String> convert(String source) {
        return Arrays.asList(source.split(","));
    }
}

您还可以根据您的逻辑将您的请求参数转换为List&lt;SortPram&gt;(但我不确定您的问题是否符合您的逻辑)。就是这个!现在 Spring 知道如何将您的请求参数绑定到列表。

@RequestMapping(value = "/search", method = RequestMethod.GET)
public ResponseEntity<MyResponse> participants(@RequestParam("sort") List<String> sort) {
     // .. do your logic
}

还有更多方法可以定义您的自定义数据绑定器。检查这个

【讨论】:

  • 感谢您的解决方案!我接受了 Jonck van der Kogel 的解决方案,但您的解决方案也很棒。谢谢。
猜你喜欢
  • 2012-06-21
  • 1970-01-01
  • 1970-01-01
  • 2018-05-02
  • 1970-01-01
  • 1970-01-01
  • 2018-03-23
  • 2011-08-10
  • 2016-11-16
相关资源
最近更新 更多