Spring REST - 有没有办法重写Spring用来将查询参数分离成一个值列表的字符?

问题描述 投票:1回答:1

我正在使用Spring编写一个REST API,并且有一些客户端不能或不会改变他们调用我的服务的方式。

通常,当发送一个带有值列表的查询参数时,你只需用逗号分隔参数,Spring就会完成剩下的工作。curl http://host.com/api/endpoint?listParam=1,2,3

和控制器

@GetMapping("/api/endpoint")
public ResponseEntity endpoint(@RequestParam("listParam" List<String> listParam){
    // Here, listParam is populated with 1,2,3
}

不幸的是,我的客户将通过列表与酒吧 | 定界符,根本不可能让他们改变。举个例子。 curl http://host.com/api/endpoint?listParam=1%7C2%7C3%7C

我还是想用Spring把这些调用分解成列表,这样我就不必用手动的 String.split() 呼叫。

我已经试过的。 我发现 @InitBinder 注释,并写了以下内容

@InitBinder
public void initBinder(WebDataBinder dataBinder){
    dataBinder.registerCustomEditor(String[].class, new StringArrayPropertyEditor("|"));
}

但是,这段代码似乎从来没有被调用过(用断点观察),而且使用条形作为定界符的请求会以400 BAD REQUEST失败。

任何建议都会非常感激,谢谢!

java spring api rest query-parameters
1个回答
0
投票

由于URL编码问题,出现404。

您需要对以下内容进行编码 | 那么它将会工作,但它会产生另一个问题,params不会被分割。

为了解决这个问题,你需要创建一个自定义的转换,它可以转换为 StringCollection. 对于自定义转换,你可以查看 StringToCollectionConverter 类。一旦你有了自定义转换,那么你就可以注册该服务,在任何一个配置类中添加以下功能


  @Autowired
  void conversionService(GenericConversionService genericConversionService) {
    genericConversionService.addConverter(myStringToCollectionConvert());
  }

  @Bean
  public MyStringToCollectionConvert myStringToCollectionConvert() {
    return new MyStringToCollectionConvert();
  }

在此 MyStringToCollectionConvert 是将解析 String 并转换为Strings的集合。


0
投票

我接受了Sonus21的答案,因为他的建议让我找到了一个可行的例子,但我的解决方案并不完全是他的。

这个类 StringToCollectionConverter 对我来说确实存在,但它无法访问,我无法以任何方式使用它。然而,在看了它所实现的接口后(ConditionalGenericConverter),并搜索更多的Spring转换器的例子,我最终确定了以下解决方案。

listParam 在我的问题中,实际上指的是一组Enum值。我做的第一件事是重写控制器,使其使用Enum值而不是原始的Integer。

@GetMapping("/api/endpoint")
public ResponseEntity endpoint(@RequestParam("listParam" List<EnumClass> listParam){
    // ...
}

接下来,我写了一个 春季定制转换器 (文件)

public class CustomStringToEnumClassListConverter implements Converter<String, List<EnumClass>> {

    @Override
    public List<EnumClass> convert(String str) {
        return Stream.of(
                str.split("\\|")) // Here is where we manually delimit the incoming string with bars instead of commas
                .map(i -> EnumClass.intToValue(Integer.parseInt(i))) // intToValue is a method I wrote to get the actual Enum for a given int
                .collect(Collectors.toList());
    }
}

最后,我写了一个Config Bean,并将这个Custom Converter注册到Spring中。

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addFormatters(FormatterRegistry registry){
        registry.addConverter(new CustomStringToEnumClassListConverter());
    }
}

一旦这些都完成了,Spring就会自动地填充了 listParam 列表 EnumClass 对象。

© www.soinside.com 2019 - 2024. All rights reserved.