Vert.x URI 模板

URI 模板 RFC 的一个实现。

这实现了规范级别 4。

使用 URI 模板

要使用此组件,请将以下依赖项添加到构建描述符的依赖项部分

  • Maven(在您的 pom.xml 中)

<dependency>
  <groupId>io.vertx</groupId>
  <artifactId>vertx-uri-template</artifactId>
  <version>5.0.1</version>
</dependency>
  • Gradle(在您的 build.gradle 文件中)

compile 'io.vertx:vertx-uri-template:5.0.1'

模板

您可以非常轻松地创建模板

UriTemplate template = UriTemplate.of("http://{host}/product/{id}{?sort}");

只能创建有效的模板,任何无效的模板在创建时都会被异常拒绝

UriTemplate template = UriTemplate.of("{!invalid}}"); // Will throw an exception

模板展开

您可以调用 expandToString 并传入变量列表以生成有效的 URI 字符串

UriTemplate template = UriTemplate.of("http://{host}/product/{id}{?sort}");
String uri = template.expandToString(Variables
  .variables()
  .set("host", "localhost")
  .set("id", "12345")
  .set("sort", "price")
);

Variables 包含模板展开所使用的变量

  • 您可以设置单值变量

variables.set("server", "localhost");
variables.set("port", "8080");
  • 您可以设置列表值变量

variables.set("ids", Arrays.asList("123", "456"));
  • 您可以设置映射值变量

Map<String, String> query = new HashMap<>();
query.put("firstName", "Dale");
query.put("lastName", "Cooper");
variables.set("query", query);

如前所述,模板中的变量通过其名称(用花括号括起来)引用,例如 {host} 引用 host 变量,这种展开方式被称为 简单字符串展开

还有其他展开样式,它们在格式和编码上与简单字符串展开不同。

列表会展开为逗号分隔的值

UriTemplate template = UriTemplate.of("http://server.com/products?sort={sort}");
Variables variables = Variables.variables().set("sort", Arrays.asList("price", "name"))
assertEquals("http://server.com/products?sort=price,name", template.expandToString(variables));

同样,映射值会展开为逗号分隔的值,例如 { "firstName": "Dale", "lastName": "Cooper" } 会展开为 "firstName,Dale,lastName,Cooper",除非它们被 星号 修饰符 展开

UriTemplate template = UriTemplate.of("http://server.com/?details={details*}");
Map<String, String> details = new HashMap<>();
details.put("firstName", "Dale");
details.put("lastName", "Cooper");
Variables variables = Variables.variables().set("details", details)
assertEquals("http://server.com/?firstName=Dale,lastName=Cooper", template.expandToString(variables));

模板编码

保留集和非保留集之外的字面字符会被百分比编码

assertEquals("http://server.com/currency/%E2%82%AC", UriTemplate.of("http://server.com/currency/€").expandToString(variables));

简单字符串展开会将非保留集之外的任何字符编码为其百分比编码的等效形式

Variables variables = Variables.variables();
variables.set("currency", "")
assertEquals("http://server.com/currency/%E2%82%AC", UriTemplate.of("http://server.com/currency/{currency}").expandToString(variables));

展开样式

除了简单字符串展开之外,您还可以使用其他展开样式,展开遵循 '{' 运算符? 变量名 '}' 的语法。

简单字符串展开

没有给出运算符时的默认展开样式。

  • 语法: {varname}

  • 允许的字符: 非保留

变量 模板 URI

{ "who": "fred" }

{who}

fred

{ "unreserved": "_" }

{unreserved}

_

{ "reserved": "/" }

{reserved}

%2F

{ "pct_encoded": "%2F" }

{pct_encoded}

%252F

{ "x": "1024", "y" : "768" }

{x,y}

1024/y768

{ "list": [ "red", "green", "blue" ] }

{list}

red,green,blue

{ "list": [ "red", "green", "blue" ] }

{list*}

red,green,blue

{ "map": { "firstName": "Dale", "lastName": "Cooper" } }

{map}

firstName,Dale,lastName,Cooper

{ "map": { "firstName": "Dale", "lastName": "Cooper" } }

{map*}

firstName=Dale,lastName=Cooper

路径段展开

路径段展开对于创建分层 URI 路径很有用。

  • 语法: {/varname}

  • 允许的字符: 非保留

变量 模板 URI

{ "who": "fred" }

{/who}

/fred

{ "unreserved": "_" }

{/unreserved}

/_

{ "reserved": "/" }

{/reserved}

/%2F

{ "pct_encoded": "%2F" }

{/pct_encoded}

/%252F

{ "x": "1024", "y" : "768" }

{/x,y}

/1024/y768

{ "list": [ "red", "green", "blue" ] }

{/list}

/red,green,blue

{ "list": [ "red", "green", "blue" ] }

{/list*}

/red/green/blue

{ "map": { "firstName": "Dale", "lastName": "Cooper" } }

{/map}

/firstName,Dale,lastName,Cooper

{ "map": { "firstName": "Dale", "lastName": "Cooper" } }

{/map*}

/firstName=Dale/lastName=Cooper

表单式查询展开

表单式查询展开对于创建查询字符串很有用。

  • 语法: {?varname}

  • 允许的字符: 非保留

变量 模板 URI

{ "who": "fred" }

{?who}

?who=fred

{ "unreserved": "_" }

{?unreserved}

?unreserved=_

{ "reserved": "/" }

{?reserved}

?reserved=%2F

{ "pct_encoded": "%2F" }

{?pct_encoded}

?pct_encoded=%252F

{ "x": "1024", "y" : "768" }

{?x,y}

?x=1024&y768

{ "list": [ "red", "green", "blue" ] }

{?list}

?list=red,green,blue

{ "list": [ "red", "green", "blue" ] }

{?list*}

?list=red&list=green&list=blue

{ "map": { "firstName": "Dale", "lastName": "Cooper" } }

{?map}

?map=firstName,Dale,lastName,Cooper

{ "map": { "firstName": "Dale", "lastName": "Cooper" } }

{?map*}

?firstName=Dale&lastName=Cooper

表单式查询延续

表单式查询延续对于附加到查询字符串很有用。

  • 语法: {&varname}

  • 允许的字符: 非保留

变量 模板 URI

{ "who": "fred" }

{&who}

&who=fred

{ "unreserved": "_" }

{&unreserved}

&unreserved=_

{ "reserved": "/" }

{&reserved}

&reserved=%2F

{ "pct_encoded": "%2F" }

{&pct_encoded}

&pct_encoded=%252F

{ "x": "1024", "y" : "768" }

{&x,y}

&x=1024&y768

{ "list": [ "red", "green", "blue" ] }

{&list}

&list=red,green,blue

{ "list": [ "red", "green", "blue" ] }

{&list*}

&list=red&list=green&list=blue

{ "map": { "firstName": "Dale", "lastName": "Cooper" } }

{&map}

&map=firstName,Dale,lastName,Cooper

{ "map": { "firstName": "Dale", "lastName": "Cooper" } }

{&map*}

&firstName=Dale&lastName=Cooper

保留展开

将简单字符串展开的允许字符集扩展到保留集和百分比编码序列。

  • 语法: {+varname}

  • 允许的字符: 非保留集、保留集和百分比编码序列。

变量 模板 URI

{ "who": "fred" }

{+who}

fred

{ "unreserved": "_" }

{+unreserved}

_

{ "reserved": "/" }

{+reserved}

/

{ "pct_encoded": "%2F" }

{+pct_encoded}

%2F

{ "x": "1024", "y" : "768" }

{+x,y}

1024,y768

{ "list": [ "red", "green", "blue" ] }

{+list}

red,green,blue

{ "list": [ "red", "green", "blue" ] }

{+list*}

red,green,blue

{ "map": { "firstName": "Dale", "lastName": "Cooper" } }

{+map}

firstName,Dale,lastName,Cooper

{ "map": { "firstName": "Dale", "lastName": "Cooper" } }

{+map*}

firstName=Dale,lastName=Cooper

片段展开

类似于以 # 为前缀的保留展开。

  • 语法: {#varname}

  • 允许的字符: 非保留集、保留集和百分比编码

变量 模板 URI

{ "who": "fred" }

{#who}

#fred

{ "unreserved": "_" }

{#unreserved}

#_

{ "reserved": "/" }

{#reserved}

#/

{ "pct_encoded": "%2F" }

{#pct_encoded}

#%2F

{ "x": "1024", "y" : "768" }

{#x,y}

#1024,y768

{ "list": [ "red", "green", "blue" ] }

{#list}

#red,green,blue

{ "list": [ "red", "green", "blue" ] }

{#list*}

#red,green,blue

{ "map": { "firstName": "Dale", "lastName": "Cooper" } }

{#map}

#firstName,Dale,lastName,Cooper

{ "map": { "firstName": "Dale", "lastName": "Cooper" } }

{#map*}

#firstName=Dale,lastName=Cooper

带点前缀的标签展开

  • 语法: {.varname}

  • 允许的字符: 非保留

变量 模板 URI

{ "who": "fred" }

{.who}

.fred

{ "unreserved": "_" }

{.unreserved}

._

{ "reserved": "/" }

{.reserved}

.%2F

{ "pct_encoded": "%2F" }

{.pct_encoded}

.%252F

{ "x": "1024", "y" : "768" }

{.x,y}

.1024.y768

{ "list": [ "red", "green", "blue" ] }

{.list}

.red,green,blue

{ "list": [ "red", "green", "blue" ] }

{.list*}

.red.green.blue

{ "map": { "firstName": "Dale", "lastName": "Cooper" } }

{.map}

.firstName,Dale,lastName,Cooper

{ "map": { "firstName": "Dale", "lastName": "Cooper" } }

{.map*}

.firstName=Dale.lastName=Cooper

路径式参数展开

  • 语法: {.varname}

  • 允许的字符: 非保留

变量 模板 URI

{ "who": "fred" }

{;who}

;who=fred

{ "unreserved": "_" }

{;unreserved}

;unreserved=_

{ "reserved": "/" }

{;reserved}

;reserved=%2F

{ "pct_encoded": "%2F" }

{;pct_encoded}

;pct_encoded=%252F

{ "x": "1024", "y" : "768" }

{;x,y}

;x=1024;y=y768

{ "list": [ "red", "green", "blue" ] }

{;list}

;list=red,green,blue

{ "list": [ "red", "green", "blue" ] }

{;list*}

;list=red;list=green;list=blue

{ "map": { "firstName": "Dale", "lastName": "Cooper" } }

{;map}

;map=firstName,Dale,lastName,Cooper

{ "map": { "firstName": "Dale", "lastName": "Cooper" } }

{;map*}

;firstName=Dale;lastName=Cooper

字符集备忘单

保留集

!*'();:@&=+$,/?#[]

非保留集

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.~