• SpringMVC 教程


    原文链接:https://www.codemore.top/cates/Backend/post/2018-04-22/spring-mvc-uri-links

    这一节主要讲的是Spring Framework组成URI的各种选项。

    UriComponents

    UriComponentsjava.net.URI类似。但是UriComponents有一个专用的UriComponentsBuilder来构建,并且支持模版变量。例如

    String uriTemplate = "http://example.com/hotels/{hotel}";
    
    UriComponents uriComponents = UriComponentsBuilder.fromUriString(uriTemplate)  1
            .queryParam("q", "{q}")  2
            .build(); 3
    
    URI uri = uriComponents.expand("Westin", "123").encode().toUri(); 4

    解释:

    1. 包含URI模版的静态工厂方法
    2. 添加或者替代URI组件
    3. 构建UriComponents
    4. 扩展URI变量,编码获取URI变量

    上述步骤合起来可以如下表示:

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

    UriComponentsBuilderUriBuilder的子类。UriBuilderFactoryUriBuilder合在一起提供了通过URI模版获取URI的一套可插拔的机制,同样也提供了一种共享公共属性,基础URI,编码策略等的方式。 RestTemplateWebClient都可以通过UriBuilderFactory配置。默认实现依赖于内部的UriComponentsBuilder,同时提供选项配置基础URI,编码策略等。 RestTemplate方式:

    String baseUrl = "http://example.com";
    DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(baseUrl);
    
    RestTemplate restTemplate = new RestTemplate();
    restTemplate.setUriTemplateHandler(factory);

    WebClient方式:

    String baseUrl = "http://exaplme.com";
    DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(baseUrl);
    
    // Configure the UriBuilderFactory..
    WebClient client = WebClient.builder().uriBuilderFactory(factory).build();
    
    // Or use shortcut on builder..
    WebClient client = WebClient.builder().baseUrl(baseUrl).build();
    
    // Or use create shortcut...
    WebClient client = WebClient.create(baseUrl);

    同样像直接使用UriComponentsBuilder一样,也可以直接使用DefaultUriBuilderFactory。唯一的区别是DefaultUriBuilderFactory是无状态的,并且可以重用。例如:

    String baseUrl = "http://example.com";
    DefaultUriBuilderFactory uriBuilderFactory = new DefaultUriBuilderFactory(baseUrl);
    
    URI uri = uriBuilderFactory.uriString("/hotels/{hotel}")
            .queryParam("q", "{q}")
            .build("Westin", "123"); // encoding strategy applied..
    URI 编码

    UriComponets中编码URI的步骤如下:

    1. 扩展URI变量
    2. 每个URI组件(path,query等)都单独编码

    编码规则如下:对所有非法字符应用百分号编码方式,包括非ASCII的字符和在RFC 3986中定义的非法字符。 上述编码规则并没有对有保留意义的字符编码,只是对URI组件中的非法字符尽心编码,如果想要对其编码,可以修改编码策略使其全部编码。 当使用 DefaultUriBuilderFactory(在WebClient,RestTemplate中使用或者直接使用)时可以如下选择编码方式:

    String baseUrl = "http://example.com";
    DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(baseUrl)
    factory.setEncodingMode(EncodingMode.VALUES_ONLY);
    Servlet 请求

    可以使用ServletUriComponentsBuilder来创建相对于当前请求的URI,例如:

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

    创建相对于当前context的URI

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

    创建相对于Servlet(例如:/main/*)的URI

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

    Spring MVC使用MvcUriComponentsBuilder为controller创建链接,例如由如下一个controller:

    @Controller
    @RequestMapping("/hotels/{hotel}")
    public class BookingController {
    
        @GetMapping("/bookings/{booking}")
        public String getBooking(@PathVariable Long booking) {
            // ...
        }
    }

    可以根据名字来生成一个链接:

    UriComponents uriComponents = MvcUriComponentsBuilder
        .fromMethodName(BookingController.class, "getBooking", 21).buildAndExpand(42);
    
    URI uri = uriComponents.encode().toUri();

    在上面这个例子中,直接提供了函数的参数值,21被赋值给路径变量,42赋值给从类的@RequestMapping继承过来的查询参数{hotel}。 MvcUriComponentsBuilder的另一个用处是可以mock一个测试,例如:

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

    上面的例子大多数情况下运行良好,但是也有不足,例如:可能会在request上下文外创建uri,或者是需要插入一个路径前缀(比如测试的时候通过前缀测试,但是正式上线后直接是根(/))。对于这种情况可以使用静态函数fromXxx这种进行处理:

    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();
    视图中的链接

    可以通过MvcUriComponentsBuilderfromMappingName在视图(例如:JSP,Thymleaf,FreeMarker等)中构建指向controller的链接。 每个@RequestMapping的方法都会有一个名字,这个名字基于controller类名的大些字母加上‘#’号再加上方法名构成,例如,FooController类中的getFoo方法的名字就是FC#getFoo。当然这个可以通过修改HandlerMethodMappingNamingStrategy来定制其名字。默认策略同样也会去查找@RequestMapping中设置名字的属性,如果提供了,则会使用其设置的名字。 Spring JSP的tag库提供了一个mvcUrl的方法,这个可以用来构建指向controller的方法。例如有如下controller:

    @RequestMapping("/people/{id}/addresses")
    public class PersonAddressController {
    
        @RequestMapping("/{country}")
        public HttpEntity getAddress(@PathVariable String country) { ... }
    }

    JSP中可以如下来构建指向其URI

    <%@ taglib uri="http://www.springframework.org/tags" prefix="s" %>
    ...
    <a href="${s:mvcUrl('PAC#getAddress').arg(0,'US').buildAndExpand('123')}">Get Address</a>
  • 相关阅读:
    John Resig 见面会视频
    《程序员羊皮卷》书评
    用 JavaScript 对 JSON 进行模式匹配 (Part 2 实现)
    工具:开发者使用,企业埋单
    「云端 JavaScript 漫游指南」
    如何让你的网站支持 IE9 Pinned Site (Part 1 理论)
    世界顶级黑客自传:Ghost in the Wires
    MVP Summit 2010 Trip (WA)
    Apple 谈论产品 vs Microsoft 谈论技术
    IBatisNet开发使用小结 之二
  • 原文地址:https://www.cnblogs.com/hitandrew/p/8944759.html
Copyright © 2020-2023  润新知