标准化URL字符串，包括：

<pre>
1. 多个/替换为一个
</pre>

@param url URL字符串
@param isEncodeBody 是否对URL中body部分的中文和特殊字符做转义（不包括http:和/）
@return 标准化后的URL字符串
@since 4.4.1
766959
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);
	}
839633
public static String encodeUrl(String stringToEncode) {
        try {
            return URLEncoder.encode(stringToEncode, "UTF-8");
        } catch (UnsupportedEncodingException e1) {
            throw new RuntimeException(e1);
        }
    }
3644
private static String encodeUrlPart(final String part) throws UnsupportedEncodingException {
        //we need to go through and check part by part that a section does not need encoding

        int pos = 0;
        for (int i = 0; i < part.length(); ++i) {
            char c = part.charAt(i);
            if(c == '?') {
                break;
            } else if (c == '/') {
                if (pos != i) {
                    String original = part.substring(pos, i);
                    String encoded = URLEncoder.encode(original, UTF_8);
                    if (!encoded.equals(original)) {
                        return realEncode(part, pos);
                    }
                }
                pos = i + 1;
            } else if (c == ' ') {
                return realEncode(part, pos);
            }
        }
        return part;
    }
628906
function getPageUrl(pageUrl, isDev, urlQueryOpts = {}) {
    const urlParseResult = urlParse(pageUrl);

    const protocol = isDev ? 'http:' : 'https:';

    // 开发场景和生产环境的地址不一样
    if (isDev) {
        urlQueryOpts.now_n_http = 1;
        urlQueryOpts.no_eruda = 1;
        urlQueryOpts.no_logger = 1;
    } else {
        urlQueryOpts._bid = 3170;
    }

    // TODO query 应该和 urlQueryOpts 合并
    return urlHandle.getUrl(`${protocol}//${urlParseResult.host}${urlParseResult.pathname}${urlParseResult.query}`, urlQueryOpts);
}
310157
def request_encode_url(self, method, url, fields=None, **urlopen_kw):
        
        if fields:
            url += '?' + urlencode(fields)
        return self.urlopen(method, url, **urlopen_kw)
995204
public static byte[] encode(byte[] arr, boolean isMultiLine, boolean isUrlSafe) {
		if (null == arr) {
			return null;
		}

		int len = arr.length;
		if (len == 0) {
			return new byte[0];
		}

		int evenlen = (len / 3) * 3;
		int cnt = ((len - 1) / 3 + 1) << 2;
		int destlen = cnt + (isMultiLine ? (cnt - 1) / 76 << 1 : 0);
		byte[] dest = new byte[destlen];

		byte[] encodeTable = isUrlSafe ? URL_SAFE_ENCODE_TABLE : STANDARD_ENCODE_TABLE;

		for (int s = 0, d = 0, cc = 0; s < evenlen;) {
			int i = (arr[s++] & 0xff) << 16 | (arr[s++] & 0xff) << 8 | (arr[s++] & 0xff);

			dest[d++] = encodeTable[(i >>> 18) & 0x3f];
			dest[d++] = encodeTable[(i >>> 12) & 0x3f];
			dest[d++] = encodeTable[(i >>> 6) & 0x3f];
			dest[d++] = encodeTable[i & 0x3f];

			if (isMultiLine && ++cc == 19 && d < destlen - 2) {
				dest[d++] = '\r';
				dest[d++] = '\n';
				cc = 0;
			}
		}

		int left = len - evenlen;// 剩余位数
		if (left > 0) {
			int i = ((arr[evenlen] & 0xff) << 10) | (left == 2 ? ((arr[len - 1] & 0xff) << 2) : 0);

			dest[destlen - 4] = encodeTable[i >> 12];
			dest[destlen - 3] = encodeTable[(i >>> 6) & 0x3f];

			if (isUrlSafe) {
				// 在URL Safe模式下，=为URL中的关键字符，不需要补充。空余的byte位要去掉。
				int urlSafeLen = destlen - 2;
				if (2 == left) {
					dest[destlen - 2] = encodeTable[i & 0x3f];
					urlSafeLen += 1;
				}
				byte[] urlSafeDest = new byte[urlSafeLen];
				System.arraycopy(dest, 0, urlSafeDest, 0, urlSafeLen);
				return urlSafeDest;
			} else {
				dest[destlen - 2] = (left == 2) ? encodeTable[i & 0x3f] : (byte) '=';
				dest[destlen - 1] = '=';
			}
		}
		return dest;
	}
