Кто-нибудь может объяснить сервлетное сопоставление? - PullRequest
51 голосов
/ 24 октября 2008

Я пытаюсь написать веб-приложение, используя SpringMVC. Обычно я просто сопоставляю какое-то готовое расширение файла с фронт-контроллером Spring и живу счастливо, но на этот раз я собираюсь использовать REST-подобные URL-адреса без расширений имени файла.

Отображение всего моего контекстного пути на фронт-контроллер (назовем его « app ») означает, что я должен также позаботиться о статических файлах, чего я бы не хотел делать (зачем изобретать еще одну weel ?), так что некоторая комбинация с сервлетом tomcat по умолчанию (назовем его « tomcat ») кажется подходящей.

У меня есть вещь, которая работает, делая что-то вроде

<servlet-mapping>
  <servlet-name>app</servlet-name>
  <url-pattern>/</url-pattern>
</servlet-mapping>

<servlet-mapping>
  <servlet-name>tomcat</servlet-name>
  <url-pattern>*.ext</url-pattern>
</servlet-mapping>

и повторение последнего для каждого из расширений файлов моего статического контента. Мне просто интересно, почему следующие настройки, которые для меня эквивалентны приведенным выше, не работают.

<!-- failed attempt #1 -->
<servlet-mapping>
  <servlet-name>app</servlet-name>
  <url-pattern>/*</url-pattern>
</servlet-mapping>

<servlet-mapping>
  <servlet-name>tomcat</servlet-name>
  <url-pattern>*.ext</url-pattern>
</servlet-mapping>

<!-- failed attempt #2 -->
<servlet-mapping>
  <servlet-name>app</servlet-name>
  <url-pattern>/</url-pattern>
</servlet-mapping>

<servlet-mapping>
  <servlet-name>tomcat</servlet-name>
  <url-pattern>/some-static-content-folder/*</url-pattern>
</servlet-mapping>

Может кто-нибудь пролить свет?

Ответы [ 3 ]

43 голосов
/ 29 октября 2008

Думаю, я знаю, что происходит.

В вашем рабочем web.xml вы установили свой сервлет в качестве сервлета по умолчанию (/ сам по себе является сервлетом по умолчанию, вызываемым, если нет других совпадений), он ответит на любой запрос, который не соответствует другому сопоставлению.

В Failed 1 ваше / * отображение действительно является допустимым отображением пути. С помощью сопоставления / * в web.xml он отвечает на все запросы, кроме других сопоставлений путей. Согласно спецификации отображения расширения являются неявными отображениями, которые перезаписываются явными отображениями. Вот почему сопоставление расширений не удалось. Все было явно сопоставлено с приложением.

В Failed 2 приложение отвечает за все, кроме контента, который соответствует статическому сопоставлению контента. Чтобы показать, что происходит в быстром тесте, я настроил. Вот пример. /some-static-content-folder/ содержит test.png

Попытка доступа к test.png Я попытался:

/some-static-content-folder/test.png

и файл не найден. Однако пытаясь

/some-static-content-folder/some-static-content-folder/test.png

это подходит. Поэтому кажется, что сервлет Tomcat по умолчанию (по крайней мере, 6.0.16) отбрасывает отображение сервлета и пытается найти файл, используя оставшийся путь. Согласно этому сообщению Servlet для обслуживания статического контента Jetty показывает поведение, которое вы и я ожидали.

По какой-то причине вы не можете сделать что-то вроде сопоставления корневого каталога для ваших остальных вызовов? Что-то вроде приложения, сопоставленного с / rest_root / *, чем вы несете ответственность за все, что происходит в папке rest_root, но в любом другом месте должен обрабатываться Tomcat, если вы не сделаете другое явное сопоставление. Я предлагаю настроить ваш оставшийся сервлет на отображение пути, потому что оно объявляет намерение лучше. Использование / или / * не представляется целесообразным, так как вы должны отобразить исключения. Используя SO в качестве примера, мои остальные сопоставления будут выглядеть примерно так:

/ users / * для пользовательского сервлета

/ posts / * для сервлета сообщений

Порядок отображения

  1. Явный (отображение пути)
  2. Неявный (сопоставления расширений)
  3. По умолчанию (/)

Пожалуйста, исправьте все, что я ошибся.

3 голосов
/ 31 октября 2014

Для справки, "неудачная попытка # 2" совершенно верна в версии Tomcat> = до 6.0.29.

Это было результатом ошибки Tomcat, исправленной в версии 6.0.29:

https://issues.apache.org/bugzilla/show_bug.cgi?id=50026

<!-- Correct for Tomcat >= 6.0.29 or other Servlet containers -->
<servlet-mapping>
  <servlet-name>app</servlet-name>
  <url-pattern>/</url-pattern>
</servlet-mapping>

<servlet-mapping>
  <servlet-name>default</servlet-name>
  <url-pattern>/some-static-content-folder/*</url-pattern>
</servlet-mapping>
2 голосов
/ 28 октября 2008

Я никогда не пытался отобразить такой сервлет, но я утверждал бы, что / * технически оба начинаются с / и заканчиваются на / *, даже если один и тот же символ используется для обоих совпадений .

...