Как получить доступ к статическим ресурсам при отображении сервлета глобального фронт-контроллера в / * - PullRequest
57 голосов
/ 15 мая 2009

Я отобразил диспетчер Spring MVC как сервлет глобального фронт-контроллера на /*.

<servlet>       
  <servlet-name>home</servlet-name>         
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>     
</servlet>  
<servlet-mapping>       
  <servlet-name>home</servlet-name>         
  <url-pattern>/*</url-pattern>     
</servlet-mapping>

Однако это сопоставление останавливает доступ к статическим файлам, таким как CSS, JS, изображения и т. Д., Которые находятся в папке /res/.

Как я могу получить к ним доступ в любом случае?

Ответы [ 18 ]

70 голосов
/ 29 августа 2010

Отобразите сервлет контроллера на более конкретный url-pattern, например /pages/*, поместите статический контент в определенную папку, например /static, и создайте Filter прослушивающий /*, который прозрачно продолжает цепочку для любого статического содержимого и отправляет запросы сервлету контроллера для другого содержимого.

В двух словах:

<filter>
    <filter-name>filter</filter-name>
    <filter-class>com.example.Filter</filter-class>
</filter>
<filter-mapping>
    <filter-name>filter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<servlet>
    <servlet-name>controller</servlet-name>
    <servlet-class>com.example.Controller</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>controller</servlet-name>
    <url-pattern>/pages/*</url-pattern>
</servlet-mapping>

со следующими параметрами в фильтре doFilter():

HttpServletRequest req = (HttpServletRequest) request;
String path = req.getRequestURI().substring(req.getContextPath().length());

if (path.startsWith("/static")) {
    chain.doFilter(request, response); // Goes to default servlet.
} else {
    request.getRequestDispatcher("/pages" + path).forward(request, response);
}

Нет, это не заканчивается /pages в адресной строке браузера. Это полностью прозрачно. При необходимости вы можете сделать "/static" и / или "/pages" init-param из фильтра.

43 голосов
/ 24 января 2011

С Spring 3.0.4.RELEASE и выше вы можете использовать

<mvc:resources mapping="/resources/**" location="/public-resources/"/>

Как видно из Ссылка на пружину .

19 голосов
/ 17 августа 2010

Что вы делаете, это добавляете файл приветствия в ваш web.xml

<welcome-file-list>
    <welcome-file>index.html</welcome-file>
</welcome-file-list>

А затем добавьте это в сопоставления ваших сервлетов, чтобы, когда кто-то переходил в корень вашего приложения, он отправлялся на index.html внутренне, а затем сопоставление внутренне отправляло его сервлету, который вы сопоставили с

<servlet-mapping>
    <servlet-name>MainActions</servlet-name>
    <url-pattern>/main</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>MainActions</servlet-name>
    <url-pattern>/index.html</url-pattern>
</servlet-mapping>

Конечный результат: Вы посещаете / Приложение, но вам представлен сервлет / Приложение / MainActions без прерывания любых других корневых запросов.

Получите это? Таким образом, ваше приложение все еще находится на дополнительном URL, но автоматически отображается, когда пользователь переходит в корень вашего сайта. Это позволяет вам /images/bob.img по-прежнему переходить на обычное место, но «/» - это ваше приложение.

17 голосов
/ 26 мая 2009

Если вы используете Tomcat, вы можете сопоставить ресурсы сервлету по умолчанию:

<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>/static/*</url-pattern>
</servlet-mapping>

и получите доступ к ресурсам с помощью URL http://{context path} / static / res /...

Также работает с Jetty, но не уверен насчет других контейнеров сервлетов.

16 голосов
/ 03 января 2012

Обслуживание статического контента с соответствующим суффиксом в нескольких определениях сервлет-сопоставления решило проблему безопасности, которая упоминается в одном из комментариев в одном из опубликованных ответов. Цитируется ниже:

Это была дыра в безопасности в Tomcat (таким образом доступны материалы WEB-INF и META-INF), и она была исправлена ​​в 7.0.4 (а также будет перенесена в 5.x и 6.x) - BalusC 2 ноября 2010 года в 22: 44

, который мне очень помог. И вот как я это решил:

<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.js</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.css</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.jpg</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.htm</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.html</url-pattern>
</servlet-mapping>
12 голосов
/ 15 мая 2009

Я тоже сталкивался с этим и никогда не находил отличного решения. Я закончил отображать свой сервлет на один уровень выше в иерархии URL:

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

И теперь все в базовом контексте (и в вашем каталоге / res) может обслуживаться вашим контейнером.

9 голосов
/ 02 ноября 2010

Начиная с версии 3.0.4, вы можете использовать mvc:resources в сочетании с mvc:default-servlet-handler, как описано в документации к пружине, для достижения этой цели.

http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/mvc.html#mvc-static-resources

5 голосов
/ 15 декабря 2009

Кажется, что причина конфликта заключается в том, что по умолчанию корень контекста "/" должен обрабатываться org.apache.catalina.servlets.DefaultServlet. Этот сервлет предназначен для обработки запросов на статические ресурсы.

Если вы решите исключить его с помощью своего собственного сервлета с целью обработки динамических запросов, этот сервлет верхнего уровня также должен выполнять любые задачи, выполняемые оригинальным обработчиком catalina "DefaultServlet".

Если вы читаете документы Tomcat, они упоминают, что True Apache (httpd) лучше, чем Apache Tomcat, для обработки статического содержимого, поскольку он специально создан для этого. Я предполагаю, что Tomcat по умолчанию использует org.apache.catalina.servlets.DefaultServlet для обработки статических запросов. Поскольку все это заключено в JVM, а Tomcat предназначен для использования в качестве контейнера Servlet / JSP, они, вероятно, не написали этот класс как супероптимизированный обработчик статического содержимого. Это здесь. Это делает работу. Достаточно хорошо.

Но это то, что обрабатывает статический контент, и он живет в "/". Так что, если вы положите туда что-нибудь еще, и эта штука не будет обрабатывать статические запросы, WHOOPS, туда уйдут ваши статические ресурсы.

Я искал один и тот же ответ все выше и ниже, и ответ, который я получаю повсюду: «Если ты не хочешь, чтобы это делалось, не делай этого».

Короче говоря, ваша конфигурация заменяет обработчик статических ресурсов по умолчанию чем-то, что вообще не является обработчиком статических ресурсов. Вам нужно будет попробовать другую конфигурацию, чтобы получить результаты, которые вы ищете (как и я).

3 голосов
/ 30 сентября 2009

Статические файлы в App Engine не доступны напрямую вашему приложению. Вам нужно либо загрузить их дважды, либо обслуживать статические файлы самостоятельно, а не использовать статический обработчик.

2 голосов
/ 18 сентября 2010

Лучший способ справиться с этим - переписать URL. Таким образом, вы можете иметь чистые спокойные URL-адреса, а НЕ с какими-либо расширениями, например, abc.com/welcom/register, а не abc.com/welcome/resister.html

.

Я использую Tuckey URL , что довольно круто.

В нем есть инструкции по настройке вашего веб-приложения. Я настроил его с помощью моего веб-приложения Spring MVC. Конечно, все было хорошо, пока я не захотел использовать аннотации для валидации Spring 3, например @Email или @Null для доменных объектов.

Когда я добавляю директивы Spring mvc:

< mvc:annotation-driven  /> 
< mvc:default-servlet-handler />

.. это нарушает старый добрый код Tuckey. Очевидно, < mvc:default-servlet-handler /> заменяет Тьюки, который я все еще пытаюсь решить.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...