
本文将介绍如何在使用UriBuilder构建URI时,避免因查询参数值与模板冲突而引发的异常。通过使用toTemplate()方法,可以确保UriBuilder正确处理包含特殊字符的参数值,构建出预期的URI。
问题根源
UriBuilder在处理查询参数时,会将参数值中形如{variable}的部分视为URI模板变量。如果这些变量在构建过程中没有被赋予实际值,就会抛出IllegalArgumentException。当参数值恰好包含类似模板的字符时,即使这些字符并非真正的模板变量,也会触发此异常。
解决方案:使用 toTemplate()
UriBuilder提供了一个toTemplate()方法,可以将已构建的URI转换为URI模板。调用此方法后,后续的queryParam()等方法添加的参数将被视为字面值,而不是模板变量。
以下是修改后的代码示例:
String key = "b4o3h4{g}fghg3";
String uri = UriBuilder.fromUri(getUriForName(name))
.queryParam("name", name)
.queryParam("key", key)
.toTemplate()
.build();在这个例子中,toTemplate()方法被调用后,key参数的值"b4o3h4{g}fghg3"将被视为一个普通的字符串,而不是一个包含模板变量的字符串。因此,UriBuilder不会尝试去解析{g},从而避免了IllegalArgumentException异常。
注意:toTemplate()方法会返回一个UriTemplate对象,而不是URI对象。因此,在构建完成后,需要调用build()方法将UriTemplate转换为URI。
完整示例
假设我们有一个方法getUriForName(String name)返回一个基础URI,例如"https://example.com/api"。以下是一个完整的示例,展示了如何使用toTemplate()方法构建URI:
import javax.ws.rs.core.UriBuilder;
import java.net.URI;
public class UriBuilderExample {
private static URI getUriForName(String name) {
return URI.create("https://example.com/api");
}
public static void main(String[] args) {
String name = "test";
String key = "b4o3h4{g}fghg3";
URI uri = UriBuilder.fromUri(getUriForName(name))
.queryParam("name", name)
.queryParam("key", key)
.toTemplate()
.build();
System.out.println(uri.toString());
}
}这段代码的输出结果将是:
https://example.com/api?name=test&key=b4o3h4{g}fghg3可以看到,key参数的值被正确地包含在了URI中,而没有引发任何异常。
总结
当使用UriBuilder构建URI,并且参数值可能包含类似模板的字符时,应该使用toTemplate()方法来避免潜在的冲突。这可以确保UriBuilder将参数值视为字面值,从而正确构建URI。记住,调用toTemplate()后,需要调用build()方法才能得到最终的URI对象。通过这种方式,可以更加安全和可靠地使用UriBuilder来构建各种复杂的URI。