991271
@Override
    public String encodeURL(String url) {
        SessionInfo info = this.request.getSessionInfo();
        if (null == info || !info.getSessionConfig().isURLRewriting()) {
            if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                Tr.debug(tc, "encodeURL: no session update needed");
            }
            return url;
        }
        if (null == info.getSession()) {
            if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                Tr.debug(tc, "encodeURL: no session found");
            }
            return url;
        }
        return SessionInfo.encodeURL(url, info);
    }
142421
private static String encodeExampleForUrl(Object example) {
        try {
            return URLEncoder.encode(String.valueOf(example), "UTF-8");
        } catch (UnsupportedEncodingException exception) {
            throw new RuntimeException(exception);
        }
    }
934680
private static String buildUrlWithQueryString(String url, Map<String, String> queryParas) {
		if (queryParas == null || queryParas.isEmpty())
			return url;
		
		StringBuilder sb = new StringBuilder(url);
		boolean isFirst;
		if (!url.contains("?")) {
			isFirst = true;
			sb.append("?");
		}
		else {
			isFirst = false;
		}
		
		for (Entry<String, String> entry : queryParas.entrySet()) {
			if (isFirst) isFirst = false;	
			else sb.append("&");
			
			String key = entry.getKey();
			String value = entry.getValue();
			if (StrKit.notBlank(value))
				try {value = URLEncoder.encode(value, CHARSET);} catch (UnsupportedEncodingException e) {throw new RuntimeException(e);}
			sb.append(key).append("=").append(value);
		}
		return sb.toString();
	}
972808
private static List<String> splitAndEncodeParams(URL url) {
		if (url.getQuery() == null) {
			return new ArrayList<>();
		}
		String[] params = url.getQuery().split("&");
		List<String> result = new ArrayList<>(params.length);
		for (String p : params) {
			String[] kv = p.split("=");
			kv[0] = PercentEncoding.decode(kv[0]);
			kv[1] = PercentEncoding.decode(kv[1]);
			kv[0] = PercentEncoding.encode(kv[0]);
			kv[1] = PercentEncoding.encode(kv[1]);
			String np = kv[0] + "=" + kv[1];
			result.add(np);
		}
		return result;
	}
18046
@Transformer
    public static String urlEncode(Object data) {
        if (null == data) return "";
        String entity = data.toString();
        try {
            String encoding = "utf-8";
            return URLEncoder.encode(entity, encoding);
        } catch (UnsupportedEncodingException e) {
            Logger.error(e, entity);
        }
        return entity;
    }
320381
public static String encode(String str)
    {
        String encoded;
        try {
            encoded = URLEncoder.encode(str, "UTF-8").replace(".", "%2E").replace("*", "%2A");
        } catch (UnsupportedEncodingException e) {
            // Should never happen

            encoded = str;
        }

        return encoded;
    }
805179
public static String get(String url, Map<String, String> body) {
        return get(url, JSONObject.toJSONString(body));
    }
614826
public static String urlFormEncode(final String s)
        {
        if (StringUtils.isBlank(s))
            {
            LOG.warn("Could not encode blank string");
            throw new IllegalArgumentException("Blank string");
            }
        try
            {
            return URLEncoder.encode(s, "UTF-8");
            }
        catch (final UnsupportedEncodingException e)
            {
            LOG.error ("Could not encode: " + s, e);            
            return s;
            }
        }
818109
public static String encodeURL(String uri)
  {
    CharBuffer cb = CharBuffer.allocate();

    for (int i = 0; i < uri.length(); i++) {
      char ch = uri.charAt(i);

      switch (ch) {
      case '<':
      case '>':
      case ' ':
      case '%':
      case '\'':
      case '\"':
        cb.append('%');
        cb.append(encodeHex(ch >> 4));
        cb.append(encodeHex(ch));
        break;

      default:
        cb.append(ch);
      }
    }

    return cb.close();
  }
162933
public static String urlEncode(String str) {
        try {
            String encodeForForm = URLEncoder.encode(str, "UTF-8");
            String encodeForUrl = encodeForForm.replace("+", "%20");
            return encodeForUrl;
        } catch (UnsupportedEncodingException e) {
            throw new IllegalStateException("JVM does not support UTF-8");
        }
    }
432426
public static String urlEncode(String string) {
        try {
            return URLEncoder.encode(string, CHARSET);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }