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


92

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

如果试图打电话来new URL(urlString)接住一个MalformedURLException,但似乎对以开头的任何东西都很满意http://

我不关心建立连接,只是有效性。有办法吗?Hibernate Validator中的注释?我应该使用正则表达式吗?

编辑:http://***和 URL的一些示例http://my favorite site!


如果您不打算建立连接,如何定义有效性?
迈克尔·迈尔斯

2
您能否举一个例子,说明那些不是URL构造方法接受的有效URL ?
uckelman 2010年

1
@mmyers:有效性应由定义URL是什么的RFC 2396和2732确定。
uckelman 2010年

4
@uckelman:几乎任何事情。“ http://***”有效。“ http://my favorite site!”有效。我无法引发异常(当http://开头时。)
Eric Wilson 2010年

Answers:


100

考虑使用Apache Commons UrlValidator类

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

有几个属性,您可以设置来控制如何类的行为,在默认情况下httphttpsftp被接受。


7
它似乎不适用于更新的域,例如.london等
VH

Intranet网址如何?
浦那(Puneet)

它不使用下划线验证网址。
Udit Kumawat

是否与新顶级域名和本地域名,例如,不工作local

我无法让UrlValidator与我们怪异的Intranet顶级域一起使用。常见的诸如.com,.org之类的作品。我对此事没有兴趣创建RegExp,因此new URL(name).toURI()成为解决方案。
Avec

59

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

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

1
好一个 仅使用新的URL(name)即可接受几乎所有内容。url.toURI(); 正是开发人员想要的-无需使用其他库/框架!
justastefan 2012年

2
这对于格式错误的网址(例如http:/google.com)也无效。我使用了来自Apache Commons的UrlValidator。
starf 2014年

1
这真的很危险。我看到这个示例还有很多其他文章。URL u = new URL(http://google).toURI();不会抛出异常。
Sonu Oommen,

@SonuOommen也许是因为new URL(http://google)有效^^我们在公司中有很多这样的内部域
user43968

8

我很乐意将其发布为对Tendayi Mawushe的回答的评论,但恐怕空间不足;)

这是来自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;

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


6

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

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

4

我最喜欢的方法,没有外部库:

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) {
}

3

从的源代码来看URI

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

构造函数比其他构造函数执行更多的验证。您可以尝试那个,但是可以使用YMMV。


3

我不喜欢任何一种实现(因为它们使用正则表达式是一个昂贵的操作,或者如果您只需要一种方法,那么它是一个过大的库),所以我最终将java.net.URI类与某些实现一起使用额外检查,并将协议限制为:http,https,文件,ftp,mailto,新闻、,。

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

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;
}

2

验证程序包:

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。

其他正则表达式代码段:

Oracle的站点weberdev.com上进行了正则表达式验证尝试。


1
该代码用于检查链接,这是另一个问题。这个问题是关于URL的有效性,而不是是否可以建立连接。
迈克尔·迈尔斯

本示例是关于检查URL是否可用,而不是格式是否正确。
uckelman 2010年

同意,增加其他方法。
亚当·马坦
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.