UriComponentsBuilder 拼接URL、解析URL
前言
- 关于URI参考这里。
- springboot 2.1.1.RELEASE
UriComponentsBuilder
- UriComponentsBuilder 是UriBuilder的实现。针对Servlet,还派生出来ServletUriComponentsBuilder。
- 使用过UriComponentsBuilder 的都知道,很好用
快速来个示例
String url = UriComponentsBuilder.fromUriString("http://mydomain/api/getToken").queryParam("appid", "123").queryParam("appsecret", "secret123").build().encode().toString();
System.out.println(url);
- 这段代码可以得到:
http://mydomain/api/getToken?appid=123&appsecret=secret123
- 这段代码实际做了几件事:
- 实例化 UriComponentsBuilder 。
UriComponentsBuilder.fromUriString("http://mydomain/api/getToken")
- 设置 UriComponentsBuilder 实例。
.queryParam("appid", "123").queryParam("appsecret", "secret123")
- 创建 UriComponents 实例。
.build()
- 设置 UriComponents 实例。
.encode()
- UriComponents 实例转成字符串。
.toString()
- 实例化 UriComponentsBuilder 。
实例化 UriComponentsBuilder 的方法
UriComponentsBuilder 提供的实例化 UriComponentsBuilder 的方法
public static UriComponentsBuilder newInstance();
public static UriComponentsBuilder fromPath(String path);
public static UriComponentsBuilder fromUri(URI uri);
public static UriComponentsBuilder fromUriString(String uri);
public static UriComponentsBuilder fromHttpUrl(String httpUrl);
public static UriComponentsBuilder fromHttpRequest(HttpRequest request);
public static UriComponentsBuilder fromOriginHeader(String origin);
ServletUriComponentsBuilder 提供的实例化 UriComponentsBuilder 的方法
public static ServletUriComponentsBuilder fromContextPath(HttpServletRequest);
public static ServletUriComponentsBuilder fromServletMapping(HttpServletRequest);
public static ServletUriComponentsBuilder fromRequest(HttpServletRequest);
public static ServletUriComponentsBuilder fromCurrentContextPath();
public static ServletUriComponentsBuilder fromCurrentServletMapping();
public static ServletUriComponentsBuilder fromCurrentRequest();
设置 UriComponentsBuilder 实例
赋值
.queryParam("appid", "123")
重复赋值
.queryParam("appid", "123")
.queryParam("appid", "234")
- appid 会变为[“123”, “234”]
替换
.queryParam("appid", "123")
.replaceQueryParam("appid", "234")
- appid 变为234
路径
.path("a")
.path("b")
.path("c")
- xxx/a/b/c
替换路径
.path("a")
.path("b")
.path("c")
.replacePath("d")
- xxx/d
更多
略。
关于urlencode
前面示例中.build()
中得到的是 UriComponents 派生类(HierarchicalUriComponents
)的实例。
HierarchicalUriComponents 类的实例在.encode()
时,使用HierarchicalUriComponents.encodeUriComponent()
方法进行 url 编码。其编码方式与java.net.URLEncoder
的实现不同。
总结一下(代码参考测试代码1
):
代码 | 结果 | 特征 | 遵循协议 |
---|---|---|---|
URLEncoder.encode(“1 + 2 = 3”, “utf-8”); | 1+%2B+2+%3D+3 | 空格转义成+;+转义成%2B | W3C标准规定 |
HierarchicalUriComponents.encodeUriComponent(“1 + 2 = 3”, “utf-8”,Type.QUERY_PARAM); | 1%20+%202%20%3D%203 | 空格转义成%20;+不变 | RFC 3986 |
用哪个对呢?都对!!!但,要看提供服务的应用支持哪个。我的建议是,都试试,哪个能用用哪个。
如何让 URLEncoder 支持 空格转义成%20;+不变
呢?
参考这里:https://blog.csdn.net/qq_43566496/article/details/84935364
如何让 HierarchicalUriComponents 支持 空格转义成+;+转义成%2B
呢?
方法1
String url = UriComponentsBuilder.fromUriString("http://mydomain/api/getToken").queryParam("appid", "123").queryParam("appsecret", "secret123").queryParam("q", URLEncoder.encode("1 + 2 = 3")).build(true).encode().toString();
System.out.println(url);
.build(true)
告诉UriComponents
我已经做过uri编码了,你就不要再做uri编码了。
方法2
String url = UriComponentsBuilder.fromUriString("http://mydomain/api/getToken").queryParam("appid", "123").queryParam("appsecret", "secret123").queryParam("q", URLEncoder.encode("1 + 2 = 3")).build().toString();
System.out.println(url);
- 去掉
.encode()
,UriComponents
就不要再做uri编码了。
spring 提供的支持 RFC 2396、RFC 3986 的类: UriUtils
https://docs.spring.io/spring-framework/docs/3.0.x/javadoc-api/org/springframework/web/util/UriUtils.html
测试代码1
import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.Charset;import org.springframework.util.Assert;
import org.springframework.util.StreamUtils;
import org.springframework.util.StringUtils;public class Test {public static void main(String[] args) throws UnsupportedEncodingException {System.out.println(URLEncoder.encode("1 + 2 = 3", "utf-8"));System.out.println(encodeUriComponent("1 + 2 = 3", Charset.forName("utf-8"), Type.QUERY_PARAM));}/*HierarchicalUriComponents.encodeUriComponent() 方法的高仿实现*/static String encodeUriComponent(String source, Charset charset, Type type) {if (!StringUtils.hasLength(source)) {return source;}Assert.notNull(charset, "Charset must not be null");Assert.notNull(type, "Type must not be null");byte[] bytes = source.getBytes(charset);boolean original = true;for (byte b : bytes) {if (!type.isAllowed(b)) {original = false;break;}}if (original) {return source;}ByteArrayOutputStream baos = new ByteArrayOutputStream(bytes.length);for (byte b : bytes) {if (type.isAllowed(b)) {baos.write(b);}else {baos.write('%');char hex1 = Character.toUpperCase(Character.forDigit((b >> 4) & 0xF, 16));char hex2 = Character.toUpperCase(Character.forDigit(b & 0xF, 16));baos.write(hex1);baos.write(hex2);}}return StreamUtils.copyToString(baos, charset);}enum Type {QUERY {@Overridepublic boolean isAllowed(int c) {return isPchar(c) || '/' == c || '?' == c;}},QUERY_PARAM {@Overridepublic boolean isAllowed(int c) {if ('=' == c || '&' == c) {return false;}else {return isPchar(c) || '/' == c || '?' == c;}}};/*** Indicates whether the given character is allowed in this URI component.* @return {@code true} if the character is allowed; {@code false} otherwise*/public abstract boolean isAllowed(int c);/*** Indicates whether the given character is in the {@code ALPHA} set.* @see <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986, appendix A</a>*/protected boolean isAlpha(int c) {return (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z');}/*** Indicates whether the given character is in the {@code DIGIT} set.* @see <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986, appendix A</a>*/protected boolean isDigit(int c) {return (c >= '0' && c <= '9');}/*** Indicates whether the given character is in the {@code sub-delims} set.* @see <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986, appendix A</a>*/protected boolean isSubDelimiter(int c) {return ('!' == c || '$' == c || '&' == c || '\'' == c || '(' == c || ')' == c || '*' == c || '+' == c ||',' == c || ';' == c || '=' == c);}/*** Indicates whether the given character is in the {@code unreserved} set.* @see <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986, appendix A</a>*/protected boolean isUnreserved(int c) {return (isAlpha(c) || isDigit(c) || '-' == c || '.' == c || '_' == c || '~' == c);}/*** Indicates whether the given character is in the {@code pchar} set.* @see <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986, appendix A</a>*/protected boolean isPchar(int c) {return (isUnreserved(c) || isSubDelimiter(c) || ':' == c || '@' == c);}}
}
String url = UriComponentsBuilder.fromUriString("http://api.fanyi.baidu.com/api/trans/vip/translate").queryParam("appid", appid).queryParam("q", encode(query)).queryParam("from", from).queryParam("to", to).queryParam("salt", salt).queryParam("sign", sign).build(true).encode().toString();
参考
https://www.cnblogs.com/zhengxl5566/p/10783422.html
https://www.cnblogs.com/zhengxl5566/p/13492602.html
https://www.cnblogs.com/siqi/p/10070926.html
UriComponentsBuilder 拼接URL、解析URL相关推荐
- Python3 URL格式化url解析url提取参数
我们一般见到的url地址都是字符串形式,例如: http://api.bilibili.com/x/web-interface/view?aid=44699780 请求协议: http 请求域名:ap ...
- yy神曲url解析php_使用PHP来简单的创建一个RPC服务
RPC全称为Remote Procedure Call,翻译过来为"远程过程调用".主要应用于不同的系统之间的远程通信和相互调用. 比如有两个系统,一个是PHP写的,一个是JAVA ...
- python3 url解析 urllib.parse.urlparse 库简介
urllib.parse - 将URL解析为组件 urllib.parse定义了一个标准接口,用于在组件中解析统一资源定位符(URL)字符串(寻址方案,网络位置,路径等),将组件组合回URL字符串,并 ...
- url参数拼接 php,PHP解析url并得到url参数方法总结
PHP 中解析 url 并得到 url 参数 这里介绍两种对url操作的方法: 1.拿到一个完整url后,如何解析该url得到里面的参数. /** * 解析url中参数信息,返回参数数组 */ fun ...
- python爬虫基础扫盲之urllib.pase解析URL
在笨方法"学习python笔记之urlopen,中提了urllib主要是提供打开网页,解析url等功能用于网络爬虫,其lib主要包含四个部分,其中urllib.parse主要是负责url的解 ...
- js常用方法,JS实用方法,jq获得文件后缀,解析window。location,解析URL参数
jq获取文件后缀的方法 var file = "测试文档1111111111.docx"; // 文件 var fileName = file.replace(/.*(\/|\\) ...
- window对象(一) 计时器 定位导航 url解析 浏览历史 对话框 消息推送
window对象 计时器 一个jQuery作者的写的关于定时器解释,记的顺手订阅一下.John Resig,jQuery之父 https://johnresig.com/blog/how-javasc ...
- python url解析path_Django(CBV解析、模板层)
https://www.zhihu.com/video/1249450287595159552 每日测验 """ 今日考题 1.反向解析的本质是什么,无名和有名反向解析如 ...
- python url解析_Python中实现URL的解析
在Python中的urlparse模块主要是用于解析url中的参数 对url按照一定格式进行 拆分或拼接 1.urlparse.urlparse 将url分为6个部分,返回一个包含6个字符串项目的元 ...
- Go 学习笔记(50)— Go 标准库之 net/url(查询转义、查询参数增/删/改/查、解析URL)
1. URL 概述 import "net/url" url 包解析 URL 并实现了查询的转码.URL 提供了一种定位因特网上任意资源的手段,但这些资源是可以通过各种不同的方案( ...
最新文章
- 2.13 向量化 Logistic 回归-深度学习-Stanford吴恩达教授
- db2 springboot 整合_springboot的yml配置文件通过db2的方式整合mysql代码示例
- jQuery导航切换功能
- mysql如何植入到oracle_MySQL产品的生命周期
- Linux下共享内存的查看和释放
- dbv mysql_MariaDB与MySQL对比 --- 对分布式事务的支持
- microsoft fix it_it狂人【14季全】
- 如果你对web前端学习感到迷茫的话请看完本文
- 中文语音识别数据集总结
- 【工具】我的键盘(机械键盘)快捷键设置
- BZOJ 4399 魔法少女LJJ(线段树合并)
- 【背包问题】基于matlab禁忌搜索算法求解背包问题【含Matlab源码 373期】
- 2021年最佳知识库软件指南
- Linux服务器下搭建SFTP服务
- 【龙讯module小课堂】“光”怪陆离:PWmat计算光学性质(二)
- 都市鸿蒙珠认主,都市之我能穿越洪荒
- Spark广播变量与累加器
- python 数据结构常用操作
- 复制文件或文件夹时出错(无法复制***:没有足够的可用磁盘空间
- 大整理!程序员最爱的12个免费Python课程