给定完整URL时,如何正确构建Java.net.URI适配Spring RestTemplate
如何正确处理带复杂嵌套参数的完整URL以构建java.net.URI(适配Spring RestTemplate)
我需要构建java.net.URI用于Spring RestTemplate,但只能拿到包含所有参数的完整URL,需要对其进行正确编码。网上的示例(包括Spring的UriComponentsBuilder)大多假设URL与参数分离,先编码URI再添加参数;但直接将带所有参数的完整URL传入UriComponentsBuilder会导致参数编码错误,比如把嵌套参数里的=错误转换为&。
示例场景
初始合法URL:
https://graph.microsoft.com/v1.0/users?$select=signInActivity,accountEnabled,userPrincipalName,userType,manager&$expand=manager($select=userPrincipalName)&$filter=(accountEnabled eq true)
使用以下代码处理:
String url = "https://graph.microsoft.com/v1.0/users?$select=signInActivity,accountEnabled,userPrincipalName,userType,manager&$expand=manager($select=userPrincipalName)&$filter=(accountEnabled eq true)"; UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(url); UriComponents uricomp = builder.build(false); URI uri = uricomp.toUri();
得到错误结果:
https://graph.microsoft.com/v1.0/users?$select=signInActivity,accountEnabled,userPrincipalName,userType,manager&$expand=manager($select&userPrincipalName)&$filter=(accountEnabled%20eq%20true)
其中($select&userPrincipalName)部分不符合预期。我可以手动拆分URL的?、&、=来解析,但自定义字符串拆分容易遗漏边缘场景。请问是否有更优的方法,能像Postman解析URL那样,通过工具或库正确处理完整URL的编码构建?
解决方案
方案一:直接使用java.net.URI原生构造器
java.net.URI的构造器会严格遵循RFC规范解析完整URL,能正确识别嵌套在括号里的参数结构,不会错误拆分参数:
String url = "https://graph.microsoft.com/v1.0/users?$select=signInActivity,accountEnabled,userPrincipalName,userType,manager&$expand=manager($select=userPrincipalName)&$filter=(accountEnabled eq true)"; try { URI uri = new URI(url); // 直接将uri传入RestTemplate使用即可 } catch (URISyntaxException e) { // 处理URL格式非法的异常情况 }
方案二:先解析为URI再构建UriComponentsBuilder(需修改URL时用)
如果需要对原始URL做后续修改(比如追加参数、调整路径),可以先用java.net.URI正确解析原始URL,再基于该URI构建UriComponentsBuilder,避免参数结构被破坏:
String url = "https://graph.microsoft.com/v1.0/users?$select=signInActivity,accountEnabled,userPrincipalName,userType,manager&$expand=manager($select=userPrincipalName)&$filter=(accountEnabled eq true)"; try { URI originalUri = new URI(url); UriComponentsBuilder builder = UriComponentsBuilder.fromUri(originalUri); // 安全地追加或修改参数,例如: // builder.queryParam("newParam", "testValue"); URI finalUri = builder.build(true).toUri(); } catch (URISyntaxException e) { e.printStackTrace(); }
问题根源
UriComponentsBuilder.fromUriString()在解析查询字符串时,会简单按&和=拆分参数,无法识别嵌套在括号内的=属于参数值的一部分,因此错误拆分了$expand的参数内容。而java.net.URI的解析逻辑更贴合URL规范,能正确处理这类复杂嵌套场景。
内容的提问来源于stack exchange,提问作者user26830288
相关产品推荐
相关产品推荐

