Как используются сопоставления url сервлета в web.xml? - программирование
Подтвердить что ты не робот

Как используются сопоставления url сервлета в web.xml?

У меня есть файл web.xml с контентом:

<servlet>
    <servlet-name>servlet1</servlet-name>
    <servlet-class>org.mycompany.test1</servlet-class>
</servlet>
<servlet>
    <servlet-name>servlet2</servlet-name>
    <servlet-class>org.mycompany.test2</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>servlet1</servlet-name>
    <url-pattern>/path/test</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>servlet2</servlet-name>
    <url-pattern>/path/test/*</url-pattern>
</servlet-mapping>

Я пробовал запросы

.../path/test/abc 
.../path/test

Оба запроса обрабатываются Servlet2. Почему?

UPDATE

Спасибо, ребята, за вашу помощь. Я понял, что поведение зависит от порядка объявления сервлет-отображения. Я пробовал этот web.xml

<servlet>
    <servlet-name>servlet1</servlet-name>
    <servlet-class>org.mycompany.test1</servlet-class>
</servlet>
<servlet>
    <servlet-name>servlet2</servlet-name>
    <servlet-class>org.mycompany.test2</servlet-class>
</servlet>
<servlet>
    <servlet-name>servlet3</servlet-name>
    <servlet-class>org.mycompany.test3</servlet-class>
</servlet>
<servlet>
    <servlet-name>servlet4</servlet-name>
    <servlet-class>org.mycompany.test4</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>servlet1</servlet-name>
    <url-pattern>/path/test</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>servlet2</servlet-name>
    <url-pattern>/path/test/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>servlet3</servlet-name>
    <url-pattern>/path/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>servlet4</servlet-name>
    <url-pattern>/path</url-pattern>
</servlet-mapping>

результаты:

.../path/test/abc - servlet2
.../path/test/ - servlet2
.../path/test - servlet2

.../path/abc - servlet3
.../path/ - servlet4
.../path - servlet4
4b9b3361

Ответ 1

Из Servlet 3.0 спецификация, вот как веб-контейнер должен найти сервлет после получения запроса (выделение мое):

Путь, используемый для сопоставления сервлету, - это URL-адрес запроса от объект запроса минус путь контекста и параметры пути. Ниже приведены правила сопоставления URL-адресов. Первый успешный матч используется без каких-либо последующих попыток:

  • Контейнер попытается найти точное соответствие пути запроса к пути сервлета. Успешный матч выбирает сервлета.
  • Контейнер будет рекурсивно пытаться сопоставить самый длинный префикс пути. Это делается путем перехода вниз по дереву путей в каталог в то время, используя символ/как разделитель путей. Самый длинный match определяет выбранный сервлет.
  • Если последний сегмент пути URL содержит расширение (например,.jsp), контейнер сервлета будет пытаться сопоставить сервлет, который обрабатывает запросы на расширение. Расширение определяется как часть последний сегмент после последнего. характер.
  • Если ни одно из предыдущих трех правил не приводит к совпадению сервлета, контейнер будет пытаться обслуживать контент, соответствующий запрашиваемый ресурс. Если для приложение, оно будет использоваться. Многие контейнеры обеспечивают неявное сервлет по умолчанию для обслуживания содержимого.

В контейнере должны использоваться сопоставления строк с учетом регистра для соответствия.

Вы также должны посмотреть спецификацию сопоставлений (см. ниже):

В дескрипторе развертывания веб-приложения следующий синтаксис используется для определения отображений:

  • Строка начинается с символа ‘/’ и заканчивается суффиксом ‘/*’используется для отображения пути.

  • Строка, начинающаяся с префикса ‘*.’, используется как отображение расширений.

  • Пустая строка ("") - это специальный шаблон URL, который точно соответствует корень контекста приложения, то есть запросы формы http://host:port/<contextroot>/. В этом случае информация о пути ’/’ и путь сервлета и путь контекста - пустая строка ("").

  • Строка, содержащая только символ ’/’, указывает на "default" сервлет приложения. В этом случае путь сервлета является запросить URI минус контекстный путь, а информация о пути - null.

  • Все остальные строки используются только для точных совпадений

Рассмотрим теперь примеры. Рассмотрим следующий набор отображений:

Path Pattern            Servlet
/foo/bar/*              servlet1
/baz/*                  servlet2
/catalog                servlet3
*.bop                   servlet4

Следующее поведение приведет к:

Incoming Path           Servlet Handling Request
/foo/bar/index.html     servlet1
/foo/bar/index.bop      servlet1
/baz                    servlet2
/baz/index.html         servlet2
/catalog                servlet3
/catalog/index.html     "default" servlet
/catalog/racecar.bop    servlet4
/index.bop              servlet4

Обратите внимание, что в случае /catalog/index.html и /catalog/racecar.bop, сервлет, отображаемый на "/catalog", не используется, потому что совпадение не является точным.

Теперь приступим к вашей проблеме:)

/path/test принадлежит к пятой точке спецификации отображений. Это означает, что только пути, заканчивающиеся на /path/test, будут нацелены на servlet1.

Однако /path/test/* подходит для первой точки той же спецификации. Это означает, что:

.../path/test будет обрабатываться servlet1 и

.../path/test/abc будет обрабатываться servlet2

Это было проверено мной в тестовом приложении.

Ответ 2

Конфликты ваших путей.

Оба из ваших путей означают то же самое, "/*" не имеет никакого значения. По-видимому, тогда, когда вы пытаетесь использовать свой путь, выполняется последнее совпадение (servlet2).

Обычно вы указываете путь с именем сервлета, например:

/path/test/servlet1
/path/test/servlet2