我正在尝试编写一个Spring REST Controller,将一个字符串数组作为HTTP GET请求的输入参数。
在GET请求中出现问题时,在数组的某些字符串中,我使用逗号,
,空格或正斜杠
/
等特殊字符,< strong>无论我是否对URL HTTP GET请求的查询部分进行URL编码。
这意味着字符串&#34; 1/4 cup ricotta, yogurt
&#34; (编辑,需要将其视为包含在输入数组的字符串元素中的唯一成分),格式如下:
http://127.0.0.1:8080/[...]/parseThis?[...]&ingredients=1/4 cup ricotta, yogurt
此格式(请注意空格编码为+
加上,而不是十六进制代码):
http://127.0.0.1:8080/[...]/parseThis?[...]&ingredients=1%2F4+cup+ricotta%2C+yogurt
或此格式(请注意编码为十六进制代码%20
的空格):
http://127.0.0.1:8080/[...]/parseThis?[...]&ingredients=1%2F4%20cup%20ricotta%2C%20yogurt
未正确呈现。
控制器的相关代码是:
@RequestMapping(
value = "/parseThis",
params = {
"language",
"ingredients"
}, method = RequestMethod.GET, headers = HttpHeaders.ACCEPT + "=" + MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public HttpEntity<CustomOutputObject> parseThis(
@RequestParam String language,
@RequestParam String[] ingredients){
try {
CustomOutputObject responseFullData = parsingService.parseThis(ingredients, language);
return new ResponseEntity<>(responseFullData, HttpStatus.OK);
} catch (Exception e) {
// TODO
}
}
我需要针对这个Spring控制器执行HTTP GET请求,这是一个要求(因此这里不能使用HTTP POST)。
修改1:
如果我将HttpServletRequest request
添加到控制器中方法的签名中,那么我添加一个日志语句,如log.debug("The query string is: '" + request.getQueryString() + "'");
,然后我在日志中看到像The query string is: '&language=en&ingredients=1%2F4+cup+ricotta%2C+yogurt'
这样的行(所以仍然是URL编码)。
编辑2:
另一方面,如果我将WebRequest request
添加到方法的签名中,则日志为log.debug("The query string is: '" + request.getParameter("ingredients") + "'");
,然后我在日志中获得一个字符串The query string is: '1/4 cup ricotta, yogurt'
(因此URL解码)。
我正在使用Apache Tomcat作为服务器。
我是否需要在Spring / webapp配置文件中添加/查看任何过滤器或其他内容?
编辑3:
主要问题在于逗号的解释:
@ResponseBody
@RequestMapping(value="test", method=RequestMethod.GET)
public String renderTest(@RequestParam("test") String[] test) {
return test.length + ": " + Arrays.toString(test);
// /app/test?test=foo,bar => 2: [foo, bar]
// /app/test?test=foo,bar&test=baz => 2: [foo,bar, baz]
}
可以防止这种行为吗?
答案 0 :(得分:3)
请求参数到方法参数的路径经过参数值提取然后参数值转换。现在发生的事情是:
<强>提取强>:
参数为extracted as a single String
value。这可能是为了允许简单的属性作为简单的字符串值传递,以便以后进行值转换。
<强>转换强>:
Spring使用ConversionService进行值转换。在其默认设置StringToArrayConverter is used中,遗憾的是将字符串作为逗号分隔列表处理。
怎么做:
你对Spring处理单值请求参数的方式非常不满。所以我会手动进行绑定:
// Method annotations
public HttpEntity<CustomOutputObject> handlerMethod(WebRequest request) {
String[] ingredients = request.getParameterValues("ingredients");
// Do other stuff
}
您还可以查看Spring guys have to say about this ..和related SO question。
答案 1 :(得分:2)
好吧,你可以注册一个custom conversion service(来自this SO answer),但这似乎很多工作。 :)如果是我,我会忽略方法签名中的@RequestParam
声明,并使用传入的request
对象解析值。
答案 2 :(得分:1)
我建议您尝试以下格式:
ingredients=egg&ingredients=milk&ingredients=butter
将&ingredients
附加到末尾将处理数组只有一个值的情况。
ingredients=egg&ingredients=milk&ingredients=butter&ingredients
ingredients=milk,skimmed&ingredients
需要从数组中删除额外的条目,使用List<String>
会使这更容易。
或者,如果您尝试将REST控制器直接导入到spring-data-jpa的数据库中,则应该查看spring-data-rest。这是一个example。
您基本上使用@RepositoryRestResource
注释您的存储库,而其余的则使用spring:)
答案 3 :(得分:0)
来自here
的解决方案public String get(WebRequest req) {
String[] ingredients = req.getParameterValues("ingredients");
for(String ingredient:ingredients ) {
System.out.println(ingredient);
}
...
}
这适用于包含逗号
的单一成分的情况