/** 取得不包含query和reference的serverURI。 */ public String getServerURI() { processInterceptors(); StringBuilder buf = new StringBuilder(); render(buf, true); return buf.toString(); }
/** 将path转换成相对于base的相对路径。 */ private String getRelativePath(String base, String path) { // 去除base中最后一段路径,例如: // /sub/dir/index.html -> /sub/dir // /sub/dir/ -> /sub/dir int index = base.lastIndexOf("/"); if (index >= 0) { base = base.substring(0, index); } // 特殊情况:base为空,直接返回path,但除去开头的/ if (isEmpty(base)) { if (path.startsWith("/")) { return path.replaceFirst("^/+", EMPTY_STRING); } else { return path; } } Matcher baseMatcher = pathPattern.matcher(base); Matcher pathMatcher = pathPattern.matcher(path); boolean baseFound; boolean pathFound; // 去除base和path中相同的部分,例如: // /this/is/base/dir -> /base/dir // /this/is/my/path -> /my/path do { baseFound = baseMatcher.find(); pathFound = pathMatcher.find(); } while (baseFound && pathFound && isEquals(baseMatcher.group(2), pathMatcher.group(2))); StringBuilder relativePath = new StringBuilder(); // 将base中剩余的部分,分别转换成../ for (; baseFound; baseFound = baseMatcher.find()) { relativePath.append("../"); } // 将path中剩余的部分,追加到末尾 while (pathFound) { relativePath.append(pathMatcher.group(2)); pathFound = pathMatcher.find(); if (pathFound) { relativePath.append("/"); } } return relativePath.toString(); }
private String getSubPathAsString(int segment, boolean multi) { assertSegment(segment); StringBuilder buf = new StringBuilder(); int endIndex = multi ? path.size() : pathSegmentIndexes[segment]; int beginIndex = segment > 0 ? pathSegmentIndexes[segment - 1] : 0; for (int i = beginIndex; i < endIndex; i++) { buf.append("/").append(path.get(i)); } return buf.toString(); }
private void render(StringBuilder buf, boolean renderServerURIOnly) { URIType type = renderServerURIOnly || getURIType() == null ? URIType.full : getURIType(); BaseURI baseURI = null; boolean renderServer = true; switch (type) { case auto: case absolute: case relative: baseURI = createBaseURI(); if (baseURI != null) { // 当且仅当baseURI中的server信息和broker中的一致,才不渲染server String scheme = getEffectiveServerScheme(getServerScheme()); int port = getEffectiveServerPort(scheme, getServerPort()); if (isEquals(scheme, baseURI.serverScheme) && isEquals(getServerName(), baseURI.serverName) && port == baseURI.serverPort) { renderServer = false; } } break; case full: } // server info if (renderServer) { if (renderer.isServerRendered()) { buf.append(renderer.serverBuffer); } else { renderServer(buf); } } // path info String path = EMPTY_STRING; if (!URIBroker.this.path.isEmpty()) { StringBuilder pathBuf = new StringBuilder(); if (renderer.isPathRendered()) { pathBuf.append(renderer.pathBuffer); } else { renderPath(pathBuf); } path = pathBuf.toString(); } path = trimToEmpty(processPathInterceptors(path)); // 将path转换成相对路径(前提:server未渲染) if (!renderServer) { switch (type) { case relative: path = getRelativePath(baseURI.path, path); break; case auto: String relativePath = getRelativePath(baseURI.path, path); if (!relativePath.startsWith("../")) { path = relativePath; } break; case full: case absolute: } } if (renderServer && !path.startsWith("/")) { buf.append("/"); } buf.append(path); if (!renderServerURIOnly) { // query info if (renderer.isQueryRendered()) { buf.append(renderer.queryBuffer); } else { renderQuery(buf); } // #reference String reference = getReference(); if (!isEmpty(reference)) { buf.append("#"); buf.append(reference); } } }