com.dahuatech.hutool.core.util.URLUtil Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of java-sdk-common Show documentation
Show all versions of java-sdk-common Show documentation
Dahua ICC Open API SDK for Java
package com.dahuatech.hutool.core.util;
import com.dahuatech.hutool.core.exceptions.UtilException;
import com.dahuatech.hutool.core.io.FileUtil;
import com.dahuatech.hutool.core.io.IORuntimeException;
import com.dahuatech.hutool.core.io.IoUtil;
import com.dahuatech.hutool.core.io.resource.ResourceUtil;
import com.dahuatech.hutool.core.lang.Assert;
import com.dahuatech.hutool.core.net.URLEncoder;
import java.io.*;
import java.net.*;
import java.nio.charset.Charset;
import java.util.jar.JarFile;
/**
* 统一资源定位符相关工具类
*
* @author xiaoleilu
*/
public class URLUtil {
/** 针对ClassPath路径的伪协议前缀(兼容Spring): "classpath:" */
public static final String CLASSPATH_URL_PREFIX = "classpath:";
/** URL 前缀表示文件: "file:" */
public static final String FILE_URL_PREFIX = "file:";
/** URL 前缀表示jar: "jar:" */
public static final String JAR_URL_PREFIX = "jar:";
/** URL 前缀表示war: "war:" */
public static final String WAR_URL_PREFIX = "war:";
/** URL 协议表示文件: "file" */
public static final String URL_PROTOCOL_FILE = "file";
/** URL 协议表示Jar文件: "jar" */
public static final String URL_PROTOCOL_JAR = "jar";
/** URL 协议表示zip文件: "zip" */
public static final String URL_PROTOCOL_ZIP = "zip";
/** URL 协议表示WebSphere文件: "wsjar" */
public static final String URL_PROTOCOL_WSJAR = "wsjar";
/** URL 协议表示JBoss zip文件: "vfszip" */
public static final String URL_PROTOCOL_VFSZIP = "vfszip";
/** URL 协议表示JBoss文件: "vfsfile" */
public static final String URL_PROTOCOL_VFSFILE = "vfsfile";
/** URL 协议表示JBoss VFS资源: "vfs" */
public static final String URL_PROTOCOL_VFS = "vfs";
/** Jar路径以及内部文件路径的分界符: "!/" */
public static final String JAR_URL_SEPARATOR = "!/";
/** WAR路径及内部文件路径分界符 */
public static final String WAR_URL_SEPARATOR = "*/";
/**
* 通过一个字符串形式的URL地址创建URL对象
*
* @param url URL
* @return URL对象
*/
public static URL url(String url) {
return url(url, null);
}
/**
* 通过一个字符串形式的URL地址创建URL对象
*
* @param url URL
* @param handler {@link URLStreamHandler}
* @return URL对象
* @since 4.1.1
*/
public static URL url(String url, URLStreamHandler handler) {
Assert.notNull(url, "URL must not be null");
// 兼容Spring的ClassPath路径
if (url.startsWith(CLASSPATH_URL_PREFIX)) {
url = url.substring(CLASSPATH_URL_PREFIX.length());
return ClassLoaderUtil.getClassLoader().getResource(url);
}
try {
return new URL(null, url, handler);
} catch (MalformedURLException e) {
// 尝试文件路径
try {
return new File(url).toURI().toURL();
} catch (MalformedURLException ex2) {
throw new UtilException(e);
}
}
}
/**
* 将URL字符串转换为URL对象,并做必要验证
*
* @param urlStr URL字符串
* @return URL
* @since 4.1.9
*/
public static URL toUrlForHttp(String urlStr) {
return toUrlForHttp(urlStr, null);
}
/**
* 将URL字符串转换为URL对象,并做必要验证
*
* @param urlStr URL字符串
* @param handler {@link URLStreamHandler}
* @return URL
* @since 4.1.9
*/
public static URL toUrlForHttp(String urlStr, URLStreamHandler handler) {
Assert.notBlank(urlStr, "Url is blank !");
// 编码空白符,防止空格引起的请求异常
urlStr = encodeBlank(urlStr);
try {
return new URL(null, urlStr, handler);
} catch (MalformedURLException e) {
throw new UtilException(e);
}
}
/**
* 单独编码URL中的空白符,空白符编码为%20
*
* @param urlStr URL字符串
* @return 编码后的字符串
* @since 4.5.14
*/
public static String encodeBlank(CharSequence urlStr) {
if (urlStr == null) {
return null;
}
int len = urlStr.length();
final StringBuilder sb = new StringBuilder(len);
char c;
for (int i = 0; i < len; i++) {
c = urlStr.charAt(i);
if (CharUtil.isBlankChar(c)) {
sb.append("%20");
} else {
sb.append(c);
}
}
return sb.toString();
}
/**
* 获得URL
*
* @param pathBaseClassLoader 相对路径(相对于classes)
* @return URL
* @see ResourceUtil#getResource(String)
*/
public static URL getURL(String pathBaseClassLoader) {
return ResourceUtil.getResource(pathBaseClassLoader);
}
/**
* 获得URL
*
* @param path 相对给定 class所在的路径
* @param clazz 指定class
* @return URL
* @see ResourceUtil#getResource(String, Class)
*/
public static URL getURL(String path, Class> clazz) {
return ResourceUtil.getResource(path, clazz);
}
/**
* 获得URL,常用于使用绝对路径时的情况
*
* @param file URL对应的文件对象
* @return URL
* @exception UtilException MalformedURLException
*/
public static URL getURL(File file) {
Assert.notNull(file, "File is null !");
try {
return file.toURI().toURL();
} catch (MalformedURLException e) {
throw new UtilException(e, "Error occured when get URL!");
}
}
/**
* 获得URL,常用于使用绝对路径时的情况
*
* @param files URL对应的文件对象
* @return URL
* @exception UtilException MalformedURLException
*/
public static URL[] getURLs(File... files) {
final URL[] urls = new URL[files.length];
try {
for (int i = 0; i < files.length; i++) {
urls[i] = files[i].toURI().toURL();
}
} catch (MalformedURLException e) {
throw new UtilException(e, "Error occured when get URL!");
}
return urls;
}
/**
* 获取URL中域名部分,只保留URL中的协议(Protocol)、Host,其它为null。
*
* @param url URL
* @return 域名的URI
* @since 4.6.9
*/
public static URI getHost(URL url) {
if (null == url) {
return null;
}
try {
return new URI(url.getProtocol(), url.getHost(), null, null);
} catch (URISyntaxException e) {
throw new UtilException(e);
}
}
/**
* 补全相对路径
*
* @param baseUrl 基准URL
* @param relativePath 相对URL
* @return 相对路径
* @exception UtilException MalformedURLException
*/
public static String complateUrl(String baseUrl, String relativePath) {
baseUrl = normalize(baseUrl, false);
if (StrUtil.isBlank(baseUrl)) {
return null;
}
try {
final URL absoluteUrl = new URL(baseUrl);
final URL parseUrl = new URL(absoluteUrl, relativePath);
return parseUrl.toString();
} catch (MalformedURLException e) {
throw new UtilException(e);
}
}
/**
* 编码URL,默认使用UTF-8编码
* 将需要转换的内容(ASCII码形式之外的内容),用十六进制表示法转换出来,并在之前加上%开头。
*
* @param url URL
* @return 编码后的URL
* @exception UtilException UnsupportedEncodingException
*/
public static String encodeAll(String url) {
return encodeAll(url, CharsetUtil.CHARSET_UTF_8);
}
/**
* 编码URL
* 将需要转换的内容(ASCII码形式之外的内容),用十六进制表示法转换出来,并在之前加上%开头。
*
* @param url URL
* @param charset 编码
* @return 编码后的URL
* @exception UtilException UnsupportedEncodingException
*/
public static String encodeAll(String url, Charset charset) throws UtilException {
try {
return java.net.URLEncoder.encode(url, charset.toString());
} catch (UnsupportedEncodingException e) {
throw new UtilException(e);
}
}
/**
* 编码URL,默认使用UTF-8编码
* 将需要转换的内容(ASCII码形式之外的内容),用十六进制表示法转换出来,并在之前加上%开头。
* 此方法用于URL自动编码,类似于浏览器中键入地址自动编码,对于像类似于“/”的字符不再编码
*
* @param url URL
* @return 编码后的URL
* @exception UtilException UnsupportedEncodingException
* @since 3.1.2
*/
public static String encode(String url) throws UtilException {
return encode(url, CharsetUtil.CHARSET_UTF_8);
}
/**
* 编码URL,默认使用UTF-8编码
* 将需要转换的内容(ASCII码形式之外的内容),用十六进制表示法转换出来,并在之前加上%开头。
* 此方法用于POST请求中的请求体自动编码,转义大部分特殊字符
*
* @param url URL
* @return 编码后的URL
* @exception UtilException UnsupportedEncodingException
* @since 3.1.2
*/
public static String encodeQuery(String url) throws UtilException {
return encodeQuery(url, CharsetUtil.CHARSET_UTF_8);
}
/**
* 编码字符为 application/x-www-form-urlencoded
* 将需要转换的内容(ASCII码形式之外的内容),用十六进制表示法转换出来,并在之前加上%开头。
* 此方法用于URL自动编码,类似于浏览器中键入地址自动编码,对于像类似于“/”的字符不再编码
*
* @param url 被编码内容
* @param charset 编码
* @return 编码后的字符
* @since 4.4.1
*/
public static String encode(String url, Charset charset) {
if (StrUtil.isEmpty(url)) {
return url;
}
if (null == charset) {
charset = CharsetUtil.defaultCharset();
}
return URLEncoder.DEFAULT.encode(url, charset);
}
/**
* 编码字符为URL中查询语句
* 将需要转换的内容(ASCII码形式之外的内容),用十六进制表示法转换出来,并在之前加上%开头。
* 此方法用于POST请求中的请求体自动编码,转义大部分特殊字符
*
* @param url 被编码内容
* @param charset 编码
* @return 编码后的字符
* @since 4.4.1
*/
public static String encodeQuery(String url, Charset charset) {
if (StrUtil.isEmpty(url)) {
return url;
}
if (null == charset) {
charset = CharsetUtil.defaultCharset();
}
return URLEncoder.QUERY.encode(url, charset);
}
/**
* 编码URL字符为 application/x-www-form-urlencoded
* 将需要转换的内容(ASCII码形式之外的内容),用十六进制表示法转换出来,并在之前加上%开头。
* 此方法用于URL自动编码,类似于浏览器中键入地址自动编码,对于像类似于“/”的字符不再编码
*
* @param url URL
* @param charset 编码
* @return 编码后的URL
* @exception UtilException UnsupportedEncodingException
*/
public static String encode(String url, String charset) throws UtilException {
if (StrUtil.isEmpty(url)) {
return url;
}
return encode(
url,
StrUtil.isBlank(charset) ? CharsetUtil.defaultCharset() : CharsetUtil.charset(charset));
}
/**
* 编码URL
* 将需要转换的内容(ASCII码形式之外的内容),用十六进制表示法转换出来,并在之前加上%开头。
* 此方法用于POST请求中的请求体自动编码,转义大部分特殊字符
*
* @param url URL
* @param charset 编码
* @return 编码后的URL
* @exception UtilException UnsupportedEncodingException
*/
public static String encodeQuery(String url, String charset) throws UtilException {
return encodeQuery(
url,
StrUtil.isBlank(charset) ? CharsetUtil.defaultCharset() : CharsetUtil.charset(charset));
}
/**
* 解码URL
* 将%开头的16进制表示的内容解码。
*
* @param url URL
* @return 解码后的URL
* @exception UtilException UnsupportedEncodingException
* @since 3.1.2
*/
public static String decode(String url) throws UtilException {
return decode(url, CharsetUtil.UTF_8);
}
/**
* 解码application/x-www-form-urlencoded字符
*
* @param content 被解码内容
* @param charset 编码
* @return 编码后的字符
* @since 4.4.1
*/
public static String decode(String content, Charset charset) {
if (null == charset) {
charset = CharsetUtil.defaultCharset();
}
return decode(content, charset.name());
}
/**
* 解码URL
* 将%开头的16进制表示的内容解码。
*
* @param url URL
* @param charset 编码
* @return 解码后的URL
* @exception UtilException UnsupportedEncodingException
*/
public static String decode(String url, String charset) throws UtilException {
if (StrUtil.isEmpty(url)) {
return url;
}
try {
return URLDecoder.decode(url, charset);
} catch (UnsupportedEncodingException e) {
throw new UtilException(e, "Unsupported encoding: [{}]", charset);
}
}
/**
* 获得path部分
*
* @param uriStr URI路径
* @return path
* @exception UtilException 包装URISyntaxException
*/
public static String getPath(String uriStr) {
URI uri;
try {
uri = new URI(uriStr);
} catch (URISyntaxException e) {
throw new UtilException(e);
}
return uri.getPath();
}
/**
* 从URL对象中获取不被编码的路径Path
* 对于本地路径,URL对象的getPath方法对于包含中文或空格时会被编码,导致本读路径读取错误。
* 此方法将URL转为URI后获取路径用于解决路径被编码的问题
*
* @param url {@link URL}
* @return 路径
* @since 3.0.8
*/
public static String getDecodedPath(URL url) {
if (null == url) {
return null;
}
String path = null;
try {
// URL对象的getPath方法对于包含中文或空格的问题
path = URLUtil.toURI(url).getPath();
} catch (UtilException e) {
// ignore
}
return (null != path) ? path : url.getPath();
}
/**
* 转URL为URI
*
* @param url URL
* @return URI
* @exception UtilException 包装URISyntaxException
*/
public static URI toURI(URL url) throws UtilException {
return toURI(url, false);
}
/**
* 转URL为URI
*
* @param url URL
* @param isEncode 是否编码参数中的特殊字符(默认UTF-8编码)
* @return URI
* @exception UtilException 包装URISyntaxException
* @since 4.6.9
*/
public static URI toURI(URL url, boolean isEncode) throws UtilException {
if (null == url) {
return null;
}
return toURI(url.toString(), isEncode);
}
/**
* 转字符串为URI
*
* @param location 字符串路径
* @return URI
* @exception UtilException 包装URISyntaxException
*/
public static URI toURI(String location) throws UtilException {
return toURI(location, false);
}
/**
* 转字符串为URI
*
* @param location 字符串路径
* @param isEncode 是否编码参数中的特殊字符(默认UTF-8编码)
* @return URI
* @exception UtilException 包装URISyntaxException
* @since 4.6.9
*/
public static URI toURI(String location, boolean isEncode) throws UtilException {
if (isEncode) {
location = encode(location);
}
try {
return new URI(location);
} catch (URISyntaxException e) {
throw new UtilException(e);
}
}
/**
* 提供的URL是否为文件
* 文件协议包括"file", "vfsfile" 或 "vfs".
*
* @param url {@link URL}
* @return 是否为文件
* @since 3.0.9
*/
public static boolean isFileURL(URL url) {
String protocol = url.getProtocol();
return (URL_PROTOCOL_FILE.equals(protocol)
|| //
URL_PROTOCOL_VFSFILE.equals(protocol)
|| //
URL_PROTOCOL_VFS.equals(protocol));
}
/**
* 提供的URL是否为jar包URL 协议包括: "jar", "zip", "vfszip" 或 "wsjar".
*
* @param url {@link URL}
* @return 是否为jar包URL
*/
public static boolean isJarURL(URL url) {
final String protocol = url.getProtocol();
return (URL_PROTOCOL_JAR.equals(protocol)
|| //
URL_PROTOCOL_ZIP.equals(protocol)
|| //
URL_PROTOCOL_VFSZIP.equals(protocol)
|| //
URL_PROTOCOL_WSJAR.equals(protocol));
}
/**
* 提供的URL是否为Jar文件URL 判断依据为file协议且扩展名为.jar
*
* @param url the URL to check
* @return whether the URL has been identified as a JAR file URL
* @since 4.1
*/
public static boolean isJarFileURL(URL url) {
return (URL_PROTOCOL_FILE.equals(url.getProtocol())
&& //
url.getPath().toLowerCase().endsWith(FileUtil.JAR_FILE_EXT));
}
/**
* 从URL中获取流
*
* @param url {@link URL}
* @return InputStream流
* @since 3.2.1
*/
public static InputStream getStream(URL url) {
Assert.notNull(url);
try {
return url.openStream();
} catch (IOException e) {
throw new IORuntimeException(e);
}
}
/**
* 获得Reader
*
* @param url {@link URL}
* @param charset 编码
* @return {@link BufferedReader}
* @since 3.2.1
*/
public static BufferedReader getReader(URL url, Charset charset) {
return IoUtil.getReader(getStream(url), charset);
}
/**
* 从URL中获取JarFile
*
* @param url URL
* @return JarFile
* @since 4.1.5
*/
public static JarFile getJarFile(URL url) {
try {
JarURLConnection urlConnection = (JarURLConnection) url.openConnection();
return urlConnection.getJarFile();
} catch (IOException e) {
throw new IORuntimeException(e);
}
}
/**
* 标准化URL字符串,包括:
*
*
* 1. 多个/替换为一个
*
*
* @param url URL字符串
* @return 标准化后的URL字符串
*/
public static String normalize(String url) {
return normalize(url, false);
}
/**
* 标准化URL字符串,包括:
*
*
* 1. 多个/替换为一个
*
*
* @param url URL字符串
* @param isEncodeBody 是否对URL中body部分的中文和特殊字符做转义(不包括http:和/)
* @return 标准化后的URL字符串
* @since 4.4.1
*/
public static String normalize(String url, boolean isEncodeBody) {
if (StrUtil.isBlank(url)) {
return url;
}
final int sepIndex = url.indexOf("://");
String pre;
String body;
if (sepIndex > 0) {
pre = StrUtil.subPre(url, sepIndex + 3);
body = StrUtil.subSuf(url, sepIndex + 3);
} else {
pre = "http://";
body = url;
}
final int paramsSepIndex = StrUtil.indexOf(body, '?');
String params = null;
if (paramsSepIndex > 0) {
params = StrUtil.subSuf(body, paramsSepIndex);
body = StrUtil.subPre(body, paramsSepIndex);
}
// 去除开头的\或者/
body = body.replaceAll("^[\\\\/]+", StrUtil.EMPTY);
// 替换多个\或/为单个/
body = body.replace("\\", "/").replaceAll("//+", "/");
if (isEncodeBody) {
body = encode(body);
}
return pre + body + StrUtil.nullToEmpty(params);
}
}