org.springframework.util.AntPathMatcher.domatch

ANT格式接口路径解析org.springframework.util.AntPathMatcher.domatch

/**
	 * @Description: 请求路径和配置路径匹配器
	 * @param reqPath
	 * @param configPath
	 * @return boolean
	 * @version v1.0
	 * @author wzdbzl
	 * @date 2024年3月1日 下午3:28:19
	 */
	public static boolean antPathMatcher(String reqPath, String configPath){
		if(reqPath == null || reqPath.startsWith(DEFAULT_PATH_SEPARATOR) != configPath.startsWith(DEFAULT_PATH_SEPARATOR)){
			return false;
		}
		String[] pathDirs = tokenizeToStringArray(reqPath, DEFAULT_PATH_SEPARATOR);
		String[] pattDirs = tokenizeToStringArray(configPath, DEFAULT_PATH_SEPARATOR);
		int pattIdxStart = 0;
		int pattIdxEnd = pattDirs.length - 1;
		int pathIdxStart = 0;
		int pathIdxEnd = pathDirs.length - 1;
		while (pattIdxStart <= pattIdxEnd && pathIdxStart <= pathIdxEnd) {
			String pattDir = pattDirs[pattIdxStart];
			if ("**".equals(pattDir)) {
				break;
			}
			//正序循环当前元素不满足,直接返回
			if (!matchStrings(pattDir, pathDirs[pathIdxStart])) {
				return false;
			}
			pattIdxStart++;
			pathIdxStart++;
		}
		if (pathIdxStart > pathIdxEnd) { 
			//path耗尽,patt也耗尽,比较结尾字符
			if (pattIdxStart > pattIdxEnd) {
				return (configPath.endsWith(DEFAULT_PATH_SEPARATOR) == reqPath.endsWith(DEFAULT_PATH_SEPARATOR));
			}
			//path耗尽,但是patt还剩一个字符串是*
			if (pattIdxStart == pattIdxEnd && pattDirs[pattIdxStart].equals("*") && reqPath.endsWith(DEFAULT_PATH_SEPARATOR)) {
				return true;
			}
			//path耗尽,但是patt没耗尽且不止一个,有一个不是**就不行
			for (int i = pattIdxStart; i <= pattIdxEnd; i++) {
				if (!pattDirs[i].equals("**")) {
					return false;
				}
			}
			return true;
		}else if (pattIdxStart > pattIdxEnd) {
			//pattern耗尽,但path没有耗尽
			return false;
		}
		while (pattIdxStart <= pattIdxEnd && pathIdxStart <= pathIdxEnd) {
			String pattDir = pattDirs[pattIdxEnd];
			if (pattDir.equals("**")) {
				break;
			}
			//倒序循环当前元素不满足,直接返回
			if (!matchStrings(pattDir, pathDirs[pathIdxEnd])) {
				return false;
			}
			pattIdxEnd--;
			pathIdxEnd--;
		}
		if (pathIdxStart > pathIdxEnd) {
			//path耗尽,patt没有耗尽
			for (int i = pattIdxStart; i <= pattIdxEnd; i++) {
				if (!pattDirs[i].equals("**")) {
					return false;
				}
			}
			return true;
		}
		while (pattIdxStart != pattIdxEnd && pathIdxStart <= pathIdxEnd) {
			//此时已经锁定了patt路径中第一次和最后一次出现**的位置,patt和path均已记录,这种情况必须去以消耗掉patt为目标循环,除非path先被消耗完
			int patIdxTmp = -1;
			for (int i = pattIdxStart + 1; i <= pattIdxEnd; i++) {
				//从第一个**的位置+1开始遍历,遇到"**"停止,但是将**的位置索引记录在patIdxTmp中
				if (pattDirs[i].equals("**")) {
					patIdxTmp = i;
					break;
				}
			}
			if (patIdxTmp == pattIdxStart + 1) {
				//用于排除patt中包含的/**/**/**这种情况,每一次**+1 等于上一次的记录则跳过本次while循环
				pattIdxStart++;
				continue;
			}
			// 此处来到了patt中的正向循环之后被记录的**的后一位
			int patLength = (patIdxTmp - (pattIdxStart + 1));//计算此时剩下的patt数量
			//此时没被校验的path长度
			int strLength = (pathIdxEnd - pathIdxStart + 1);
			int foundIdx = -1;
			strLoop://平移操作?
			for (int i = 0; i <= strLength - patLength; i++) {
				for (int j = 0; j < patLength; j++) {
					//循环剩下的patt和path,直到找到path中能和patt中**后一位相匹配的,此时返回path中被匹配到的路径的位置
					String subPat = pattDirs[(pattIdxStart  + 1) + j];
					String subStr = pathDirs[pathIdxStart + i + j];
					if (!matchStrings(subPat, subStr)) {
						continue strLoop;
					}
				}
				foundIdx = pathIdxStart + i;
				break;
			}
			if (foundIdx == -1) {
				return false;
			}
			pattIdxStart = patIdxTmp;//再从patIdxTmp位置继续循环这个while,直到patt耗尽或者path耗尽
			pathIdxStart = foundIdx + patLength;//同理path循环也是从发现与patt中**后一位相匹配的索引的下一位开始。直到patt耗尽或者path耗尽
		}
		//path消耗完之后patt仍有剩余
		for (int i = pattIdxStart; i <= pattIdxEnd; i++) {
			if (!pattDirs[i].equals("**")) {
				return false;
			}
		}
		return true;
	}
