Dubbo源码-02-URL
parse url
demo
// UrlUtilsTest.java
@Test
public void test00(){
/**
* 往map中添点配置信息
* - application->native-provider
* - qos.port=22222
* - path->com.alibaba.dubbo.registry.RegistryService
* - dubbo->2.0.2
* - timestamp->?
* - pid->?
* - protocol->dubbo
* address=zookeeper://localhost:2181
*/
String address = "zookeeper://localhost:2181";
Map<String,String> map = new HashMap<String, String>(){{
put("application","native-provider");
put("qos.port","22222");
put("protocol","dubbo");
}};
List<URL> urls = UrlUtils.parseURLs("protocol1://ip1:1234;protocol2://ip2:6789", map);
URL url = UrlUtils.parseURL(address, map);
System.out.println();
}
多条地址
// UrlUtils.java
/**
* address中用;分割多个地址
* 一个地址信息的基本信息
* - 协议://ip:port
* - 附加的其他信息追加到后面
* 将hash表中配置信息拼接到地址中
*/
public static List<URL> parseURLs(String address, Map<String, String> defaults) {
if (address == null || address.length() == 0) {
return null;
}
String[] addresses = Constants.REGISTRY_SPLIT_PATTERN.split(address); // 分割符多个地址
if (addresses == null || addresses.length == 0) {
return null; //here won't be empty
}
List<URL> registries = new ArrayList<URL>();
for (String addr : addresses) {
registries.add(parseURL(addr, defaults)); // 单条地址
}
return registries;
}
单条地址
// UrlUtils.java
/**
* address
* - 基础信息
* - 指定了协议://ip:port
* - 没指定协议
* - 单台服务器 ip:port
* - 多服务器 ip1:port1.ip2:port2
* - 把hash表中信息追加到地址后面连接
*/
public static URL parseURL(String address, Map<String, String> defaults) {
if (address == null || address.length() == 0) {
return null;
}
String url;
if (address.indexOf("://") >= 0) { // 地址中指定了协议
url = address;
} else {
String[] addresses = Constants.COMMA_SPLIT_PATTERN.split(address); // 多个服务器用,分割符
url = addresses[0];
if (addresses.length > 1) {
StringBuilder backup = new StringBuilder();
for (int i = 1; i < addresses.length; i++) {
if (i > 1) {
backup.append(",");
}
backup.append(addresses[i]);
}
url += "?" + Constants.BACKUP_KEY + "=" + backup.toString();
}
}
/**
* 到此为止url无非就3中格式
* - 指定了协议 protocol://ip:port
* - 没有指定协议
* - 只有一台主机 ip1:port1
* - 多台主机 ip1:port1?backup=ip2:port2,ip3:port3
*/
String defaultProtocol = defaults == null ? null : defaults.get("protocol");
if (defaultProtocol == null || defaultProtocol.length() == 0) {
defaultProtocol = "dubbo";
}
String defaultUsername = defaults == null ? null : defaults.get("username");
String defaultPassword = defaults == null ? null : defaults.get("password");
int defaultPort = StringUtils.parseInteger(defaults == null ? null : defaults.get("port"));
String defaultPath = defaults == null ? null : defaults.get("path");
Map<String, String> defaultParameters = defaults == null ? null : new HashMap<String, String>(defaults);
if (defaultParameters != null) {
defaultParameters.remove("protocol");
defaultParameters.remove("username");
defaultParameters.remove("password");
defaultParameters.remove("host");
defaultParameters.remove("port");
defaultParameters.remove("path");
}
URL u = URL.valueOf(url);
boolean changed = false;
String protocol = u.getProtocol();
String username = u.getUsername();
String password = u.getPassword();
String host = u.getHost();
int port = u.getPort();
String path = u.getPath();
Map<String, String> parameters = new HashMap<String, String>(u.getParameters());
if ((protocol == null || protocol.length() == 0) && defaultProtocol != null && defaultProtocol.length() > 0) {
changed = true;
protocol = defaultProtocol;
}
if ((username == null || username.length() == 0) && defaultUsername != null && defaultUsername.length() > 0) {
changed = true;
username = defaultUsername;
}
if ((password == null || password.length() == 0) && defaultPassword != null && defaultPassword.length() > 0) {
changed = true;
password = defaultPassword;
}
/*if (u.isAnyHost() || u.isLocalHost()) {
changed = true;
host = NetUtils.getLocalHost();
}*/
if (port <= 0) {
if (defaultPort > 0) {
changed = true;
port = defaultPort;
} else {
changed = true;
port = 9090;
}
}
if (path == null || path.length() == 0) {
if (defaultPath != null && defaultPath.length() > 0) {
changed = true;
path = defaultPath;
}
}
if (defaultParameters != null && defaultParameters.size() > 0) {
for (Map.Entry<String, String> entry : defaultParameters.entrySet()) {
String key = entry.getKey();
String defaultValue = entry.getValue();
if (defaultValue != null && defaultValue.length() > 0) {
String value = parameters.get(key);
if (value == null || value.length() == 0) {
changed = true;
parameters.put(key, defaultValue);
}
}
}
}
if (changed) {
u = new URL(protocol, username, password, host, port, path, parameters);
}
return u;
}
URL
// URL.java
private final String protocol; // 协议
private final String username;
private final String password;
// by default, host to registry
private final String host;
// by default, port to registry
private final int port;
private final String path; // 路径
private final Map<String, String> parameters;
自定义了URL
跟标准互联网URL比 多了3个部分
-
username
-
password
-
parameters
valueOf
// URL.java
/**
* 协议://用户名:密码@ip:port/路径
* - zookeeper://localhost:2181
* - zookeeper://bannirui:123456@localhost:2181
*/
public static URL valueOf(String url) {
if (url == null || (url = url.trim()).length() == 0) {
throw new IllegalArgumentException("url == null");
}
String protocol = null;
String username = null;
String password = null;
String host = null;
int port = 0;
String path = null;
Map<String, String> parameters = null;
int i = url.indexOf("?"); // seperator between body and parameters // 基础内容之外的附加信息?连接
if (i >= 0) {
String[] parts = url.substring(i + 1).split("\\&"); // 每一项基础内容&连接
parameters = new HashMap<String, String>();
for (String part : parts) {
part = part.trim();
if (part.length() > 0) {
int j = part.indexOf('=');
if (j >= 0) {
parameters.put(part.substring(0, j), part.substring(j + 1));
} else {
parameters.put(part, part);
}
}
}
url = url.substring(0, i);
}
// ignore the url content following '#'
int poundIndex = url.indexOf('#');
if (poundIndex != -1) {
url = url.substring(0, poundIndex);
}
i = url.indexOf("://"); // 协议分割符
if (i >= 0) {
if (i == 0) throw new IllegalStateException("url missing protocol: \"" + url + "\"");
protocol = url.substring(0, i);
url = url.substring(i + 3);
} else {
// case: file:/path/to/file.txt
i = url.indexOf(":/");
if (i >= 0) {
if (i == 0) throw new IllegalStateException("url missing protocol: \"" + url + "\"");
protocol = url.substring(0, i);
url = url.substring(i + 1);
}
}
i = url.indexOf("/");
if (i >= 0) {
path = url.substring(i + 1);
url = url.substring(0, i);
}
i = url.lastIndexOf("@");
if (i >= 0) {
username = url.substring(0, i);
int j = username.indexOf(":");
if (j >= 0) {
password = username.substring(j + 1);
username = username.substring(0, j);
}
url = url.substring(i + 1);
}
i = url.indexOf(":");
if (i >= 0 && i < url.length() - 1) {
port = Integer.parseInt(url.substring(i + 1));
url = url.substring(0, i);
}
if (url.length() > 0) host = url;
return new URL(protocol, username, password, host, port, path, parameters);
}
构造方法
// URL.java
public URL(String protocol, String username, String password, String host, int port, String path, Map<String, String> parameters) {
if ((username == null || username.length() == 0)
&& password != null && password.length() > 0) {
throw new IllegalArgumentException("Invalid url, password without username!");
}
this.protocol = protocol;
this.username = username;
this.password = password;
this.host = host;
this.port = (port < 0 ? 0 : port);
// trim the beginning "/"
while (path != null && path.startsWith("/")) {
path = path.substring(1);
}
this.path = path;
if (parameters == null) {
parameters = new HashMap<String, String>();
} else {
parameters = new HashMap<String, String>(parameters);
}
this.parameters = Collections.unmodifiableMap(parameters);
}
简单,就是直接属性赋值
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?