概述

本教程将重点介绍Spring的UriComponentsBuilder。我们将描述各种实际的实现示例。

UriComponentsBuilderUriComponents类协同工作,后者是URI组件的不可变容器。

通过UriComponentsBuilder类,我们可以细致地控制URI的各个方面,包括构建、模板变量的展开以及编码。

Maven依赖

为了使用这个构建器,我们需要在pom.xmldependencies部分添加以下内容:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>5.2.2.RELEASE</version>
</dependency>

最新的版本可以在这里找到。

这个依赖仅涵盖了Spring Web,因此对于完整的Web应用,别忘了添加spring-context

当然,我们还需要为项目设置日志记录——更多内容请参考这里

用例

UriComponentsBuilder有许多实用场景,从对相应URI组件中不允许的字符进行上下文编码,到动态替换URL的某些部分。

UriComponentsBuilder的一个主要优势是我们可以直接将其注入控制器方法:

@RequestMapping(method = RequestMethod.POST)
public ResponseEntity createCustomer(UriComponentsBuilder builder) {
    // implementation
}

现在让我们逐一描述有用的示例,并立即使用JUnit框架进行测试。

3.1. 构建URI

我们从最简单的开始。我们想要使用UriComponentsBuilder创建一个简单的链接:

@Test
public void constructUri() {
    UriComponents uriComponents = UriComponentsBuilder.newInstance()
      .scheme("http").host("www.baeldung.com").path("/junit-5").build();

    assertEquals("/junit-5", uriComponents.toUriString());
}

我们可以看到,我们创建了一个新的UriComponentsBuilder实例,然后提供了协议类型、主机和请求目的地的路径。

当需要重定向到网站的其他部分或链接时,这个简单的示例可能很有用。

3.2. 构建编码URI

除了创建简单链接外,我们可能还希望对最终结果进行编码。让我们看看实际操作:

@Test
public void constructUriEncoded() {
    UriComponents uriComponents = UriComponentsBuilder.newInstance()
      .scheme("http").host("www.baeldung.com").path("/junit 5").build().encode();

    assertEquals("/junit%205", uriComponents.toUriString());
}

在这个例子中,我们想在单词junit和数字5之间添加空格。根据RFC 3986,这通常是不允许的。我们需要对链接进行编码,以获得有效结果,使用encode()方法。

3.3. 从模板构建URI

URI模板允许在URI的大多数部分中使用,但它们的值被限制在特定元素上,我们用括号{…}表示。让我们看一个例子来说明:

@Test
public void constructUriFromTemplate() {
    UriComponents uriComponents = UriComponentsBuilder.newInstance()
      .scheme("http").host("www.baeldung.com").path("/{article-name}")
      .buildAndExpand("junit-5");

    assertEquals("/junit-5", uriComponents.toUriString());
}

在这个例子中,我们声明路径的方式不同,以及如何构建最终的URI。模板将在path()方法中用关键字替换的部分由方括号{…}表示。用于生成最终链接的关键字在名为buildAndExpand(…)的方法中使用。

请注意,可能有多个关键字需要替换。URI的路径可以是相对的。

当想要基于传递给Spring控制器的模型对象构建URI时,这个示例非常有用。

3.4. 使用查询参数构建URI

另一个非常有用的情况是创建带有查询参数的URI。

我们需要使用UriComponentsBuilderquery()方法指定URI查询参数。以下是示例:

@Test
public void constructUriWithQueryParameter() {
    UriComponents uriComponents = UriComponentsBuilder.newInstance()
      .scheme("http").host("www.google.com")
      .path("/").query("q={keyword}").buildAndExpand("baeldung");

     assertEquals("http://www.google.com/?q=baeldung", uriComponents.toUriString());
}

查询将被添加到链接的主要部分。我们可以使用方括号{…}提供多个查询参数,它们将在buildAndExpand(…)方法中用关键字替换。

这种UriComponentsBuilder的实现可用于构建REST API的查询语言。

3.5. 使用正则表达式扩展URI

最后一个示例展示了使用正则表达式验证构建URI的情况。只有在正则表达式验证成功后,我们才能扩展uriComponents

@Test
public void expandWithRegexVar() {
    String template = "/myurl/{name:[a-z]{1,5}}/show";
    UriComponents uriComponents = UriComponentsBuilder.fromUriString(template)
      .build();
    uriComponents = uriComponents.expand(Collections.singletonMap("name", "test"));
 
    assertEquals("/myurl/test/show", uriComponents.getPath());
}

在上述示例中,我们可以看到链接的中间部分只能包含小写字母,长度在1-5范围内。

此外,我们使用了singletonMap,将关键词name替换为test

当允许用户动态指定链接,但又想为我们的Web应用提供某种安全措施(只允许有效的链接工作)时,这个示例特别有用。

总结

本教程展示了UriComponentsBuilder的实用示例。

UriComponentsBuilder的主要优点是使用URI模板变量的灵活性,以及直接注入Spring控制器方法的可能性。

所有示例和配置可在GitHub上找到。