URL表示统一资源定位器,指向世界上“资源”的指针万维网。资源可以是简单的文件或目录,或者它可以是对更复杂对象的引用,例如对数据库或搜索引擎的查询。这个类的作用就是URL的定位的作用,定位了每个资源符号引用的位置。整个URL大体上就是对URL内容进行规范,对URL进行解析。
构造方法是通过文件里面的端口和文件的访问主机对这个URL进行构造。
public URL(String protocol, String host, int port, String file)
throws MalformedURLException
{
this(protocol, host, port, file, null);
}
URL的构造方法,这个构造方法里面传输了URL里面的协议,主机名,端口号和文件名,最后通过流协议处理器来进行URL的解析。
public URL(String protocol, String host, int port, String file,
URLStreamHandler handler) throws MalformedURLException {
if (handler != null) {
//安全管理器检查
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkSpecifyHandler(sm);
}
}
protocol = protocol.toLowerCase();
this.protocol = protocol;
//判断主机名是否为空
if (host != null) {
//根据冒号和中括号来判断主机名是否是ip地址
if (host.indexOf(':') >= 0 && !host.startsWith("[")) {
host = "["+host+"]";
}
this.host = host;
//端口号小于-1,抛出异常说明这个端口号是无效端口。
if (port < -1) {
throw new MalformedURLException("Invalid port number :" +
port);
}
this.port = port;
//判断主机名中是否有端口号
authority = (port == -1) ? host : host + ":" + port;
}
//Parts类对文件的信息进行处理。
Parts parts = new Parts(file);
path = parts.getPath();
query = parts.getQuery();
if (query != null) {
this.file = path + "?" + query;
} else {
this.file = path;
}
ref = parts.getRef();
//注意:我们这里没有对URL进行完全验证。因为太冒险会变化。现在,但仅供将来参考。-比尔
if (handler == null &&
(handler = getURLStreamHandler(protocol)) == null) {
throw new MalformedURLException("unknown protocol: " + protocol);
}
this.handler = handler;
//调用URL流处理器来进行URL的解析。
if (host != null && isBuiltinStreamHandler(handler)) {
//IP地址工具类,检查存在的表单。
String s = IPAddressUtil.checkExternalForm(this);
if (s != null) {
throw new MalformedURLException(s);
}
}
//判断是否是jar的连接协议
if ("jar".equalsIgnoreCase(protocol)) {
if (handler instanceof sun.net.www.protocol.jar.Handler) {
String s = ((sun.net.www.protocol.jar.Handler) handler).checkNestedProtocol(file);
if (s != null) {
throw new MalformedURLException(s);
}
}
}
}
URL反序列化状态值
public UrlDeserializedState(String protocol,
String host, int port,
String authority, String file,
String ref, int hashCode) {
this.protocol = protocol;
this.host = host;
this.port = port;
this.authority = authority;
this.file = file;
this.ref = ref;
this.hashCode = hashCode;
}
文件信息分离,分离“#”符号以后的引用内容,分离"?"以后的参数。见文末“#”引用在URL地址中的作用。
class Parts {
String path, query, ref;
Parts(String file) {
//分割URL中“#”引用符号
int ind = file.indexOf('#');
ref = ind < 0 ? null: file.substring(ind + 1);
file = ind < 0 ? file: file.substring(0, ind);
int q = file.lastIndexOf('?');
if (q != -1) {
query = file.substring(q+1);
path = file.substring(0, q);
} else {
path = file;
}
}
String getPath() {
return path;
}
String getQuery() {
return query;
}
String getRef() {
return ref;
}
}
URL读取内容处理方法。设置URLStreamHandler 目的是为了进行开启连接和进行URL的字符串的解析。
private Object readResolve() throws ObjectStreamException {
URLStreamHandler handler = null;
//已签入readObject
handler = getURLStreamHandler(tempState.getProtocol());
URL replacementURL = null;
//判断流处理器是否是从sun.net.www.protocol调用
if (isBuiltinStreamHandler(handler.getClass().getName())) {
//配置新的URL
replacementURL = fabricateNewURL();
} else {
//设置反序列化的参数
replacementURL = setDeserializedFields(handler);
}
return replacementURL;
}
//设置URL反序列化参数。
private URL setDeserializedFields(URLStreamHandler handler) {
URL replacementURL;
String userInfo = null;
String protocol = tempState.getProtocol();
String host = tempState.getHost();
int port = tempState.getPort();
String authority = tempState.getAuthority();
String file = tempState.getFile();
String ref = tempState.getRef();
int hashCode = tempState.getHashCode();
//构建权限部分
if (authority == null
&& ((host != null && host.length() > 0) || port != -1)) {
if (host == null)
host = "";
authority = (port == -1) ? host : host + ":" + port;
//处理包含用户信息的主机
int at = host.lastIndexOf('@');
if (at != -1) {
userInfo = host.substring(0, at);
host = host.substring(at+1);
}
} else if (authority != null) {
//构建用户信息部分
int ind = authority.indexOf('@');
if (ind != -1)
userInfo = authority.substring(0, ind);
}
//构造路径和查询部分
String path = null;
String query = null;
if (file != null) {
//修正:只有在等级制度下才能这样做?
int q = file.lastIndexOf('?');
if (q != -1) {
query = file.substring(q+1);
path = file.substring(0, q);
} else
path = file;
}
//设置对象字段。
this.protocol = protocol;
this.host = host;
this.port = port;
this.file = file;
this.authority = authority;
this.ref = ref;
this.hashCode = hashCode;
this.handler = handler;
this.query = query;
this.path = path;
this.userInfo = userInfo;
replacementURL = this;
return replacementURL;
}
static final String BUILTIN_HANDLERS_PREFIX = "sun.net.www.protocol";
boolean isBuiltinStreamHandler(URLStreamHandler handler) {
Class<?> handlerClass = handler.getClass();
return isBuiltinStreamHandler(handlerClass.getName())
|| (handlerClass.getClassLoader() == null);
}
private boolean isBuiltinStreamHandler(String handlerClassName) {
return (handlerClassName.startsWith(BUILTIN_HANDLERS_PREFIX));
}
//临时参数存放
private transient UrlDeserializedState tempState;
private URL fabricateNewURL()
throws InvalidObjectException {
//从反序列化对象创建URL字符串
URL replacementURL = null;
//获取URL字符串
String urlString = tempState.reconstituteUrlString();
try {
replacementURL = new URL(urlString);
} catch (MalformedURLException mEx) {
resetState();
InvalidObjectException invoEx = new InvalidObjectException(
"Malformed URL: " + urlString);
invoEx.initCause(mEx);
throw invoEx;
}
replacementURL.setSerializedHashCode(tempState.getHashCode());
resetState();
return replacementURL;
}
final class UrlDeserializedState {
private final String protocol;
private final String host;
private final int port;
private final String authority;
private final String file;
private final String ref;
private final int hashCode;
public UrlDeserializedState(String protocol,
String host, int port,
String authority, String file,
String ref, int hashCode) {
this.protocol = protocol;
this.host = host;
this.port = port;
this.authority = authority;
this.file = file;
this.ref = ref;
this.hashCode = hashCode;
}
//预计算StringBuilder的长度
int len = protocol.length() + 1;
if (authority != null && authority.length() > 0)
len += 2 + authority.length();
if (file != null) {
len += file.length();
}
if (ref != null)
len += 1 + ref.length();
StringBuilder result = new StringBuilder(len);
result.append(protocol);
result.append(":");
if (authority != null && authority.length() > 0) {
result.append("//");
result.append(authority);
}
if (file != null) {
result.append(file);
}
if (ref != null) {
result.append("#");
result.append(ref);
}
return result.toString();
}
}
附:URL类的使用方法
https://www.cnblogs.com/blackiesong/p/6182038.html
URL中#的作用
https://www.cnblogs.com/kaituorensheng/p/3776527.html