Подтвердить что ты не робот

Правильный способ проверки равенства URL

У меня есть следующий сценарий:

URL u1 = new URL("http://www.yahoo.com/");
URL u2 = new URL("http://www.yahoo.com");

if (u1.equals(u2)) {
    System.out.println("yes");
}
if (u1.toURI().equals(u2.toURI())) {
    System.out.println("uri equality");
}
if (u1.toExternalForm().equals(u2.toExternalForm())) {
    System.out.println("external form equality");
}
if (u1.toURI().normalize().equals(u2.toURI().normalize())) {
    System.out.println("uri normalized equality");
}

Ни одна из этих проверок не выполняется. Только путь отличается: u1 имеет путь "/", а u2 имеет путь к "". Являются ли эти URL-адреса, указывающие на один и тот же ресурс, и есть ли способ проверить такую ​​вещь, не открывая соединение? Я неправильно понимаю что-то фундаментальное в отношении URL-адресов?

РЕДАКТИРОВАТЬ. Я должен указать, что требуется нехитрый чек. Можно ли сказать, что пустой путь ==/? Я надеялся не иметь такой код

4b9b3361

Ответ 1

Из JavaOne 2007:

Вторая головоломка, названная "More Joys of Sets", позволяет пользователю создавать ключи HashMap, которые состоят или несколько объектов URL. Опять же, большая часть аудитории не смогла угадать правильный ответ.

Важная вещь, которую узнала аудитория здесь, заключается в том, что метод equals() объекта URL, по сути, нарушен. В этом случае два объекта URL равны, если они разрешают один и тот же IP-адрес и порт, а не только, если они имеют одинаковые строки. Тем не менее, Блох и Пью указывают на еще более серьезную ахиллесову пяту: поведение равенства отличается в зависимости от того, подключены ли вы к сети, где виртуальные адреса могут разрешаться на одном и том же хосте, или если вы не в сети, где разрешение - операция блокировки. Итак, что касается извлеченных уроков, они рекомендуют:

Не использовать URL; вместо этого используйте URI. URI не пытается сравнивать адреса или порты. Кроме того, не используйте URL как элемент Set или ключ карты.
Для разработчиков API метод equals() не должен зависеть от среды. Например, в этом случае равенство не должно изменяться, если компьютер подключен к Интернету по сравнению с автономным.


Из документации URI равна:

Для того чтобы два иерархических URI считались равными, их пути должны быть равны, и их запросы должны либо быть undefined, либо равными.

В вашем случае два пути различны. один - "/", другой - "".


В соответствии с URI RFC §6.2.3:

Реализации могут использовать правила конкретной схемы, при дальнейшей обработке    чтобы уменьшить вероятность ложных негативов. Например,    потому что схема "http" использует компонент полномочий, имеет    порт по умолчанию "80" и определяет пустой путь, эквивалентный     "/" следующие четыре URI эквивалентны:

 http://example.com
 http://example.com/
 http://example.com:/
 http://example.com:80/

Кажется, что эта реализация не использует правила, специфичные для схемы.


Ресурсы:

Ответ 2

Строго говоря, они не равны. Необязательный трейлинг-косая черта (/) - это обычное использование, но не обязательное. Вы можете отображать разные страницы для

http://www.yahoo.com/foo/

и для

http://www.yahoo.com/foo

Это возможно даже для того, который вы предоставили. Я считаю, что HTTP-заголовок может пропустить эту косую черту.

Ответ 3

Вы всегда можете сравнить относительные URL-адреса с методом Path.equals

ех.

Paths.get("/user/login").equals(Paths.get("/user/login/")))

создать true

Вы также можете использовать startWith/endsWith-methods