如何验证URL在Java 1.6中是否有效?

时间:2010-06-29 08:18:19

标签: java url parsing

我的应用程序处理用户手动输入的网址。我发现一些格式错误的URL(如'http:/ not-valid')导致在打开连接时抛出NullPointerException。正如我从this Java bug report那里了解到的那样,这个问题是众所周知的,不会被修复。建议是使用java.net.URI,这是“更符合RFC 2396”。

问题是:如何使用URI来解决问题?我唯一能用URI做的就是用它来解析字符串并生成URL。我准备了以下程序:

import java.net.*;

public class Test
{
    public static void main(String[] args)
    {
       try {
           URI uri = URI.create(args[0]);
           Object o = uri.toURL().getContent(); // try to get content
       }
       catch(Throwable e) {
           e.printStackTrace();
       }
    }
}

以下是我的测试结果(使用java 1.6.0_20),与java.net.URL的测试结果差别不大:

sh-3.2$ java Test url-not-valid
java.lang.IllegalArgumentException: URI is not absolute
        at java.net.URI.toURL(URI.java:1080)
        at Test.main(Test.java:9)
sh-3.2$ java Test http:/url-not-valid
java.lang.NullPointerException
        at sun.net.www.ParseUtil.toURI(ParseUtil.java:261)
        at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:795)
        at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:726)
        at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1049)
        at java.net.URLConnection.getContent(URLConnection.java:688)
        at java.net.URL.getContent(URL.java:1024)
        at Test.main(Test.java:9)
sh-3.2$ java Test http:///url-not-valid
java.lang.IllegalArgumentException: protocol = http host = null
        at sun.net.spi.DefaultProxySelector.select(DefaultProxySelector.java:151)
        at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:796)
        at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:726)
        at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1049)
        at java.net.URLConnection.getContent(URLConnection.java:688)
        at java.net.URL.getContent(URL.java:1024)
        at Test.main(Test.java:9)
sh-3.2$ java Test http:////url-not-valid
java.lang.NullPointerException
        at sun.net.www.ParseUtil.toURI(ParseUtil.java:261)
        at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:795)
        at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:726)
        at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1049)
        at java.net.URLConnection.getContent(URLConnection.java:688)
        at java.net.URL.getContent(URL.java:1024)
        at Test.main(Test.java:9)

3 个答案:

答案 0 :(得分:1)

如果我使用错误报告中的格式错误的URI类型运行您的代码,则会抛出URISyntaxException。因此,建议的修复程序修复了报告的错误。

$ java -cp bin UriTest http:\\\\www.google.com\\
java.lang.IllegalArgumentException
    at java.net.URI.create(URI.java:842)
    at UriTest.main(UriTest.java:8)
Caused by: java.net.URISyntaxException: Illegal character in opaque part at index 5: http:\\www.google.com\
    at java.net.URI$Parser.fail(URI.java:2809)
    at java.net.URI$Parser.checkChars(URI.java:2982)
    at java.net.URI$Parser.parse(URI.java:3019)
    at java.net.URI.(URI.java:578)
    at java.net.URI.create(URI.java:840)

您的格式错误的URI类型不同,似乎不是语法错误。

相反,捕获空指针异常并使用合适的消息进行恢复。

您可以尝试友好并检查URI是否以单个斜杠“http:/”开头,并向用户建议,或者您可以检查URL的主机名是否为非空:

import java.net.*;

public class UriTest
{
    public static void main ( String[] args )
    {
        try {
            URI uri = URI.create ( args[0] );

            // avoid null pointer exception
            if ( uri.getHost() == null )
                throw new MalformedURLException ( "no hostname" );

            URL url = uri.toURL();
            URLConnection s = url.openConnection();

            s.getInputStream();
        } catch ( Throwable e ) {
            e.printStackTrace();
        }
    }
}

答案 1 :(得分:1)

您可以使用apache Validator Commons ..

UrlValidator urlValidator = new UrlValidator();
urlValidator.isValid("http://google.com");

http://commons.apache.org/validator/

http://commons.apache.org/validator/api-1.3.1/

答案 2 :(得分:0)

请注意,即使使用其他答案中提出的方法,您也无法获得正确的验证,因为java.net.URI遵守RFC 2396,这显然已过时。使用java.net.URI,您将获得当前对所有网络浏览器都有效的网址的例外情况。

为了解决这些问题,我在Java中编写了一个用于URL解析的库:galimatias。它以与Web浏览器相同的方式执行URL解析(遵守WHATWG URL Specification)。

在你的情况下,你可以写:

try {
    URL url = io.mola.galimatias.URL.parse(url).toJavaURL();
} catch (GalimatiasParseException e) {
    // If this exception is thrown, the given URL contains a unrecoverable error. That is, it's completely invalid.
}

作为一个很好的副作用,你会得到许多你在java.net.URI获得的消毒。例如,http:/example.com将被正确解析为http://example.com/