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

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

Сопоставление всего, что связано с моим контекстным путём к переднему контроллеру (пусть его называют " приложение" ) означает, что я должен позаботиться и о статических файлах, чего я бы предпочел не делать (зачем изобретать еще один 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>

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

Ответ 1

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

В вашем рабочем 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/* для сервлета сообщений

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

  • Явные (сопоставления пути)
  • Неявные (расширения).
  • По умолчанию (/)

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

Ответ 2

Для справки, "неудачная попытка № 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>

Ответ 3

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