Spring的UriComponentsBuilder.queryParam问题

时间:2016-03-21 15:34:50

标签: java spring rest

我最近切换到Spring以使用ServiceNow托管的REST API调用。

我正在构建我的URI,如下所示:

UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(baseUrl.toString());
logger.info("URI before Query Param: " + builder.build().encode().toUri());
builder.queryParam("sysparm_limit", "2000000");
builder.queryParam("sysparm_offset", "0");
builder.queryParam("sysparm_exclude_reference_link", "true");
//this line is the issue because there is a = sign here
builder.queryParam("sysparm_query=user_name", snUser.getUser_name());
logger.info("URI after Query Param: " + builder.build().encode().toUri());

此代码的输出为:

INFO: URI before Query Param: https://sandbox.service-now.com/api/now/v1/table/sys_user
INFO: URI after Query Param: https://sandbox.service-now.com/api/now/v1/table/sys_user?sysparm_limit=2000000&sysparm_offset=0&sysparm_exclude_reference_link=true&sysparm_query%3Duser_name=AX0011

问题在于最终的builder.queryParam。我得到输出:

sysparm_query%3Duser_name=AX0011

但我想要的是:

sysparm_query=user_name=AX0011

所以最终的最终URI看起来像这样:

INFO: URI after Query Param: https://sandbox.service-now.com/api/now/v1/table/sys_user?sysparm_limit=2000000&sysparm_offset=0&sysparm_exclude_reference_link=true&sysparm_query=user_name=Z001NR6

所以我尝试更换,

builder.queryParam("sysparm_query=user_name", snUser.getUser_name());

由:

builder.query("sysparm_query=user_name=" + snUser.getUser_name());

改变了原始输出:

INFO: URI after Query Param: https://sandbox.service-now.com/api/now/v1/table/sys_user?sysparm_limit=2000000&sysparm_offset=0&sysparm_exclude_reference_link=true&sysparm_query%3Duser_name=Z001NR6

为:

INFO: URI after Query Param: https://sandbox.service-now.com/api/now/v1/table/sys_user?sysparm_limit=2000000&sysparm_offset=0&sysparm_exclude_reference_link=true&sysparm_query=user_name%3DZ001NR6

注意sysparm_query%3Duser_name = Z001NR6如何更改为sysparm_query = user_name%3DZ001NR6

无论如何要在输出中看到a =而不是%3D?

2 个答案:

答案 0 :(得分:3)

该参数看起来很奇怪 - 但是 - 您可以使用UriComponentsBuilder#query方法手动添加它:

UriComponentsBuilder builder = UriComponentsBuilder
            .fromHttpUrl("https://example.com/api/")
            .queryParam("param1", "12345")
            .queryParam("param2", "abc")
            .query("query=username=JOE");

System.out.println(builder.build().toString()); 
// produces https://example.com/api/?param1=12345&param2=abc&query=username=JOE

System.out.println(builder.build().encode().toString());
// produces https://example.com/api/?param1=12345&param2=abc&query=username%3DJOE

手动连接:

UriComponentsBuilder builder = UriComponentsBuilder
            .fromHttpUrl("https://example.com/api/")
            .queryParam("param1", "12345")
            .queryParam("param2", "abc");
// the parameter has to be properly url-encoded manually (not shown here)
String uri = builder.build().encode().toString() + "&query=username=JOE";

System.out.println(uri);
// produces: https://example.com/api/?param1=12345&param2=abc&query=username=JOE

答案 1 :(得分:0)

URL的查询组件经常用于以key=value对的形式携带信息;您可以将其视为Map<String, String>。在这种情况下,=&是界定这些对的特殊字符,当它们构成keyvalue的一部分时必须对其进行编码,以确保任何内容以这种方式读取查询字符串可以正确解析它。

对于您来说,builder的使用方式取决于您以后希望如何检索数据。有两种选择:

// Building the URL:
builder.queryParam("sysparm_query=user_name", snUser.getUser_name());
// URL contains ...&sysparm_query%3Duser_name=AX0011

// Reading the parsed query map:
Map<String, String> query = ...
String data = query.get("sysparm_query=user_name");
// value is AX0011

// Building the URL:
builder.queryParam("sysparm_query", "user_name=" + snUser.getUser_name());
// URL contains ...&sysparm_query=user_name%3DAX0011

// Reading the parsed query map:
Map<String, String> query = ...
String value = query.get("sysparm_query");
// value is user_name=AX0011

在正确编码的URL中,=之一将始终被编码为%3D。使用UriComponentsBuilder可以确保您的URL正确编码,并且读取URL的任何内容都可以正确编码而不会丢失数据。