Как обрабатывать статический контент в Spring MVC?
я разрабатываю веб-приложение с помощью Spring MVC 3 и имею DispatcherServlet ловить все запросы к'/', как так (web.xml):
<servlet>
<servlet-name>app</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>app</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
теперь это работает как рекламируется, однако, как я могу обрабатывать статический контент? Раньше, прежде чем использовать RESTful url, я бы поймал все *.html например и отправил это в DispatcherServlet, но теперь это другая игра в мяч.
у меня есть /static/ папка, которая включает /styles/, /js/, / images / etc, и я хотел бы исключить /static/* из DispatcherServlet.
теперь я мог получить статические ресурсы, работающие, когда я сделал это:
<servlet-mapping>
<servlet-name>app</servlet-name>
<url-pattern>/app/</url-pattern>
</servlet-mapping>
но я хочу, чтобы у него были хорошие URL-адреса (точка меня с помощью Spring MVC 3), а не целевая страница www.domain.com/app/
Я также не хочу, чтобы решение было связано с tomcat или любым другим контейнером сервлетов, и поскольку это (относительно) низкий трафик, мне не нужен веб-сервер (например, apache httpd) infront.
есть чистое решение для этого?
22 ответов:
так как я потратил много времени на эту проблему, я решил поделиться своим решением. Начиная с весны 3.0.4, есть параметр конфигурации, который называется
<mvc:resources/>(подробнее об этом на сайт справочной документации), который может использоваться для обслуживания статических ресурсов, все еще используя DispatchServlet в корне вашего сайта.чтобы использовать это, используйте структуру каталогов, которая выглядит следующим образом:
src/ springmvc/ web/ MyController.java WebContent/ resources/ img/ image.jpg WEB-INF/ jsp/ index.jsp web.xml springmvc-servlet.xmlсодержимое файлов должно выглядит так:
src / springmvc/web / HelloWorldController.java:
package springmvc.web; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class HelloWorldController { @RequestMapping(value="/") public String index() { return "index"; } }WebContent/WEB-INF / web.XML-код:
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>WebContent/WEB-INF / springmvc-сервлет.XML-код:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <!-- not strictly necessary for this example, but still useful, see http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/mvc.html#mvc-ann-controller for more information --> <context:component-scan base-package="springmvc.web" /> <!-- the mvc resources tag does the magic --> <mvc:resources mapping="/resources/**" location="/resources/" /> <!-- also add the following beans to get rid of some exceptions --> <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" /> <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"> </bean> <!-- JSTL resolver --> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" /> <property name="prefix" value="/WEB-INF/jsp/" /> <property name="suffix" value=".jsp" /> </bean> </beans>WebContent/jsp / index.jsp:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <h1>Page with image</h1> <!-- use c:url to get the correct absolute path --> <img src="<c:url value="/resources/img/image.jpg" />" />надеюсь, что это помогает :-)
эта проблема решается весной 3.0.4.Релиз, где вы можете использовать
<mvc:resources mapping="..." location="..."/>элемент конфигурации в конфигурационный файл Spring диспетчером.Регистрация Весна Документации
Весной 3.0.x добавьте в ваш сервлет-конфиг следующее.XML-файл (файл, который настроен в web.xml как contextConfigLocation. Вам также нужно добавить пространство имен mvc, но просто google для этого, если вы не знаете, как это сделать! ;)
это работает для меня
<mvc:default-servlet-handler/>в отношении
Аюб Малик
Если я правильно понимаю вашу проблему, я думаю, что нашел решение вашей проблемы:
У меня была та же проблема, когда вывод raw был показан без стилей css, javascripts или файлов jquery.
Я только что добавил сопоставления в сервлет" по умолчанию". В Сеть было добавлено следующее.xml-файл:
<servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.css</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.js</url-pattern> </servlet-mapping>Это должно отфильтровать запросы файлов javascript и css от объекта DispatcherRequest.
опять же, не уверен, что это то, что вы после, но это сработало для меня. Я думаю, что "default" - это имя сервлета по умолчанию в JBoss. Не слишком уверен, что это для других серверов.
есть еще один столб переполнения стека, который имеет отличное решение.
он не кажется Tomcat конкретным, прост и отлично работает. Я пробовал несколько решений в этом посте с spring mvc 3.1, но затем возникли проблемы с получением моего динамического контента.
короче говоря, он говорит добавить отображение сервлета следующим образом:
<servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>/images/*</url-pattern> </servlet-mapping>
Я только что боролся с этой проблемой весной MVC 3.0, и я изначально пошел с опцией UrlRewriteFilter. Однако я не был доволен этим решением, поскольку он "не чувствовал себя правильно" (я не единственный - см. ссылку выше на весенние форумы, где слово "hack" появляется несколько раз).
поэтому я придумал аналогичное решение для" неизвестного (Google) " выше, но позаимствовал идею о том, что все статическое содержимое подается из /static/ (взято из версии Spring Roo Приложение для зоомагазина). Сервлет" по умолчанию " не работал для меня, но Spring Webflow ResourceServlet сделал (также взятый из приложения Spring Roo generated).
Web.XML-код:
<servlet> <servlet-name>mainDispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>2</load-on-startup> </servlet> <servlet> <servlet-name>Resource Servlet</servlet-name> <servlet-class>org.springframework.js.resource.ResourceServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>mainDispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>Resource Servlet</servlet-name> <url-pattern>/static/*</url-pattern> </servlet-mapping>единственное изменение, которое я сделал в JSP, - это добавить /static/ путь к URL-адресам для CSS, JS и изображений. Например, " ${pageContext.запрос.contextPath} / static / css / screen.стиль CSS."
для пользователей Maven зависимость для " org.springframework.js.ресурс.ResourceServlet " это:
<dependency> <groupId>org.springframework.webflow</groupId> <artifactId>org.springframework.js</artifactId> <version>2.0.8.RELEASE</version> </dependency>
Я нашел способ обойти это, используя urlrewritefilter tuckey. Пожалуйста, не стесняйтесь дать лучший ответ, если у вас есть!
в интернете.XML-код:
<filter> <filter-name>UrlRewriteFilter</filter-name> <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class> </filter> <filter-mapping> <filter-name>UrlRewriteFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <servlet> <servlet-name>app</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>app</servlet-name> <url-pattern>/app/*</url-pattern> </servlet-mapping>в urlrewrite.XML-код:
<urlrewrite default-match-type="wildcard"> <rule> <from>/</from> <to>/app/</to> </rule> <rule match-type="regex"> <from>^([^\.]+)$</from> <to>/app/</to> </rule> <outbound-rule> <from>/app/**</from> <to>/</to> </outbound-rule>это означает, что любой uri с '. в нем (как стиль.css например)не будет переписан.
мой собственный опыт с этой проблемой следующим образом. Большинство связанных с Spring веб-страниц и книг, похоже, предполагают, что наиболее подходящий синтаксис заключается в следующем.
<mvc:resources mapping="/resources/**" location="/resources/" />приведенный выше синтаксис предполагает, что вы можете разместить свои статические ресурсы (CSS, JavaScript, изображения) в папке с именем "ресурсы" в корне вашего приложения, т. е. /webapp/resources/.
однако, по моему опыту (я использую Eclipse и плагин Tomcat), единственный подход, который работает, если вы размещаете папку ресурсов внутри WEB_INF (или META-INF). Итак, синтаксис, который я рекомендую, следующий.
<mvc:resources mapping="/resources/**" location="/WEB-INF/resources/" />в вашем JSP (или аналогичном) , ссылайтесь на ресурс следующим образом.
<script type="text/javascript" src="resources/my-javascript.js"> </script>излишне упоминать, что весь вопрос возник только потому, что я хотел, чтобы мой Spring dispatcher servlet (front controller) перехватывал все, все динамическое, то есть. Поэтому у меня есть следующее В моей сети.XML.
<servlet> <servlet-name>front-controller</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <load-on-startup>1</load-on-startup> <!-- spring automatically discovers /WEB-INF/<servlet-name>-servlet.xml --> </servlet> <servlet-mapping> <servlet-name>front-controller</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>наконец-то, так как я используя текущие рекомендации, у меня есть следующее В моем переднем контроллере сервлета xml (см. выше).
<mvc:annotation-driven/>и у меня есть следующее В моей фактической реализации контроллера, чтобы гарантировать, что у меня есть метод по умолчанию для обработки всех входящих запросов.
@RequestMapping("/")Я надеюсь, что это помогает.
Я получил ту же проблему и нашел ответ Джориса очень полезным. Но дополнительно мне нужно добавить
<mvc:annotation-driven />в сервлет файл config. Без этого сопоставление ресурсов не будет работать, и все обработчики перестанут работать. Надеюсь, это кому-то поможет.
URLRewrite-это своего рода" хак", Если вы хотите это назвать. Все сводится к тому, что вы заново изобретаете колесо; поскольку уже существуют решения. Еще одна вещь, которую нужно помнить, - это Http Server = Static content & App server = dynamic content (так они были разработаны). Делегируя соответствующие обязанности каждому серверу, вы максимизируете эффективность... но сейчас-это, вероятно, только проблема в критических средах производительности и что-то вроде Tomcat скорее всего, хорошо работать в обеих ролях, большую часть времени, но это все равно, что иметь в виду тем не менее.
Я решил это так:
<servlet-mapping> <servlet-name>Spring MVC Dispatcher Servlet</servlet-name> <url-pattern>/</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>*.png</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.gif</url-pattern> </servlet-mapping> <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>это работает на Tomcat и, конечно, Jboss. Однако в конце концов я решил использовать решение пружина обеспечивает (как упоминалось rozky), который является гораздо более портативным.
С весны 3, все ресурсы должны отображаться по-другому. Вы должны использовать тег, чтобы указать расположение ресурсов.
пример :
<mvc:resources mapping="/resources/**" location="/resources/" />таким образом, вы направляете сервлет диспетчера для поиска статического содержимого в ресурсы каталога.
мой способ решения этой проблемы-поместить все ваши действия с определенным префиксом, таким как" web "или" service", и настроить, что все url-адреса с этим префиксом будут перехвачены DispatcherServlet.
Я просто добавляю три правила перед весенним правилом по умолчанию ( / * * ) в urlrewritefilter tuckey (urlrewrite.xml) для решения проблемы
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 3.0//EN" "http://tuckey.org/res/dtds/urlrewrite3.0.dtd"> <urlrewrite default-match-type="wildcard"> <rule> <from>/</from> <to>/app/welcome</to> </rule> <rule> <from>/scripts/**</from> <to>/scripts/</to> </rule> <rule> <from>/styles/**</from> <to>/styles/</to> </rule> <rule> <from>/images/**</from> <to>/images/</to> </rule> <rule> <from>/**</from> <to>/app/</to> </rule> <outbound-rule> <from>/app/**</from> <to>/</to> </outbound-rule> </urlrewrite>
Я знаю, что есть несколько конфигураций для использования статического содержимого, но мое решение заключается в том, что я просто создаю папку массового веб-приложения в вашем tomcat. Это "массовое веб-приложение" обслуживает только все статическое содержимое без обслуживания приложений. Это безболезненное и простое решение для подачи статического содержимого в ваш фактический spring webapp.
например, я использую две папки webapp на моем tomcat.
- springapp: он работает только весной веб приложение без статического содержимого, такого как imgs, js или css. (выделенный для весенних приложений.)
- ресурсы: он обслуживает только статическое содержимое без JSP, сервлета или любого веб-приложения java. (выделено для статического содержимого)
Если я хочу использовать javascript, я просто добавляю URI для моего файла javascript.
EX> / resources / path/to/js / myjavascript.js
для статических изображений, я используя тот же метод.
EX> / resources / path/to/img / myimg.jpg
наконец, я поставил"защита-ограничение " на моем tomcat, чтобы заблокировать доступ к фактическому каталогу. Я поставил" nobody " user-roll на ограничение, так что страница генерирует "403 forbidden error", когда люди пытались получить доступ к пути статического содержимого.
до сих пор она работает очень хорошо для меня. Я также заметил, что многие популярные сайты, такие как Amazon, Twitter и, и Facebook они используют разные URI для обслуживания статического контента. Чтобы узнать это, просто щелкните правой кнопкой мыши на любом статическом содержимом и проверьте их URI.
я использовал оба способа, которые основаны на urlrewrite и аннотации в spring mvc 3.0.x и обнаружил, что подход, основанный на аннотации, наиболее подходит, то есть
<annotation-driven /> <resources mapping="/resources/**" location="/resources/" />в случае urlrewrite, должны определить много правил и некоторое время также получить класс не найден исключение для UrlRewriteFilter, как уже предусмотрено зависимость для него. Я обнаружил, что это происходит из-за наличия транзитивной зависимости, поэтому снова один шаг будет увеличен и должен исключить это зависимость от пом.xml с помощью
<exclusion></exclusion> tags.Так что аннотации на основе подхода будет хорошая сделка.
Это сделало реальную работу в моем случае
в интернете.XML-код:
... <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>/images/*</url-pattern> <url-pattern>/css/*</url-pattern> <url-pattern>/javascripts/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>spring-mvc-dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>...
после встречи и прохождения того же процесса принятия решений, описанного здесь, я решил пойти с предложением ResourceServlet, которое работает довольно хорошо.
обратите внимание, что вы получите дополнительную информацию о том, как использовать webflow в процессе сборки maven здесь: http://static.springsource.org/spring-webflow/docs/2.0.x/reference/html/ch01s05.html
Если вы используете стандартный центральный репозиторий Maven является артефакт (в противоположность выше referred springsource bundle):
<dependency> <groupId>org.springframework.webflow</groupId> <artifactId>spring-js</artifactId> <version>2.0.9.RELEASE</version> </dependency>
Это может быть достигнуто по крайней мере тремя способами.
решений:
- выставить html в виде файла ресурсов
- поручите JspServlet также обрабатывать *.запросы HTML-код
- написать свой собственный сервлет (или передать другому существующему сервлету запросы на *.формат HTML.)
для полных примеров кода, как этого достичь, пожалуйста, ответьте на мой ответ в другом посте:как сопоставить запросы в HTML-файл весной MVC?
<?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(); }
для конфигурации spring на основе java вы можете использовать следующее
С помощью ResourceHandlerRegistry который хранит регистрации обработчиков ресурсов для обслуживания статических ресурсов.
Подробнее @ WebMvcConfigurerAdapter который определяет методы обратного вызова для настройки конфигурации на основе Java для Spring MVC, включенной через @EnableWebMvc.
@EnableWebMvc @Configurable @ComponentScan("package.to.scan") public class WebConfigurer extends WebMvcConfigurerAdapter { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/static_resource_path/*.jpg").addResourceLocations("server_destination_path"); }
Comments