All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.hutool.core.net.url.UrlPath Maven / Gradle / Ivy

Go to download

Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。

There is a newer version: 5.8.34
Show newest version
package cn.hutool.core.net.url;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.net.RFC3986;
import cn.hutool.core.net.URLDecoder;
import cn.hutool.core.util.CharUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;

import java.nio.charset.Charset;
import java.util.LinkedList;
import java.util.List;

/**
 * URL中Path部分的封装
 *
 * @author looly
 * @since 5.3.1
 */
public class UrlPath {

	private List segments;
	private boolean withEngTag;

	/**
	 * 构建UrlPath
	 *
	 * @param pathStr 初始化的路径字符串
	 * @param charset decode用的编码,null表示不做decode
	 * @return UrlPath
	 */
	public static UrlPath of(CharSequence pathStr, Charset charset) {
		final UrlPath urlPath = new UrlPath();
		urlPath.parse(pathStr, charset);
		return urlPath;
	}

	/**
	 * 是否path的末尾加 /
	 *
	 * @param withEngTag 是否path的末尾加 /
	 * @return this
	 */
	public UrlPath setWithEndTag(boolean withEngTag) {
		this.withEngTag = withEngTag;
		return this;
	}

	/**
	 * 获取path的节点列表
	 *
	 * @return 节点列表
	 */
	public List getSegments() {
		return ObjectUtil.defaultIfNull(this.segments, ListUtil.empty());
	}

	/**
	 * 获得指定节点
	 *
	 * @param index 节点位置
	 * @return 节点,无节点或者越界返回null
	 */
	public String getSegment(int index) {
		if (null == this.segments || index >= this.segments.size()) {
			return null;
		}
		return this.segments.get(index);
	}

	/**
	 * 添加到path最后面
	 *
	 * @param segment Path节点
	 * @return this
	 */
	public UrlPath add(CharSequence segment) {
		addInternal(fixPath(segment), false);
		return this;
	}

	/**
	 * 添加到path最前面
	 *
	 * @param segment Path节点
	 * @return this
	 */
	public UrlPath addBefore(CharSequence segment) {
		addInternal(fixPath(segment), true);
		return this;
	}

	/**
	 * 解析path
	 *
	 * @param path    路径,类似于aaa/bb/ccc或/aaa/bbb/ccc
	 * @param charset decode编码,null表示不解码
	 * @return this
	 */
	public UrlPath parse(CharSequence path, Charset charset) {
		if (StrUtil.isNotEmpty(path)) {
			// 原URL中以/结尾,则这个规则需保留,issue#I1G44J@Gitee
			if(StrUtil.endWith(path, CharUtil.SLASH)){
				this.withEngTag = true;
			}

			path = fixPath(path);
			if(StrUtil.isNotEmpty(path)){
				final List split = StrUtil.split(path, '/');
				for (String seg : split) {
					addInternal(URLDecoder.decodeForPath(seg, charset), false);
				}
			}
		}

		return this;
	}

	/**
	 * 构建path,前面带'/'
*
	 *     path = path-abempty / path-absolute / path-noscheme / path-rootless / path-empty
	 * 
* * @param charset encode编码,null表示不做encode * @return 如果没有任何内容,则返回空字符串"" */ public String build(Charset charset) { return build(charset, true); } /** * 构建path,前面带'/'
*
	 *     path = path-abempty / path-absolute / path-noscheme / path-rootless / path-empty
	 * 
* * @param charset encode编码,null表示不做encode * @param encodePercent 是否编码`%` * @return 如果没有任何内容,则返回空字符串"" * @since 5.8.0 */ public String build(Charset charset, boolean encodePercent) { if (CollUtil.isEmpty(this.segments)) { // 没有节点的path取决于是否末尾追加/,如果不追加返回空串,否则返回/ return withEngTag ? StrUtil.SLASH : StrUtil.EMPTY; } final char[] safeChars = encodePercent ? null : new char[]{'%'}; final StringBuilder builder = new StringBuilder(); for (final String segment : segments) { if(builder.length() == 0){ // 根据https://www.ietf.org/rfc/rfc3986.html#section-3.3定义 // path的第一部分不允许有":",其余部分允许 // 在此处的Path部分特指host之后的部分,即不包含第一部分 builder.append(CharUtil.SLASH).append(RFC3986.SEGMENT_NZ_NC.encode(segment, charset, safeChars)); } else { builder.append(CharUtil.SLASH).append(RFC3986.SEGMENT.encode(segment, charset, safeChars)); } } if(withEngTag){ if (StrUtil.isEmpty(builder)) { // 空白追加是保证以/开头 builder.append(CharUtil.SLASH); }else if (false == StrUtil.endWith(builder, CharUtil.SLASH)) { // 尾部没有/则追加,否则不追加 builder.append(CharUtil.SLASH); } } return builder.toString(); } @Override public String toString() { return build(null); } /** * 增加节点 * * @param segment 节点 * @param before 是否在前面添加 */ private void addInternal(CharSequence segment, boolean before) { if (this.segments == null) { this.segments = new LinkedList<>(); } final String seg = StrUtil.str(segment); if (before) { this.segments.add(0, seg); } else { this.segments.add(seg); } } /** * 修正路径,包括去掉前后的/,去掉空白符 * * @param path 节点或路径path * @return 修正后的路径 */ private static String fixPath(CharSequence path) { Assert.notNull(path, "Path segment must be not null!"); if ("/".contentEquals(path)) { return StrUtil.EMPTY; } String segmentStr = StrUtil.trim(path); segmentStr = StrUtil.removePrefix(segmentStr, StrUtil.SLASH); segmentStr = StrUtil.removeSuffix(segmentStr, StrUtil.SLASH); segmentStr = StrUtil.trim(segmentStr); return segmentStr; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy