如何在 Java 中检查有效的 URL?

检查 URL 在 Java 中是否有效的最佳方法是什么?

如果尝试调用 new URL(urlString)并捕获一个 MalformedURLException,但它似乎很高兴与任何以 http://开始。

我不在乎建立联系,只在乎有效性。有什么办法吗?Hibernate Validator 中的注释?我应该使用正则表达式吗?

编辑: 一些被接受的 URL 例子是 http://***http://my favorite site!

146357 次浏览

验证程序包:

似乎有一个 Yonatan Matalon 的包装很漂亮,名叫 UrlUtil。引用其 API:

isValidWebPageAddress(java.lang.String address, boolean validateSyntax,
boolean validateExistance)
Checks if the given address is a valid web page address.

Sun 的方法-检查网络地址

Sun 的 Java 站点提供了验证 URL 的 连接尝试作为解决方案

其他正则表达式代码片段:

甲骨文的网站Weberdev.com有正则表达式验证尝试。

Consider using the ApacheCommons UrlValidator 类

UrlValidator urlValidator = new UrlValidator();
urlValidator.isValid("http://my favorite site!");

可以设置几个属性来控制此类的行为,默认情况下接受 httphttpsftp

根据 URI的源代码判断,

public URL(URL context, String spec, URLStreamHandler handler)

构造函数 比其他构造函数执行更多的验证。

这是我尝试并发现有用的方法,

URL u = new URL(name); // this would check for the protocol
u.toURI(); // does the extra checking required for validation of URI

我很想把这篇文章作为评论发表在 坦达伊 · 马武什的回答上,但恐怕没有足够的空间;)

这是 Apache Commons UrlValidator 来源中的相关部分:

/**
* This expression derived/taken from the BNF for URI (RFC2396).
*/
private static final String URL_PATTERN =
"/^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?/";
//         12            3  4          5       6   7        8 9


/**
* Schema/Protocol (ie. http:, ftp:, file:, etc).
*/
private static final int PARSE_URL_SCHEME = 2;


/**
* Includes hostname/ip and port number.
*/
private static final int PARSE_URL_AUTHORITY = 4;


private static final int PARSE_URL_PATH = 5;


private static final int PARSE_URL_QUERY = 7;


private static final int PARSE_URL_FRAGMENT = 9;

您可以从那里轻松地构建自己的验证器。

我不喜欢任何一个实现(因为它们使用的正则表达式是一个昂贵的操作,或者一个库,如果你只需要一个方法就是一个过度杀伤) ,所以我最终使用 java.net.URI 类进行了一些额外的检查,并将协议限制为: http,https,file,ftp,mailto,news,urn。

是的,捕捉异常可能是一项昂贵的操作,但可能没有正则表达式那么糟糕:

final static Set<String> protocols, protocolsWithHost;


static {
protocolsWithHost = new HashSet<String>(
Arrays.asList( new String[]{ "file", "ftp", "http", "https" } )
);
protocols = new HashSet<String>(
Arrays.asList( new String[]{ "mailto", "news", "urn" } )
);
protocols.addAll(protocolsWithHost);
}


public static boolean isURI(String str) {
int colon = str.indexOf(':');
if (colon < 3)                      return false;


String proto = str.substring(0, colon).toLowerCase();
if (!protocols.contains(proto))     return false;


try {
URI uri = new URI(str);
if (protocolsWithHost.contains(proto)) {
if (uri.getHost() == null)      return false;


String path = uri.getPath();
if (path != null) {
for (int i=path.length()-1; i >= 0; i--) {
if ("?<>:*|\"".indexOf( path.charAt(i) ) > -1)
return false;
}
}
}


return true;
} catch ( Exception ex ) {}


return false;
}

My favorite approach, without external libraries:

try {
URI uri = new URI(name);


// perform checks for scheme, authority, host, etc., based on your requirements


if ("mailto".equals(uri.getScheme()) {/*Code*/}
if (uri.getHost() == null) {/*Code*/}


} catch (URISyntaxException e) {
}

最“简单”的方法是检查 URL 的可用性:

public boolean isURL(String url) {
try {
(new java.net.URL(url)).openStream().close();
return true;
} catch (Exception ex) { }
return false;
}