Разница между / и /* в шаблоне отображения сервлета
Знакомый код:
<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
только корень. На самом деле, он примет http://host:port/context/hello
, но отклонить http://host:port/context/hello.jsp
,
Может кто-нибудь объяснить, как это http://host:port/context/hello
сопоставляются?
5 ответов
<url-pattern>/*</url-pattern>
/*
в сервлете переопределяет все остальные сервлеты, включая все сервлеты, предоставляемые контейнером сервлетов, такие как сервлет по умолчанию и сервлет JSP. Какую бы просьбу вы не уволили, она окажется в этом сервлете. Таким образом, это плохой шаблон URL для сервлетов. Обычно вы хотели бы использовать /*
на Filter
только. Он может разрешить выполнение запроса любому сервлету, прослушивающему более конкретный шаблон URL, вызвав FilterChain#doFilter()
,
<url-pattern>/</url-pattern>
/
не переопределяет любой другой сервлет. Он заменяет только встроенный сервлет по умолчанию для сервлет-контейнера для всех запросов, которые не соответствуют ни одному другому зарегистрированному сервлету. Обычно это вызывается только для статических ресурсов (CSS/JS/image/etc) и списков каталогов. Встроенный в сервлет контейнер сервлетов по умолчанию также может обрабатывать запросы кеша HTTP, потоковую передачу мультимедиа (аудио / видео) и возобновление загрузки файлов. Обычно вы не хотите переопределять сервлет по умолчанию, так как в противном случае вам придется позаботиться обо всех его задачах, что не совсем тривиально (служебная библиотека JSF OmniFaces имеет пример с открытым исходным кодом). Таким образом, это также плохой шаблон URL для сервлетов. Почему JSP-страницы не попадают в этот сервлет, это потому, что будет вызван встроенный сервлет JSP сервлет-контейнера, который по умолчанию уже сопоставлен с более конкретным шаблоном URL. *.jsp
,
<url-pattern></url-pattern>
Тогда есть также шаблон URL пустой строки , Это будет вызвано при запросе корневого контекста. Это отличается от
<welcome-file>
подход, который не вызывается, когда запрашивается любая подпапка. Скорее всего, это шаблон URL, который вы на самом деле ищете, если вам нужен " сервлет домашней страницы ". Я только должен признать, что я бы интуитивно ожидал шаблон URL пустой строки и шаблон URL косой черты
/
определиться с точностью до наоборот, так что я могу понять, что многие начинающие люди запутались в этом. Но что есть, то есть.
Фронт-контроллер
В случае, если вы действительно хотите иметь сервлет фронт-контроллера, лучше всего сопоставить его с более конкретным шаблоном URL, таким как *.html
, *.do
, /pages/*
, /app/*
и т. д. Вы можете скрыть шаблон URL фронт-контроллера и скрыть статические ресурсы в общем шаблоне URL, например /resources/*
, /static/*
и т. д. с помощью фильтра сервлетов. Смотрите также Как предотвратить обработку статических ресурсов сервлетом фронт-контроллера, который отображается в / *. Следует отметить, что Spring MVC имеет встроенный сервлет статического ресурса, поэтому вы можете отобразить его фронт-контроллер на /
если вы настроите общий шаблон URL для статических ресурсов в Spring. Смотрите также Как обрабатывать статический контент в Spring MVC?
Я хотел бы дополнить ответ BalusC правилами сопоставления и примером.
Правила отображения из спецификации Servlet 2.5:
- Точный URL карты
- Карта подстановочных путей
- Расширения карты
- Сопоставить с сервлетом по умолчанию
В нашем примере есть три сервлета. / - это установленный нами сервлет по умолчанию. Tomcat устанавливает два сервлета для обслуживания jsp и jspx. Так к карте http://host:port/context/hello
- Следующие URL-адреса не установлены.
- Следующие сервлеты не установлены.
- Не соответствует никаким расширениям, следующий.
- Карта к сервлету по умолчанию, возврат.
На карту http://host:port/context/hello.jsp
- Следующие URL-адреса не установлены.
- Следующие сервлеты не установлены.
- Нашли расширение сервлета, верните.
Возможно, вам нужно знать, как отображаются 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) {
....
}
}
Это идеальный матч, верно? Но почему 404
, Как упоминалось ранее, значение по умолчанию alwaysUseFullPath
ложно, что означает в вашем запросе только /api/feature/doSomething
используется для поиска соответствующего Контроллера, но Контроллер не заботится об этом пути. Вам нужно либо изменить свой URL-адрес на /perfix/perfix/api/feature/doSomething
или удалить perfix
из базы MyController @RequestingMapping
,
Я думаю, что ответ Кенди в основном правильный. Есть одна маленькая часть, я думаю иначе.
Для сопоставления хоста:port/context/hello.jsp
- Следующие URL-адреса не установлены.
- Найдены подстановочные пути, сервлеты, вернемся.
Я полагаю, что почему "/*" не соответствует host:port/context/hello, потому что он рассматривает "/ hello" как путь вместо файла (так как он не имеет расширения).
Существенная разница между /*
а также /
это сервлет с отображением /*
будет выбран перед любым сервлетом с отображением расширения (например, *.html
), пока сервлет с отображением /
будет выбран только после того, как будут рассмотрены сопоставления расширений (и будет использоваться для любого запроса, который не соответствует ничему другому - это "сервлет по умолчанию").
В частности, /*
отображение всегда будет выбрано до /
отображение. Наличие либо предотвращает любые запросы от достижения собственного сервлета по умолчанию контейнера.
Любой из них будет выбран только после сопоставлений сервлета, которые точно совпадают (например, /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.