2013-03-13 3 views
19

У меня есть файл web.xml с содержанием:Как используются сопоставления url сервлета в 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 
+0

Может быть, вы не используете текущую версию вашего веб-приложения. Используете ли вы IDE? Как вы развертываете? – Uooo

+1

/path/test подходит для правила/path/test/*, они находятся в конфликте. –

+0

похоже, что вы прокомментировали часть кода по ошибке ..... check/* .... не комментируется ... ну, может быть, я ошибаюсь, но это то, что вы скопировали выше справа. – AurA

ответ

44

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

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

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

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

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

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

  • A строка, начинающаяся с символа ‘/’ и заканчивающаяся ‘/*’ суффиксом используется для сопоставления пути.

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

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

  • Строка, содержащая только символ ’/’, указывает сервлет приложения «по умолчанию» приложения. В этом случае путь сервлета является 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 принадлежит к 5 точке спецификации отображений. Это означает, что только пути, заканчивающиеся на /path/test, будут нацелены на servlet1.

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

.../path/test будет обработана servlet1 и

.../path/test/abc будет обработан servlet2

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

+2

@wfr, почему вы ответили на этот ответ? Кажется, вы не согласны с вашим наблюдением, что servlet2 обрабатывается/path/test. –

+0

Спасибо. Вы решили мой вопрос здесь: http://stackoverflow.com/questions/33522888/how-does-the-getservletmapping-affects-the-url-in-spring-webmvc – smwikipedia

1

Ваши конфликты.

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

Вы обычно ставят в путь с именем Servlet, как, например:

/path/test/servlet1 
/path/test/servlet2 
Смежные вопросы