Jak sprawdzić prawidłowy adres URL w Javie?


96

Jaki jest najlepszy sposób sprawdzenia, czy adres URL jest prawidłowy w Javie?

Jeśli próbujesz zadzwonić new URL(urlString)i złapać MalformedURLException, ale wydaje się być zadowolony z wszystkiego, co się zaczyna http://.

Nie martwię się o ustanowienie połączenia, po prostu ważność. Czy jest na to metoda? Adnotacja w Hibernate Validator? Czy powinienem używać wyrażenia regularnego?

Edycja: niektóre przykłady akceptowanych adresów URL to http://***i http://my favorite site!.


Jak zdefiniujesz ważność, jeśli nie zamierzasz nawiązać połączenia?
Michael Myers

2
Czy możesz podać przykład czegoś, co nie jest prawidłowym adresem URL, który URLakceptuje konstruktor?
uckelman

1
@mmyers: Ważność powinna być określona przez RFCs 2396 i 2732, te, które definiują, czym jest adres URL.
uckelman

4
@uckelman: Prawie wszystko. „ http://***” działa. „ http://my favorite site!” działa. Nie mogę zmusić go do rzucenia wyjątku (kiedy http: // jest na początku.)
Eric Wilson,

2
możliwy duplikat Validating URL w Javie
JasonB

Odpowiedzi:


102

Rozważ użycie klasy Apache Commons UrlValidator

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

Istnieje kilka właściwości, które można ustawić, aby kontrolować, jak to klasa zachowuje się domyślnie http, httpsi ftpsą akceptowane.


7
wygląda na to, że nie działa z nowszymi domenami, takimi jak .london itp.
VH,

a co z adresami URL w intranecie?
Puneet

Nie weryfikuje adresów URL z podkreśleniami.
Udit Kumawat

Nie działa z nowymi TLD i lokalnymi nazwami domen, np. localItp.

Nie mogłem zmusić UrlValidator do pracy z naszą dziwną domeną intranetową najwyższego poziomu. Typowe, takie jak .com, .org i takie prace. Nie jestem zainteresowany tworzeniem RegExp w tej sprawie, więc rozwiązanie new URL(name).toURI()stało się rozwiązaniem.
Avec

60

Oto sposób, który wypróbowałem i okazał się przydatny,

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

1
Dobry. Użycie tylko nowego adresu URL (nazwy) akceptuje prawie wszystko. Url.toURI (); jest dokładnie tym, czego szuka programista - bez korzystania z innych bibliotek / frameworków!
justastefan

2
Nie zadziała to również w przypadku źle sformułowanych adresów URL, takich jak http: /google.com. Użyłem UrlValidator z Apache Commons.
start

1
Ten jest naprawdę niebezpieczny. Widzę, że istnieje wiele innych artykułów z tym przykładem. URL u = new URL(http://google).toURI();nie zgłosi wyjątku.
Sonu Oommen

@SonuOommen może dlatego, że new URL(http://google)jest ważna ^^ mamy w mojej firmie dużo domeny wewnętrznej takiej jak ta
user43968

8

Chciałbym to opublikować jako komentarz do odpowiedzi Tendayi Mawushe , ale obawiam się, że nie ma wystarczająco dużo miejsca;)

To jest odpowiednia część ze źródła 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;

Stamtąd możesz łatwo zbudować własny walidator.


6

Najbardziej „niezawodny” sposób to sprawdzenie dostępności adresu URL:

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

5

Moje ulubione podejście, bez zewnętrznych bibliotek:

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

Sądząc po kodzie źródłowym URI,

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

Konstruktor wykonuje więcej walidacji niż inne konstruktory. Możesz spróbować tego, ale YMMV.


3

Nie podobała mi się żadna z implementacji (ponieważ używają Regex, która jest kosztowną operacją lub biblioteki, która jest przesadą, jeśli potrzebujesz tylko jednej metody), więc ostatecznie użyłem klasy java.net.URI z niektórymi dodatkowe sprawdzenia i ograniczenie protokołów do: http, https, file, ftp, mailto, news, urn.

I tak, wychwytywanie wyjątków może być kosztowną operacją, ale prawdopodobnie nie tak złą, jak wyrażenia regularne:

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

pakiet walidatora:

Wygląda na to, że Yonatan Matalon stworzył fajny pakiet o nazwie UrlUtil . Cytując jego API:

isValidWebPageAddress(java.lang.String address, boolean validateSyntax, 
                      boolean validateExistance) 
Checks if the given address is a valid web page address.

Podejście firmy Sun - sprawdź adres sieciowy

Witryna Java firmy Sun oferuje próbę połączenia jako rozwiązanie do sprawdzania poprawności adresów URL.

Inne fragmenty kodu wyrażenia regularnego:

Istnieją próby weryfikacji wyrażeń regularnych w witrynie Oracle i weberdev.com .


1
Ten kod służy do sprawdzania linków, co stanowi inny problem. To pytanie dotyczy ważności adresu URL, a nie tego, czy można nawiązać z nim połączenie.
Michael Myers

Ten przykład dotyczy sprawdzenia, czy adres URL jest dostępny, a nie tego, czy jest poprawnie sformułowany.
uckelman

Zgoda, dodałem inne podejścia.
Adam Matan
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.