【问题标题】:How to check for a valid URL in Java?如何在 Java 中检查有效的 URL?
【发布时间】:2011-01-14 21:34:15
【问题描述】:

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

如果尝试调用new URL(urlString) 并捕获MalformedURLException,但它似乎对以http:// 开头的任何内容感到满意。

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

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

【问题讨论】:

  • 如果你不打算建立连接,你如何定义有效性?
  • 你能举个例子说明URL构造函数接受的不是有效的URL吗?
  • @mmyers:有效性应由定义 URL 的 RFC 2396 和 2732 确定。
  • @uckelman:几乎任何事情。 “http://***”有效。 “http://my favorite site!”有效。我无法让它抛出异常(当 http:// 开头时)。
  • Validating URL in Java 的可能重复项

标签: java validation url


【解决方案1】:

URI的源代码来看,

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

constructor 比其他构造函数做更多的验证。你可以试试那个,但是 YMMV。

【讨论】:

    【解决方案2】:

    最“万无一失”的方法是检查 URL 的可用性:

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

    【讨论】:

    • 实际查询 URL 可能会导致更改、操作或跟踪。 OP 想要在不进行查询的情况下检查有效性。例如,也许这是现在存储并稍后执行,并合理保证它是有效的。
    【解决方案3】:

    我不喜欢其中的任何一个实现(因为它们使用了一个昂贵的操作的正则表达式,或者如果你只需要一种方法,那么一个库就是一个矫枉过正的工具),所以我最终使用了 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;
    }
    

    【讨论】:

      【解决方案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) {
      }
      

      【讨论】:

        【解决方案5】:

        我很想将此作为评论发布到Tendayi Mawushe's answer,但恐怕没有足够的空间;)

        这是来自 Apache Commons UrlValidator source 的相关部分:

        /**
         * 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 u = new URL(name); // this would check for the protocol
          u.toURI(); // does the extra checking required for validation of URI 
          

          【讨论】:

          • 好一个。仅使用 new URL(name) 几乎可以接受所有内容。 url.toURI();正是开发人员正在寻找的 - 无需使用其他库/框架!
          • 这也不适用于格式错误的 URL,例如 http:/google.com。我使用了 Apache Commons 的 UrlValidator。
          • 这个真的很危险。我看到这个例子还有很多其他的文章。 URL u = new URL(http://google).toURI(); 不会抛出异常。
          • @SonuOommen 可能是因为new URL(http://google) 有效^^ 我们公司有很多这样的内部域
          【解决方案7】:

          考虑使用Apache Commons UrlValidator class

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

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

          【讨论】:

          • 它似乎不适用于 .london 等较新的域
          • 内网url怎么样?
          • 它不验证带有下划线的网址。
          • 不适用于新 TLD 和本地域名,例如local
          • 我无法让 UrlValidator 与我们奇怪的 Intranet 顶级域一起使用。常见的如 .com、.org 等作品。我对为此创建 RegExp 不感兴趣,因此 new URL(name).toURI() 成为解决方案。
          【解决方案8】:

          验证器包:

          似乎有一个nice package by Yonatan Matalon called 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 站点提供 connect attempt as a solution 用于验证 URL。

          其他正则表达式代码sn-ps:

          Oracle's siteweberdev.com 有正则表达式验证尝试。

          【讨论】:

          • 该代码用于检查链接,这是一个不同的问题。这个问题是关于 URL 的有效性,而不是是否可以建立到它的连接。
          • 这个例子是检查URL是否可用,而不是检查它是否格式正确。
          • 同意,添加了其他方法。
          猜你喜欢
          • 2022-11-19
          • 2015-03-20
          • 2014-07-24
          • 2021-10-12
          • 2018-05-15
          • 2011-06-21
          • 1970-01-01
          • 2012-05-20
          相关资源
          最近更新 更多