百木园-与人分享,
就是让自己快乐。

SpringMVC 解析(五)URI链接处理

URI在网络请求中必不可少,Spring提供了一些工具类用于解析或者生成URL,比如根据参数生成GET的URL等。本文会对Spring MVC中的URI工具进行介绍,本文主要参考Spring官方文档。

工具类UriComponents

UriComponentsBuilder可以用于根据URL和参数来构建路径,比如我们需要一个带GET参数的URL,通常情况下我们需要自己去拼接URL,添加\"&\"和\"?等参数\"。UriComponentsBuilder提供一种更简介的方法去构建URL:

UriComponents uriComponents = UriComponentsBuilder
        .fromUriString(\"https://example.com/hotels/{hotel}\")  
        .queryParam(\"q\", \"{q}\")  
        .encode() 
        .build(); 

// https://example.com/hotels/Westin?q=123
URI uri = uriComponents.expand(\"Westin\", \"123\").toUri();  

上面的两条语句也可以合并到一个Build链中,用如下方式达到同样的目的:

URI uri = UriComponentsBuilder
        .fromUriString(\"https://example.com/hotels/{hotel}\")
        .queryParam(\"q\", \"{q}\")
        .encode()
        .buildAndExpand(\"Westin\", \"123\")
        .toUri();

URI uri = UriComponentsBuilder
        .fromUriString(\"https://example.com/hotels/{hotel}\")
        .queryParam(\"q\", \"{q}\")
        .build(\"Westin\", \"123\");

URI uri = UriComponentsBuilder
        .fromUriString(\"https://example.com/hotels/{hotel}?q={q}\")
        .build(\"Westin\", \"123\");

接口UriBuilder

UriComponentsBuilder实现了UriBuilder接口,该接口的主要功能就是构建Uri。Spring中可以通过UriBuilderFactory获取UriBuilder的实例。我们平时使用httpClient类如Spring的RestTemplate,并不需要自己拼接Uri,只需要输入参数组件会自动拼接Url。对于过Spring的RestTemplate,其内部使用的Url组件就是UriBuilderFactory。

// import org.springframework.web.util.DefaultUriBuilderFactory.EncodingMode;

String baseUrl = \"https://example.org\";
DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(baseUrl);
factory.setEncodingMode(EncodingMode.TEMPLATE_AND_VALUES);

RestTemplate restTemplate = new RestTemplate();
restTemplate.setUriTemplateHandler(factory);

// import org.springframework.web.util.DefaultUriBuilderFactory.EncodingMode;

String baseUrl = \"https://example.org\";
DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(baseUrl);
factory.setEncodingMode(EncodingMode.TEMPLATE_AND_VALUES);

WebClient client = WebClient.builder().uriBuilderFactory(factory).build();
String baseUrl = \"https://example.com\";
DefaultUriBuilderFactory uriBuilderFactory = new DefaultUriBuilderFactory(baseUrl);

URI uri = uriBuilderFactory.uriString(\"/hotels/{hotel}\")
        .queryParam(\"q\", \"{q}\")
        .build(\"Westin\", \"123\");

Url的编码

UriComponentsBuilder组件提供了两种类型的编码方式:

  • UriComponentsBuilder#encode():对Url模板和参数分别进行编码之后进行拼接。
  • UriComponents#encode():对拼接后的Url进行编码操作。

大多数情况下适合使用UriComponentsBuilder#encode(),因为它将参数单独进行了编码。但是如果你需要在编码中保留特殊字符,那么最好使用第二种编码方式。

URI uri = UriComponentsBuilder.fromPath(\"/hotel list/{city}\")
        .queryParam(\"q\", \"{q}\")
        .encode()
        .buildAndExpand(\"New York\", \"foo+bar\")
        .toUri();

// Result is \"/hotel%20list/New%20York?q=foo%2Bbar\"

Servlet Uri构建

Spring提供了另一个Uri组件ServletUriComponentsBuilder,该组件可以基于Servlet请求构建新的Uri:

HttpServletRequest request = ...

// Re-uses host, scheme, port, path and query string...
ServletUriComponentsBuilder ucb = ServletUriComponentsBuilder.fromRequest(request)
        .replaceQueryParam(\"accountId\", \"{id}\").build()
        .expand(\"123\")
        .encode();

// Re-uses host, port and context path...
ServletUriComponentsBuilder ucb = ServletUriComponentsBuilder.fromContextPath(request).path(\"/accounts\").build()

// Re-uses host, port, context path, and Servlet prefix...
ServletUriComponentsBuilder ucb = ServletUriComponentsBuilder.fromServletMapping(request).path(\"/accounts\").build()

Controller Uri

我们知道Spring中可以通过@RequestMapping把一个请求映射到Controller的方法上,那么我们如何获取到Controller方法的请求路径呢?

@Controller
@RequestMapping(\"/hotels/{hotel}\")
public class BookingController {

    @GetMapping(\"/bookings/{booking}\")
    public ModelAndView getBooking(@PathVariable Long booking) {
        // ...
    }
}

Spring 提供了MvcUriComponentsBuilder工具获取Controller方法对应的路径,其使用示例如下所示:

// 21:指明参数的类型, 42:新的参数类型. 
UriComponents uriComponents = MvcUriComponentsBuilder
    .fromMethodName(BookingController.class, \"getBooking\", 21).buildAndExpand(42);

URI uri = uriComponents.encode().toUri();

UriComponents uriComponents = MvcUriComponentsBuilder
    .fromMethodCall(on(BookingController.class).getBooking(21)).buildAndExpand(42);

URI uri = uriComponents.encode().toUri();

Controller方法应该是非Final的,否则Spring可能会获取不到配置的路径信息。

MvcUriComponentsBuilder 还支持指定Context,如域名等信息,示例如下所示:

UriComponentsBuilder base = ServletUriComponentsBuilder.fromCurrentContextPath().path(\"/en\");
MvcUriComponentsBuilder builder = MvcUriComponentsBuilder.relativeTo(base);
builder.withMethodCall(on(BookingController.class).getBooking(21)).buildAndExpand(42);

URI uri = uriComponents.encode().toUri();

视图中的URL

在Thymeleaf、FreeMarker和JSP等视图组件中,我们可以通过视图URL组件去拼接URL,示例如下:

@RequestMapping(\"/people/{id}/addresses\")
public class PersonAddressController {

    @RequestMapping(\"/{country}\")
    public HttpEntity<PersonAddress> getAddress(@PathVariable String country) { ... }
}
<%@ taglib uri=\"http://www.springframework.org/tags\" prefix=\"s\" %>
...
<a href=\"${s:mvcUrl(\'PAC#getAddress\').arg(0,\'US\').buildAndExpand(\'123\')}\">Get Address</a>

本文最先发布至微信公众号,版权所有,禁止转载!


来源:https://www.cnblogs.com/yuhushen/p/16125186.html
本站部分图文来源于网络,如有侵权请联系删除。

未经允许不得转载:百木园 » SpringMVC 解析(五)URI链接处理

相关推荐

  • 暂无文章