Javaで有効なURLを確認するにはどうすればよいですか?


92

URLがJavaで有効かどうかを確認する最良の方法は何ですか?

を呼び出しnew URL(urlString)てキャッチしようとした場合は、MalformedURLExceptionで始まるすべてに満足しているようhttp://です。

私は接続の確立については心配していません。有効性についてだけです。これには方法がありますか?Hibernate Validatorの注釈?正規表現を使用する必要がありますか?

編集: 受け入れられるURLの例にはhttp://***、およびがあり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://先頭である。)
エリック・ウィルソン

回答:


100

Apache Commons UrlValidatorクラスの使用を検討してください

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

このクラスの動作を制御するために設定できるいくつかのプロパティがあり、デフォルトhttpでは、、httpsおよびftp受け入れられます。


7
.londonなどの新しいドメインでは動作しないようです
VH

イントラネットのURLはどうですか?
Puneet

アンダースコアでURLを検証しません。
Udit Kumawat 2018年

新しいTLDやローカルドメイン名(例:localなど)では機能しません

UrlValidatorを私たちの奇妙なイントラネットのトップレベルドメインで動作させることができませんでした。.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などの不正なURLでも機能しません。Apache CommonsのUrlValidatorを使用しました。
starf

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

私はどの実装も好きではありませんでした(高価な操作であるRegex、またはメソッドが1つしか必要ない場合はやり過ぎであるライブラリを使用しているため)。追加のチェック、およびプロトコルの制限: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;
}

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への接続を確立できるかどうかではありません。
マイケルマイヤーズ

この例は、URLが正しいかどうかではなく、URLが使用可能かどうかを確認するためのものです。
uckelman、2010

同意し、他のアプローチを追加しました。
2010
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.