原文链接: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>

SpringMVC 教程 - URI 链接的更多相关文章

  1. SpringMVC教程3

    SpringMVC教程2 一.文件上传 1.引入相关jar包 maven坐标 <!-- fileUpload 解析上传的文件用到的jar --> <dependency> &l ...

  2. SpringMVC教程1

    一.SpringMVC介绍 1.MVC介绍 ==模型-视图-控制器(MVC== 是一个众所周知的以设计界面应用程序为基础的设计模式.它主要通过分离模型.视图及控制器在应用程序中的角色将业务逻辑从界面中 ...

  3. Java系列教程-SpringMVC教程

    SpringMVC教程 1.SpringMVC概述 1.回顾MVC 1.什么是MVC MVC是模型(Model).视图(View).控制器(Controller)的简写,是一种软件设计规范. 是将业务 ...

  4. SpringMVC教程4

    SpringMVC教程3 一.数据回写 数据回写:在做数据更新的时候服务端查询的数据自动填充到表单中. 1.1默认方式 通过前面讲解的 Map Mode ModelMap绑定数据 @RequestMa ...

  5. SpringMVC教程2

    接上篇文章-SpringMVC教程1 五.基本操作 1.响应请求的方式 1.1ModeAndView /** * 查询方法 * @return */ @RequestMapping("/qu ...

  6. SpringMvc Controller请求链接忽略大小写(包含拦截器)及@ResponseBody返回String中文乱码处理

    SpringMvc Controller请求链接忽略大小写(包含拦截器)及@ResponseBody返回String中文乱码处理... @RequestMapping(value = "/t ...

  7. SpringMVC 解析(五)URI链接处理

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

  8. SpringMVC 教程 - Handler Method

    原文链接:https://www.codemore.top/cates/Backend/post/2018-04-21/spring-mvc-handler-methods 由注解@RequestMa ...

  9. JMeter 教程汇总链接

    http://www.360doc.com/content/14/0318/23/16361380_361732630.shtml 可以作为入门系列教程. 尽管网页也给出了视频链接,但是我不建议看视频 ...

随机推荐

  1. redis 持久化之 RDB

    redis的运维过程中,我们对数据持久化做一个基本的总结. 1什么是持久化: redis 所有数据保持在内存中,对数据的更新将异步地保存到磁盘上. RDB 文件创建的过程是直接从内存 写入到我们我磁盘 ...

  2. python jquery

    jquery 一.寻找元素(选择器和筛选器) a.选择器 1.基本选择器 1 $("*")  $("#id")   $(".class")  ...

  3. html超文本标记语言的由来

    万维网上的一个超媒体文档称为一个页面:page,作为一个组织或者个人在万维网上放置开始点的页面称为主页:homepage或者首页,主页中通常有指向其他相关页面或者其他节点的指针,就是通常所说的超链接, ...

  4. urllib.parse.urlencode

    urllib.request.urlopen(url,data,timeout) 其中如果data被赋值,则请求的方式就会由get转为post,而post需要提供一些待处理的数据. 这些待处理的数据需 ...

  5. Maven 本地仓库明明有jar包,pom文件还是报错解决办法

    方法一: 找到出错的jar包文件位置,删掉_maven.repositories文件 方法二: maven中的本地仓库的index索引没有更新导致 解决方案: 在eclipse中打开菜单 window ...

  6. bootstrap——bootstrap-table(2)

    先看问题现象: 问题描述: 点击"管理子账号"按钮,预期是按照传递的参数更新列表数据,但是最后才发现这个列表根本不会刷新,只会继承前一次的数据,意思也就是不会去请求第二次. 解决方 ...

  7. [ABP]浅谈工作单元 在整个 ABP 框架当中的应用

    ABP在其内部实现了工作单元模式,统一地进行事务与连接管理. 其核心就是通过 Castle 的 Dynamic Proxy 进行动态代理,在组件注册的时候进行拦截器注入,拦截到实现了 Unit Of ...

  8. [LeetCode] Second Minimum Node In a Binary Tree 二叉树中第二小的结点

    Given a non-empty special binary tree consisting of nodes with the non-negative value, where each no ...

  9. [LeetCode] Find Largest Value in Each Tree Row 找树每行最大的结点值

    You need to find the largest value in each row of a binary tree. Example: Input: 1 / \ 3 2 / \ \ 5 3 ...

  10. Linux 在添加一个新账号后却没有权限怎么办

    当添加一个新账号后,我们可能会发现新账号sudo 时会报告不在sudoers中,使用su -s时输入密码后也会认证失败 上网搜索大部分都要求修改/etc/sudoers中的内容,但修改这个文件必须需要 ...