/** 渲染URI query string。 */ @Override protected final void renderQuery(StringBuilder buf) { if (!getQuery().isEmpty()) { buf.append("?"); for (Iterator<Map.Entry<String, Object>> i = getQuery().entrySet().iterator(); i.hasNext(); ) { Map.Entry<String, Object> entry = i.next(); String id = escapeURL(entry.getKey()); Object value = entry.getValue(); if (value instanceof String[]) { int length = ((String[]) value).length; for (int j = 0; j < length; j++) { buf.append(id).append("=").append(escapeURL(((String[]) value)[j])); if (j + 1 < length) { buf.append("&"); } } } else { buf.append(id).append("=").append(escapeURL(String.valueOf(value))); } if (i.hasNext()) { buf.append("&"); } } } }
/** 将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(); }
/** 渲染URI服务器信息。 */ @Override protected final void renderServer(StringBuilder buf) { // scheme:// String serverScheme = getEffectiveServerScheme(getServerScheme()); buf.append(serverScheme); buf.append("://"); // user:password@ String loginUser = getLoginUser(); String loginPassword = getLoginPassword(); if (!isEmpty(loginUser)) { buf.append(loginUser); if (!isEmpty(loginPassword)) { buf.append(":").append(loginPassword); } buf.append("@"); } // hostname:port String serverName = getServerName(); if (!isEmpty(serverName)) { buf.append(serverName); if (!isDefaultPort(serverScheme)) { buf.append(":"); buf.append(getServerPort()); } } }
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(); }
/** 渲染URI path。 */ @Override protected final void renderPath(StringBuilder buf) { for (String path : URIBroker.this.path) { buf.append("/").append(escapeURL(path)); } }
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); } } }