我的应用程序处理用户手动输入的网址。我发现一些格式错误的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)
答案 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");
答案 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/
。