/**
	 * @Description: 将Ant风格的字符串模板转换为正则表达式
	 * @param pattern
	 * @return Pattern
	 * @version v1.0
	 * @author wzdbzl
	 * @date 2024年3月1日 下午5:59:09
	 */
	public static Pattern changeAntStringToRegular(String pattern){
		StringBuilder patternBuilder = new StringBuilder();
		//GLOB_PATTERN正则表达式和模式串pattern匹配,会得到一个matcher,matcher中包含一些方法,得到匹配的一些情况
		Matcher matcher = GLOB_PATTERN.matcher(pattern);
		int end = 0;
		while (matcher.find()) {
			//在找到匹配的情况下将前面的字符串先放入patternBuilder中
			patternBuilder.append(quote(pattern, end, matcher.start()));
			String match = matcher.group();
			//如果找到了?就转换为正则表达式中的'.'
			if ("?".equals(match)) { 
				patternBuilder.append('.');
			}
			//如果找到了*就转换为正则表达式中的'.*'
			else if ("*".equals(match)) {
				patternBuilder.append(".*");
			}
			else if (match.startsWith("{") && match.endsWith("}")) {
				//如果是在{}中就把花括号去掉
				match = match.substring(1, match.length() - 1);
				patternBuilder.append('(');
				patternBuilder.append(match);
				patternBuilder.append(')');
			}
			end = matcher.end();
		}
		patternBuilder.append(quote(pattern, end, pattern.length()));
		return Pattern.compile(patternBuilder.toString());
	}
/**
	 * @Description: 校验传入路径段和配置路径段是否合规
	 * @param pattern
	 * @param path
	 * @return boolean
	 * @version v1.0
	 * @author wzdbzl
	 * @date 2024年3月1日 下午6:13:39
	 */
	public static boolean matchStrings(String pattern, String path){
		return changeAntStringToRegular(pattern).matcher(path).matches();
	}
/**
	 * @Description: 将不是通配符的字符串做为字面常量来处理,规避正则字符校验,即{}等符号
	 * @param s
	 * @param start
	 * @param end
	 * @return String
	 * @version v1.0
	 * @author wzdbzl
	 * @date 2024年3月1日 下午6:03:39
	 */
	public static String quote(String s, int start, int end){
		return start == end ? "" : Pattern.quote(s.substring(start, end));
	}
/**
	 * @Description: 将字符串参数根据分隔符切割为数组
	 * @param param
	 * @param delimiters
	 * @return String[]
	 * @version v1.0
	 * @author wzdbzl
	 * @date 2024年3月1日 下午3:10:40
	 */
	public static String[] tokenizeToStringArray(String param, String delimiters){
		if (param == null) {
			return new String[0];
		} else {
			StringTokenizer st = new StringTokenizer(param, delimiters);
			List<String> tokens = new ArrayList<String>();
			while (true) {
				String token;
				do {
					if (!st.hasMoreTokens()) {
						return CollectionUtil.isEmpty(tokens) ? new String[0] : tokens.toArray(new String[tokens.size()]);
					}
					token = st.nextToken();
					token = token.trim();
				} while (token.length() <= 0);
				tokens.add(token);
			}
		}
	}
  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值