如何禁用弹簧引导参数拆分



我们有许多@RestController接收用户编写的通用语言短语。短语可以很长,并且包含标点符号,例如句点,当然还有逗号。

简化的控制器示例:

@RequestMapping(value = "/countphrases", method = RequestMethod.PUT)
public String countPhrases(
@RequestParam(value = "phrase", required = false) String[] phrase) {
return "" + phrase.length;
}

Spring 引导的默认行为是在逗号处拆分参数值,因此使用此 url 调用的上一个控制器:

[...]/countphrases?phrase=john%20and%20me,%20you%and%her

将像我们想要的那样返回"1"的"2"。实际上,使用逗号拆分时,上一个调用等效于:

[...]/countphrases?phrase=john%20and%20me&phrase=you%and%her

我们使用自然语言,我们需要分析用户如何准确编写短语,并确切地知道他们写了多少。

我们尝试了这个解决方案:https://stackoverflow.com/a/42134833/1085716 将其调整到我们的 Spring 启动版本 (2.0.5( 后:

@Configuration
public class MvcConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
// we hoped this code could remove the "split strings at comma"
registry.removeConvertible(String.class, Collection.class);
}
}

但它不起作用。

有人知道如何在 Spring boot 2.0.5 中全局删除"弹簧引导拆分字符串参数"行为吗?

我找到了解决方案。 要覆盖默认转换,我们必须添加一个新转换。如果我们只删除旧的,它不起作用。

正确的(示例(代码应该是:

@Configuration
public class MvcConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.removeConvertible(String.class, String[].class);
registry.addConverter(String.class, String[].class, noCommaSplitStringToArrayConverter());
}
@Bean
public Converter<String, String[]> noCommaSplitStringToArrayConverter() {
return new Converter<String, String[]>() {
@Override
public String[] convert(String source) {
String[] arrayWithOneElement = {source};
return arrayWithOneElement;
}
};
}
}

这样,任何像主要问题中的控制器这样的控制器都不会拆分参数值:

  • [...]/countphrases?phrase=a,b 将返回 1(和 fq=["a,b"](
  • [...]/countphrases?phrase=a,b&phrase=c,d 将返回 2(和 fq=["a,b", "c,d"](

用一个全新的列表替换你的格式化程序注册表可能会让你失去框架附带的一些必要的默认格式化程序。这还将在每个终结点上禁用整个应用程序的所有字符串到集合分析,这样,如果要在另一个终结点上执行如下请求筛选器,它将不起作用:

identifiers = 12,34,45,56,67

溶液: 只需将您的分隔符更改为其他内容... # 或 ;或 $

identifiers = 12;23;34;45;56

这就是我一直在做的事情,所以我不会弄乱格式化程序注册表中的所有好东西。

最新更新