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>

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

SpringMVC 解析(五)URI链接处理的更多相关文章

  1. C语言文件操作解析(五)之EOF解析(转载)

      C语言文件操作解析(五)之EOF解析 在C语言中,有个符号大家都应该很熟悉,那就是EOF(End of File),即文件结束符.但是很多时候对这个理解并不是很清楚,导致在写代码的时候经常出错,特 ...

  2. Celery 源码解析五: 远程控制管理

    今天要聊的话题可能被大家关注得不过,但是对于 Celery 来说确实很有用的功能,曾经我在工作中遇到这类情况,就是我们将所有的任务都放在同一个队列里面,然后有一天突然某个同学的代码写得不对,导致大量的 ...

  3. dubbo源码解析五 --- 集群容错架构设计与原理分析

    欢迎来我的 Star Followers 后期后继续更新Dubbo别的文章 Dubbo 源码分析系列之一环境搭建 博客园 Dubbo 入门之二 --- 项目结构解析 博客园 Dubbo 源码分析系列之 ...

  4. springmvc 解析xml数据

    springmvc 解析xml数据 http://blog.csdn.net/zhi_jun/article/details/37925475

  5. Spring Security 解析(五) —— Spring Security Oauth2 开发

    Spring Security 解析(五) -- Spring Security Oauth2 开发   在学习Spring Cloud 时,遇到了授权服务oauth 相关内容时,总是一知半解,因此决 ...

  6. IDEA 之 ERROR:无法在web.xml或使用此应用程序部署的jar文件中解析绝对uri:[http://java.sun.com/jsp/jstl/core]

    问题描述:在使用IDEA对JSTL进行测试时出现error:无法在web.xml或使用此应用程序部署的jar文件中解析绝对uri:[http://java.sun.com/jsp/jstl/core] ...

  7. SpringMVC 教程 - URI 链接

    原文链接:https://www.codemore.top/cates/Backend/post/2018-04-22/spring-mvc-uri-links 这一节主要讲的是Spring Fram ...

  8. Java 面试知识点解析(五)——网络协议篇

    前言: 在遨游了一番 Java Web 的世界之后,发现了自己的一些缺失,所以就着一篇深度好文:知名互联网公司校招 Java 开发岗面试知识点解析 ,来好好的对 Java 知识点进行复习和学习一番,大 ...

  9. SpringMVC解析5-DispatcherServlet逻辑细节

    MultipartContent类型的request处理 对于请求的处理,spring首先考虑的是对于Multipart的处理,如果是MultipartContent类型的request,则转换req ...

随机推荐

  1. 编程篇——Java学习路线

    1.java基础编程2.Java多线程编程(并发)3.Java设计模式(重构)4.Java调试技术(Java虚拟机)5.Java常用框架学习篇6.Java开发之web篇

  2. sqli-labs下载与安装

    Sqli-labs 下载 Sqli-labs是一个印度程序员写的,用来学习sql注入的一个游戏教程. 博客地址为:http://dummy2dummies.blogspot.hk/, 博客当中有一些示 ...

  3. (一)【转】asp.net mvc生成验证码

    网站添加验证码,主要为防止机器人程序批量注册,或对特定的注册用户用特定程序暴力破解方式,以进行不断的登录.灌水等危害网站的操作.验证码被广泛应用在注册.登录.留言等提交信息到服务器端处理的页面中.   ...

  4. SolidWorks在一个零件中设置不同的尺寸版本

    问题 比如想设置一系列螺丝的长度,一个一个建零件非常麻烦,希望在一个零件中设置不同的长度尺寸版本 解决 比如想设置不同的拉伸长度,右键拉伸>配置特征 可以生成新配置,设置不同的D1参数,即可生成 ...

  5. path()和re_path()用法&区别

    path() 参数列表: 参数1:字符串类型,用来匹配请求路径 参数2:指定路径所对应的视图函数名 参数3:关键字参数 实际用的不多 参数4... # urls.py # 创建子应用的路由文件 fro ...

  6. 什么是BGP

    BGP概述 边界网关协议(BGP)是运行于TCP协议上的一种自治系统的路由协议. 是一种外部路由协议. AS概述 自治系统(AS),指的是同一个使用相同策略的设备的集合. 每个AS有自己位移的编号,不 ...

  7. (转)String,StringBuilder,StringBuffer区别

    Java中的String,StringBuilder,StringBuffer三者的区别 注:转自-博客园-酥风 最近在学习Java的时候,遇到了这样一个问题,就是String,StringBuild ...

  8. 什么是SpringCloudConfig?

    在分布式系统中,由于服务数量巨多,为了方便服务配置文件统一管理,实时更新,所以需要分布式配置中心组件.在Spring Cloud中,有分布式配置中心组件spring cloud config ,它支持 ...

  9. 百度地图Api使用常见问题

    引用 百度地图API文档 百度地图使用文档 使用 LocalSearch 控件搜索出来的Marker无法点击的问题或者导致第一个Marker标注的信息框关闭后Label消失 解决方法就是使用 onMa ...

  10. 如果在拦截请求中,我想拦截get方式提交的方法,怎么配置?

    可以在@RequestMapping注解里面加上method=RequestMethod.GET.