Можно ли настроить SpringMVC для обработки всех запросов, но исключить каталоги статического содержимого?
Если я сопоставляю свое приложение spring для обработки всех входящих запросов ( '/ * ' ), то запросы на статическое содержимое возвращают 404's. например, запрос на "myhost.com/css/global.css" вернул бы 404, хотя ресурс существует, поскольку Spring перехватывает запрос.
альтернативой является сопоставление SpringMVC с подкаталогом (например ' / home/'), но в этом случае вы должны передать этот каталог во всех ссылках внутри приложения. Есть ли способ, чтобы карту к инфраструктуре springmvc - / и исключить набор каталогов из обработки?
мой нынешний веб.конфигурация xml:
<servlet>
<servlet-name>springApp</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springApp</servlet-name>
<url-pattern>/home/*</url-pattern>
</servlet-mapping>
В идеале я хотел бы, чтобы отображение было чем-то вроде следующего:
<servlet-mapping>
<servlet-name>springApp</servlet-name>
<url-pattern>/*</url-pattern>
<exclude>/css/*,/js/*</exclude>
</servlet-mapping>
возможно ли такое?
13 ответов:
Если вы хотите сделать это только с весной, это возможно, но немного грязно:
- вы должны использовать SimpleUrlHandlerMapping для которого вы можете явно указать шаблоны URL, которые должны быть сопоставлены с контроллерами или расширить его для поддержки "игнорировать" URL-адреса, такие как "css/**".
- вам нужно будет написать свой собственный HttpRequestHandler реализация, которая в основном будет состоять из "getServletContext().getRequestDsipatcher ().include () " вызов для возврата запрошенного ресурса как есть.
- вы должны будете зарегистрировать этот обработчик как defaultHandler для вышеупомянутого SimpleUrlHandlerMapping.
Как только все это будет сделано, все запросы, которые не могут быть сопоставлены с вашими контроллерами, будут перенаправлены на ваш
HttpRequestHandler
и подаются "как есть".
Примечание: этот ответ относится только к Spring 3.0.4+
(кстати, этот вопрос также рассматривался здесь: пружина обслуживания статического контента с MVC:ресурсы, поврежденных xsd-схемы)
Проверьте проект Spring mvc-showcase весной Subversion samples repository. Он показывает именно то, что вы хотите сделать, а именно, что вы можете определить статические ресурсы, которые не будут обрабатываться DisapatcherServlet. См. файл
/mvc-showcase/src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml
. Вот фрагмент того, как я обрабатываю эти исключения, где JS, CSS и изображения находятся в корневом контексте приложения (с пространством имен MVC, сопоставленным сmvc
:<!-- resources exclusions from servlet mapping --> <mvc:resources mapping="/css/**" location="/css/" /> <mvc:resources mapping="/images/**" location="/images/" /> <mvc:resources mapping="/js/**" location="/js/" />
Я решил, обслуживая статический контент через сервлет "по умолчанию", который просто обслуживает контент клиенту. Так что моя паутина.XML выглядит так:
<servlet> <servlet-name>MyApp</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>MyApp</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!-- The 'dynamic' content --> <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> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.jpg</url-pattern> </servlet-mapping> <!-- The 'static' content -->
надеюсь, что это помогает.
самый простой способ для меня (если использовать достаточно позднюю версию Spring) - это
<mvc:resources mapping="/**/*.js" location="/"/> <mvc:resources mapping="/**/*.css" location="/"/> ...
один из способов сделать это будет с фильтрами. Вам придется написать немного пользовательского кода, но это не плохо. Вот пример, если вы не хотите проходить *.css или *.JS файлы для вашего весеннего сервлета:
web.XML-код:
<filter-mapping> <filter-name>fileTypeFilter</filter-name> <filter-class>foo.FileTypeFilter</filter-class> <url-pattern>/*</url-pattern> </filter-mapping>
Java-класс:
public class FileTypeFilter implements Filter { public void init(FilterConfig conf) { // init logic here } public void destroy() { // release resources here } public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws ServletException, IOException { if(shouldExclude(req)) { chain.doFilter(req, res); //some logic so the request doesnt go to the servlet //maybe you could just forward //the request directly to the file getting accessed. not sure if that would work } //file should be passed to the servlet; you can do some logic here //if you want } private boolean shouldExclude(ServletRequest req) { if(req instanceof HttpServletRequest) { HttpServletRequest hreq = (HttpServletRequest) req; return (hreq.getRequestURI().endsWith(".css") || hreq.getRequestURI().endsWith(".js")); } return false; } }
Я не проверял это, но я думаю, что это будет работать.
EDIT: в спецификации сервлета нет никаких функций исключения. Я не думаю, что есть хороший способ сделать это в течение весны, но он по существу достигает того же самого в вашем посте.
EDIT 2: если вы хотите легко изменить то, что фильтруется, вы можете просто использовать Spring, чтобы ввести что-то в фильтр во время выполнения.
редактировать 3: я только что понял, что если вы перейдете непосредственно к файлу, он снова сделает фильтр, и вы попадете в бесконечный цикл. Может быть, есть другой способ сделать это с фильтрами, но я честно не уверен, что это.
что вы используете для обслуживания статических изображений? Если это Apache, то вы можете настроить Apache, чтобы не передавать запросы css/js на сервер приложений.
Если вы используете Tomcat, вы бы поместили что-то вроде этого в свой httpd.conf:
JkUnMount /*.css webapp
где 'webapp' - это запись от ваших работников.свойства.
Извините, я не могу дать вам чистый весенний раствор, но вот как я это делаю.
Я получил ту же проблему, и вот как я ее решил:
в Сеть было добавлено следующее.xml-файл:
<servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.js</url-pattern> <url-pattern>*.css</url-pattern> <url-pattern>*.ico</url-pattern> <url-pattern>*.png</url-pattern> <url-pattern>*.jpg</url-pattern> <url-pattern>*.htc</url-pattern> <url-pattern>*.gif</url-pattern> <url-pattern>*.html</url-pattern> <url-pattern>*.htm</url-pattern> </servlet-mapping>
в файл определения компонента сервлета spring3 MVC (например, applicationContext.xml, файл, настроенный в web.xml как contextConfigLocation.):
<mvc:annotation-driven /> <mvc:default-servlet-handler />
есть ли у вас последовательное расширение(ы) для запросов, которые вы хотите обработать Spring dispatcher (я считаю, что большинство примеров Spring используют a *.htm)? В этом случае вы можете сопоставить расширения, которые вы хотите обработать, которые обойдут ваши файлы css и js.
в противном случае я бы согласился с Nalandial, подход фильтра, вероятно, лучшая работа вокруг на данный момент.
Как правило, крупные сайты предпочитают использовать другой сервер только для обработки статического контента. Запросы статического контента идут на один сервер, а динамического - на другой (в данном случае с spring).
во многих случаях, сервер Nginx (http://nginx.com/), недавний и очень быстрый сервер.
но это не тривиально сделать. Много конфигураций.
Я использую виртуальный URL-адрес для получения нужного мне ресурса. Обычно я использую Spring MVC, поэтому я не мог иметь javascripts и css в папке /WEB-INF/views. Я придумал этот пользовательский сервлет, чтобы только разрешить доступ .js & .файлы css в папке/WEB-INF / views. В вашем случае, если вы переместите папку /css и папку /js в родительскую папку, такую как /resource, тогда мое решение будет применимо к вам.
вы можете изменить строку url = "YOUR_RESOURCE_FOLDER"
Так например, виртуальный путь может быть чем-то вродеhttp://www.mysite.com/resources/path/path/app.js
это будет отображаться на мой / WEB-INF / views/path/path / app.js
web.xml
<servlet> <servlet-name>ResourceDispatcherServlet</servlet-name> <servlet-class>mywebapp.web.ResourceDispatcherServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>ResourceDispatcherServlet</servlet-name> <url-pattern>/resource/*</url-pattern> </servlet-mapping>
сервлет
public class ResourceDispatcherServlet extends HttpServlet { public void init() throws ServletException { } public void doGet(HttpServletRequest req, HttpServletResponse rsp) throws ServletException, IOException { String servletPath = req.getServletPath(); // /resource String pathInfo = req.getPathInfo(); // /path/path/app.js String url = "/WEB-INF/views" + pathInfo; String lastPath = StringUtil.substringAfterLast(pathInfo, "/"); String extension = StringUtil.substringAfterLast(lastPath, "."); try { RequestDispatcher dispatcher = null; if (!StringUtil.isEmpty(extension) && ("js".equals(extension) || "css".equals(extension))) { dispatcher = req.getRequestDispatcher(url); } if (dispatcher != null) { dispatcher.include(req, rsp); } else { rsp.sendError(404); } } catch (Exception e) { if (!rsp.isCommitted()) { rsp.sendError(500); } } } }
если вы используете Spring 3.0.4 и выше, вы должны использовать решение atrain
в противном случае, вы можете сделать это простой всего:
возможно, у вас есть следующая статическая структура каталогов, которую вы хотите обслуживать:
WebContent | WEB-INF | public | css | js | img
Eclipse
динамические веб-проекты по умолчанию генерируют следующую структуру:WebContent/WEB-INF
. Двигайpublic
папка из вашего каталога WEB-INF в
это чище использовать UrlRewriteFilter чтобы перенаправить запрос на ваш сервлет, вот пример
urlrewrite.xml
<urlrewrite> <rule> <from>^/img/(.*)$</from> <to>/img/</to> </rule> <rule> <from>^/js/(.*)$</from> <to>/js/</to> </rule> <rule> <from>^/css/(.*)$</from> <to>/css/</to> </rule> <rule> <from>^/(.*)$</from> <to>/app/</to> </rule> <outbound-rule> <from>/app/(.*)$</from> <to>/</to> </outbound-rule> </urlrewrite>
Примечания:
- важно последнее
<rule>
находится в нижней части, поэтому img, js, css будут пойманы первыми- The
<outbound-rule>
- это необязательным и просто сделать существующий<c:url value="/app/some" />
оказать/some
вместо/app/some
в моем случае все было ок. Но у меня есть проблема в контроллере
Это была моя проблема @RequestMapping (method = RequestMethod.Получите)
y изменение для этого:
@RequestMapping(value = "/usuario", method = RequestMethod.GET)
и работает
ищите контроллер, который имеет плохой @RequestMappgin и изменения.