Подтвердить что ты не робот

Как получить доступ к статическим ресурсам при сопоставлении глобального сервлет-контроллера на/*

Я сопоставил диспетчер MVC Spring как глобальный сервлет суперконтроллера на /*.

<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/.

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

Сопоставьте сервлет контроллера с более конкретным 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" a init-param фильтра.

Ответ 3

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

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

Как видно из Spring Ссылка.

Ответ 4

Что вы делаете, это добавить приветственный файл в ваш 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>

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

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

Ответ 5

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

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

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

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

Ответ 6

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

Это было отверстие безопасности в Tomcat (содержимое WEB-INF и META-INF доступно таким образом), и оно было исправлено в 7.0.4 (и будет перенесено на 5.x и 6.x). - BalusC 2 ноября 10 в 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>

Ответ 8

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

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

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

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

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

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

Ответ 9

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

Ответ 10

Лучший способ справиться с этим - использовать повторную запись 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 />

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

Ответ 11

Добавьте папки, которые вы не хотите запускать сервлет-обработку в разделе <static-files> вашего файла appengine-web.xml.

Я просто сделал это и, похоже, все начинает работать нормально. Здесь моя структура:

/

/pages/<.jsp files >

/CSS

Я добавил "/pages/**" и "/css/**" в раздел <static-files>, и теперь я могу перенаправить в .jsp файл из сервлета doGet, не вызывая бесконечного цикла.

Ответ 12

После неудачного попытки использовать фильтр (он почему-то не ввел функцию doFilter()), я немного изменил свою настройку и нашел очень простое решение проблемы с корневой службой:

Вместо того, чтобы служить "/*" в моем основном сервлете я теперь только слушаю префикс языка "EN", "EN/*", "DE", "DE/*"

Статический контент получает Servlet по умолчанию, а пустые запросы root идут в index.jsp, который вызывает мой основной сервлет с языком по умолчанию:

< jsp: include page = "/EN/" /" > (на странице индекса нет другого содержимого.)

Ответ 13

Я обнаружил, что используя

<mvc:default-servlet-handler />

в файле spring MVC-сервлет bean работает для меня. Он передает любой запрос, который не обрабатывается зарегистрированным контроллером MVC для исходного обработчика по умолчанию контейнера, который должен служить ему как статический контент. Просто убедитесь, что у вас нет зарегистрированного контроллера, который обрабатывает все, и он должен работать нормально. Не знаю, почему @logixplayer предлагает переписывать URL-адреса; вы можете добиться эффекта, который он просто ищет, используя только spring MVC.

Ответ 14

Я бы рекомендовал использовать фильтр, а не сервлет по умолчанию, когда это возможно.

Другие две возможности:

Напишите файл FileServlet самостоятельно. Вы найдете много примеров, он должен просто открыть файл по URL-адресу и записать его содержимое в выходной поток. Затем используйте его для обслуживания статического запроса файла.

Создайте экземпляр класса FileServlet, используемого Google App Engine, и вызовите службу (запрос, ответ) в этом FileServlet, когда вам нужно будет обслуживать статический файл по заданному URL.

Вы можете сопоставить /res/ * с вашимFileServlet или любым другим, чтобы исключить его из обработки DispatcherServlets или вызвать его непосредственно из DispatcherServlet.

И я должен спросить, что документация Spring говорит об этом столкновении? Я никогда не использовал его.

Ответ 15

Я нашел более простое решение с файлом фиктивного индекса.

Создайте сервлет (или используйте тот, который вы хотите ответить на "/" ), который отображается на "/index.html" (Решения, упомянутые здесь, используют отображение через XML, я использовал версию 3.0 с аннотацией @WebServlet) Затем создайте статический (пустой) файл в корневом каталоге статического содержимого с именем "index.html"

Я использовал Jetty, и произошло то, что сервер распознал файл, а не список, но при запросе ресурса мой Servlet взял на себя управление вместо этого. Все остальное статическое содержимое оставалось неизменным.

Ответ 16

В Embedded Jetty мне удалось добиться чего-то подобного, добавив сопоставление для каталога "css" в web.xml. Явно говорю ему использовать DefaultServlet:

<servlet>
  <servlet-name>DefaultServlet</servlet-name>
  <servlet-class>org.eclipse.jetty.servlet.DefaultServlet</servlet-class>
</servlet>

<servlet-mapping>
  <servlet-name>DefaultServlet</servlet-name>
  <url-pattern>/css/*</url-pattern>
</servlet-mapping>

Ответ 17

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<mvc:default-servlet-handler/>
</beans>

и если вы хотите использовать настройку на основе аннотации, используйте код ниже

@Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }