• 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>
    

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

  • 相关阅读:
    上传文件sftp和base 64上传的优缺点?
    电脑监控软件:保护企业核心信息资产,防止数据泄露
    Qt5开发从入门到精通——第四篇(标准字体对话框类 getFont())
    Web前端系列技术之JavaScript基础(从入门开始)⑤
    江湖再见,机器视觉兄弟们,我已经提离职了,聪明的机器视觉工程师,离职不亏本!
    Linux下安装Mysql5.7,超详细完整教程,以及云mysql连接
    三菱FX3U小项目—机床定时器延时启动
    周少剑,很少见
    Axios
    Spring Boot虚拟线程与Webflux在JWT验证和MySQL查询上的性能比较
  • 原文地址:https://www.cnblogs.com/yuhushen/p/16125186.html