Разница между / и / * в шаблоне url сопоставления сервлетов

знакомый код:

<servlet-mapping>
    <servlet-name>main</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>

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

насколько я понимаю, это /* карты http://host:port/context/*.

как о /? Он уверен, что не сопоставляется с http://host:port/context только root. На самом деле, он примет http://host:port/context/hello, но отказать http://host:port/context/hello.jsp.

может кто-нибудь объяснить, как это http://host:port/context/hello сопоставляется?

5 ответов


<url-pattern>/*</url-pattern>

на /* на сервлете переопределяет все другие сервлеты, включая все сервлеты, предоставляемые servletcontainer, такие как сервлет по умолчанию и сервлет JSP. Какой бы запрос вы ни запросили, он окажется в этом сервлете. Таким образом, это плохой шаблон URL для сервлетов. Обычно, вы хотели бы использовать /* на Filter только. Он может позволить запросу продолжить любой из сервлетов, прослушивающих более конкретный шаблон URL, вызвав FilterChain#doFilter().

<url-pattern>/</url-pattern>

на / не переопределяет любой другой сервлет. Он заменяет встроенный сервлет servletcontainer по умолчанию только для всех запросов, которые не соответствуют другим зарегистрированным сервлетам. Обычно это вызывается только на статических ресурсах (CSS/JS/image / etc) и списках каталогов. Встроенный сервлет servletcontainer по умолчанию также способен работать с HTTP-запросами кэша, потоковой передачей мультимедиа (аудио/видео) и загрузкой файлов возобновляет. Обычно вы не хотите переопределять сервлет по умолчанию, поскольку в противном случае вам придется заботиться обо всех его задачах, что не совсем тривиально (JSF utility library OmniFaces есть открыть источник пример). Таким образом, это также плохой шаблон URL для сервлетов. Что касается того, почему страницы JSP не попадают в этот сервлет, это потому, что будет вызван встроенный сервлет JSP servletcontainer, который уже по умолчанию сопоставлен с более конкретным URL шаблон *.jsp.

<url-pattern></url-pattern>

тогда есть также пустая строка URL pattern . This will be invoked when the context root is requested. This is different from the <welcome-file> подход, который не вызывается, когда запрашивается любая подпапка. Это, скорее всего, шаблон URL, который вы на самом деле ищете, если вы хотите "Домашняя страница сервлет". Я только должен признать, что я интуитивно ожидал бы пустой шаблон URL-адреса строки и шаблон url Слэш / быть определено точно наоборот, поэтому я могу поймите, что многие стартеры запутались в этом. Но это то, что есть.

Фронт-Контроллера

в случае, если вы на самом деле намеревайтесь иметь сервлет переднего контроллера, тогда вам лучше сопоставить его с более конкретным шаблоном URL, таким как *.html, *.do, /pages/*, /app/*, etc. Вы можете скрыть шаблон URL переднего контроллера и покрыть статические ресурсы на общем шаблоне URL, таком как /resources/*, /static/*, etc с помощью фильтра сервлета. Смотреть также как предотвратить обработку статических ресурсов сервлетом переднего контроллера, который отображается на /*. Следует отметить, что Spring MVC имеет встроенный статический сервлет ресурсов, поэтому вы можете отобразить его передний контроллер на / если вы настраиваете общий шаблон URL для статических ресурсов весной. См. также как обрабатывать статический контент в Spring MVC?


Я хотел бы дополнить ответ BalusC правилами отображения и примером.

правила отображения из спецификации сервлета 2.5:

  1. карта точный URL
  2. карта путей по шаблону
  3. карта расширения
  4. сопоставить сервлет по умолчанию

в нашем примере, есть три сервлеты. / - установленный нами сервлет по умолчанию. Tomcat устанавливает два сервлета для обслуживания jsp и jspx. Итак, на карту http://host:port/context/hello

  1. не установлены точные сервлеты URL, далее.
  2. сервлеты подстановочных путей не установлены, Далее.
  3. не соответствует никаким расширениями, далее.
  4. сопоставьте сервлет по умолчанию, return.

на карте http://host:port/context/hello.jsp

  1. не установлены точные сервлеты URL, далее.
  2. сервлеты подстановочных путей не установлены, Далее.
  3. найдено расширение сервлета, возврат.

Возможно, вам нужно знать, как отображаются URL-адреса, так как я страдал 404 в течение нескольких часов. Существует два вида обработчиков запросов. BeanNameUrlHandlerMapping и SimpleUrlHandlerMapping. Когда мы определили servlet-mapping, мы используем SimpleUrlHandlerMapping. Нам нужно знать, что эти два обработчика имеют общее свойство под названием alwaysUseFullPath значение по умолчанию false.

false здесь означает, что Spring не будет использовать полный путь для сопоставления url-адреса с контроллером. Что это значит? Это означает, когда вы определяете servlet-mapping:

<servlet-mapping>
    <servlet-name>viewServlet</servlet-name>
    <url-pattern>/perfix/*</url-pattern>
</servlet-mapping>

обработчик будет использовать * часть, чтобы найти контроллер. Например, следующий контроллер столкнется с 404 ошибка при запросе с помощью /perfix/api/feature/doSomething

@Controller()
@RequestMapping("/perfix/api/feature")
public class MyController {
    @RequestMapping(value = "/doSomething", method = RequestMethod.GET) 
    @ResponseBody
    public String doSomething(HttpServletRequest request) {
        ....
    }
}

это идеальный матч, не так ли? Но почему?--2-->. Как упоминалось ранее, значение по умолчанию alwaysUseFullPath false, что означает, в Вашему желанию, только /api/feature/doSomething используется для поиска соответствующего контроллера, но контроллер не заботится об этом пути. Вам нужно либо измените свой url на /perfix/perfix/api/feature/doSomething или удалить perfix из базы MyController @RequestingMapping.


Я думаю, что ответ Candy в основном правильный. Есть одна маленькая часть, я думаю иначе.

для отображения хоста: порт / контекст / привет.jsp

  1. не установлены точные сервлеты URL, далее.
  2. найдены подстановочные пути сервлетов, вернуть.

Я считаю, что почему " / * "не соответствует host:port/context/hello, потому что он рассматривает" /hello " как путь вместо файла (поскольку он не имеет расширения).


существенная разница между /* и / это сервлет с отображением /* будет выбран перед любым сервлетом с отображением расширения (например,*.html), в то время как сервлет сопоставления с / будет выбран только после рассмотрения сопоставлений расширений (и будет использоваться для любого запроса, который не соответствует ничему другому---это "сервлет по умолчанию").

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

либо будет выбран только после сопоставления сервлетов, которые являются точными совпадениями (например,/foo/bar), и те, которые являются отображениями путь длиннее, чем /* (типа /foo/*). Обратите внимание, что пустое сопоставление строк точно соответствует корневому контексту (http://host:port/context/).

см. Главу 12 спецификации сервлета Java, доступной в версии 3.1 на http://download.oracle.com/otndocs/jcp/servlet-3_1-fr-eval-spec/index.html.