Різниця між / і / * в шаблоні URL-адрес відображення сервлетів


175

Знайомий код:

<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відображено?

Відповіді:


268

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

Значення /*сервлета замінює всі інші сервлети, включаючи всі сервлети, надані контейнером сервлетів, такими як сервлет за замовчуванням та сервлет JSP. Який би запит ви не стріляли, він опиниться в тій серветці. Таким чином, це поганий шаблон URL-адрес для сервлетів. Як правило, ви хотіли б використовувати /*на Filterтільки. Він може дозволити продовжувати запит будь-якому з сервлетів, які слухають більш конкретний шаблон URL-адреси, зателефонувавши FilterChain#doFilter().

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

/Чи не скасовує будь-який інший сервлет. Він замінює лише вбудований серверт за замовчуванням servletcontainer для всіх запитів, який не відповідає жодному іншому зареєстрованому сервлету. Зазвичай це викликається лише на статичних ресурсах (CSS / JS / image / тощо) та списках каталогів. Вбудований серверт за замовчуванням в сервлет-контейнер також може вирішувати запити кеша 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 MVC?


9
Дякую. Після деяких досліджень я хотів би уточнити тонку точку. / замінює сервлет за замовчуванням, який встановлює веб-сервер. Наприклад, Tomcat встановлює DefaultServlet, який обслуговує статичні ресурси. Використання / позбавлення сервлета за замовчуванням як (швидше за все небажаний) побічний ефект.
Candy Chiu

Ну, я б не назвав це "перезаписом", а "заміною". Це може бути корисно замінити сервлет за замовчуванням таким.
BalusC

1
<url-pattern> </url-pattern> видає помилку: Недійсний <url-pattern> в сервлетському картографуванні
тонкий

Повідомлення про помилку було від tomcat, а не моєї IDE; однак я використовую Tomcat 6, так що, мабуть, це проблема;)
стрункий

2
@BalusC, скажіть, будь ласка, про який /**шаблон вказує?
Саджіб Ачарія

45

Я хотів би доповнити відповідь BalusC правилами картографування та прикладом.

Правила картографування із специфікації Servlet 2.5:

  1. Точна URL-адреса на карті
  2. Позначити магістральні шляхи
  3. Розширення карт
  4. Мапа до сервлету за замовчуванням

У нашому прикладі є три серветки. / - сервлет за замовчуванням, встановлений нами. Tomcat встановлює два сервлети для обслуговування jsp та jspx. Отже, на картіhttp://host:port/context/hello

  1. Далі не встановлено точних сервлетів URL-адрес.
  2. Не встановлено сервлетів для магістральних шляхів.
  3. Не відповідає жодним розширенням, наступне.
  4. Мапа до сервлету за замовчуванням, повернення.

На карту http://host:port/context/hello.jsp

  1. Далі не встановлено точних сервлетів URL-адрес.
  2. Не встановлено сервлетів для магістральних шляхів.
  3. Знайдено розширення сервлета, повернення.

25

Можливо, вам потрібно знати, як відображаються також URL-адреси, оскільки я страждав 404годинами. Існує два види обробників, що обробляють запити. BeanNameUrlHandlerMappingі SimpleUrlHandlerMapping. Коли ми визначили a 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. Як згадувалося раніше, значення за замовчуванням значення alwaysUseFullPathfalse - це означає, що у вашому запиті /api/feature/doSomethingвикористовується лише для пошуку відповідного контролера, але немає жодного контролера, який піклується про цей шлях. Вам потрібно або змінити URL-адресу, /perfix/perfix/api/feature/doSomethingабо вилучити його perfixз бази MyController @RequestingMapping.


8

Я думаю, що відповідь Кенді здебільшого правильна. Є одна невелика частина, яку я думаю інакше.

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

  1. Далі не встановлено точних сервлетів URL-адрес.
  2. Знайдені підстановочні стежки сервлетів , повернення.

Я вважаю, що чому "/ *" не відповідає хосту: port / context / hello, оскільки він розглядає "/ hello" як шлях замість файлу (оскільки у нього немає розширення).


2

Істотна відмінність між /*і в /тому , що сервлет з відображенням /*буде обраний до будь-якого сервлета з відображенням розширення (як *.html), в той час як сервлет з відображенням /буде обраний тільки після відображення розширення вважається (і буде використовуватися для будь-якого запиту , який Байдуже » t відповідати будь-що інше --- це "сервлет за замовчуванням").

Зокрема, перед /*картографуванням завжди буде вибиратися /відображення. Будь-яка забороняє будь-яким запитам досягати власного сервлету за замовчуванням контейнера.

Буде вибрано лише після відображення сервлетів, які є точними збігами (на зразок /foo/bar) та тими, які відображають шлях довше, ніж /*(як /foo/*). Зауважте, що відображення порожнього рядка є точно збігом кореня контексту ( http://host:port/context/).

Дивіться Розділ 12 Специфікації Java Servlet, доступний у версії 3.1 за адресою http://download.oracle.com/otndocs/jcp/servlet-3_1-fr-eval-spec/index.html .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.