Можно ли настроить SpringMVC для обработки всех запросов, но исключить каталоги статического содержимого?
Если я перечислил мое приложение spring для обработки всех входящих запросов ('/*'), тогда запросы на статический контент возвращают 404. Например, запрос "myhost.com/css/global.css" вернет 404, хотя ресурс существует как spring перехватывает запрос.
Альтернативой является сопоставление SpringMVC с подкаталогом (например, '/home/'), но в этом случае вы должны передать этот каталог во все ссылки в приложении. Есть ли способ сопоставить SpringMVC с '/' и исключить набор каталогов из обработки?
Моя текущая конфигурация web.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>
Возможно ли это?
Ответы
Ответ 1
Если вы хотите сделать это только с помощью Spring, это возможно, но немного беспорядочно:
- Вам нужно либо использовать SimpleUrlHandlerMapping, для которого вы можете явно указать шаблоны URL-адресов, которые должны отображаться на контроллерах или расширять его для поддержки "игнорировать" URL-адреса, такие как "css/**".
- Вам нужно будет написать свою собственную реализацию HttpRequestHandler, которая в основном будет состоять из "getServletContext(). getRequestDsipatcher(). include ( )", чтобы вернуть запрошенный ресурс как есть.
- Вам нужно будет зарегистрировать этот обработчик как defaultHandler для вышеуказанного SimpleUrlHandlerMapping.
Как только все это будет сделано, все запросы, которые не могут быть сопоставлены с вашими контроллерами, будут перенаправлены на ваш HttpRequestHandler
и будут обслуживаться как "как есть".
Ответ 2
ПРИМЕЧАНИЕ. Этот ответ относится только к Spring 3.0.4+ ТОЛЬКО
(Кстати, этот вопрос также обсуждался здесь: Spring, обслуживающий статический контент с помощью mvc: resources, invalid xsd)
Просмотрите проект Spring mvc-showcase в Spring репозиторий выборок subversion. Он показывает, что именно вы хотите сделать, а именно, что вы можете очертить статические ресурсы, которые не будут обрабатываться с помощью 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/" />
Ответ 3
Я решил использовать статический контент через сервлет "по умолчанию", который просто обслуживает контент для клиента. Поэтому мой web.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 -->
Надеюсь, что это поможет.
Ответ 4
Самый простой способ для меня (при использовании достаточно поздней версии Spring) -
<mvc:resources mapping="/**/*.js" location="/"/>
<mvc:resources mapping="/**/*.css" location="/"/>
...
Ответ 5
Один из способов сделать это будет с фильтрами. Вам нужно написать немного пользовательского кода, но это не так. Вот пример, если вы не хотите передавать файлы *.css или *.js на ваш сервлет Spring:
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;
}
}
Я не тестировал это, но думаю, что это сработает.
РЕДАКТИРОВАТЬ. В спецификации сервлета нет каких-либо исключающих функциональных возможностей. Я не думаю, что есть хороший способ сделать это в Spring, но он по сути достигает того же самого в вашем сообщении.
РЕДАКТИРОВАТЬ 2. Если вы хотите легко изменить то, что фильтруется, вы можете просто использовать Spring для ввода чего-либо в фильтр во время выполнения.
EDIT 3: я понял, что если вы перейдете непосредственно к файлу, он снова сделает фильтр, и вы попадете в бесконечный цикл. Возможно, есть другой способ сделать это с помощью фильтров, но я честно не уверен, что это такое.
Ответ 6
Что вы используете для обслуживания своих статических изображений?
Если это Apache, вы можете настроить Apache, чтобы не передавать запросы css/js на ваш сервер приложений.
Если вы используете Tomcat, вы добавили бы что-то подобное в свой httpd.conf:
JkUnMount /*.css webapp
Где "webapp" - это запись из ваших рабочих .properties.
Извините, я не могу дать вам чистое решение Spring, но так я это делаю.
Ответ 7
У меня такая же проблема, и вот как я ее решил:
В файл web.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 bean был добавлен следующий файл (например, applicationContext.xml, файл, который настроен в web.xml как contextConfigLocation.):
<mvc:annotation-driven />
<mvc:default-servlet-handler />
Ответ 8
У вас есть постоянное расширение для запросов, которые вы хотите обработать диспетчером Spring (я считаю, что в большинстве примеров Spring используется *.htm)? В этом случае вы можете сопоставить расширения, которые вы хотите обработать, которые будут обходить ваши файлы css и js.
В противном случае я согласен с Nalandial, подход Filter, вероятно, лучше всего работает на этом этапе.
Ответ 9
Обычно крупные веб-сайты предпочитают использовать другой сервер только для обработки статического контента.
Запросы статического содержимого отправляются на один сервер, а динамический - на другой (с этим spring).
Во многих случаях сервер Nginx (http://nginx.com/), недавний и очень быстрый сервер.
Но это не так уж и сложно. Множество конфигураций.
Ответ 10
Я использую виртуальный 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);
}
}
}
}
Ответ 11
Если вы используете Spring 3.0.4 и выше, вы должны использовать решение, предоставленное atrain
В противном случае вы можете сделать это просто:
возможно, у вас есть следующая статическая структура каталогов, которую вы хотите обслуживать:
WebContent
|
WEB-INF
|
public
|
css
|
js
|
img
Eclipse
Динамические веб-проекты по умолчанию генерируют следующую структуру: WebContent/WEB-INF
. Переместите папку public
из каталога WEB-INF в каталог WebContent
.
На стороне клиента
ссылайтесь на свои статические файлы следующим образом:
<link rel="stylesheet" type="text/css" href="public/css/mystyles.css">
Вот ссылка .
Ответ 12
Очистить, чтобы использовать UrlRewriteFilter для перенаправления запроса на ваш сервлет, вот пример urlrewrite.xml
<urlrewrite>
<rule>
<from>^/img/(.*)$</from>
<to>/img/$1</to>
</rule>
<rule>
<from>^/js/(.*)$</from>
<to>/js/$1</to>
</rule>
<rule>
<from>^/css/(.*)$</from>
<to>/css/$1</to>
</rule>
<rule>
<from>^/(.*)$</from>
<to>/app/$1</to>
</rule>
<outbound-rule>
<from>/app/(.*)$</from>
<to>/$1</to>
</outbound-rule>
</urlrewrite>
ПРИМЕЧАНИЯ:
- Важно, чтобы последний
<rule>
был внизу, поэтому img, js, css будет обнаружен первым.
-
<outbound-rule>
является необязательным и состоит только в том, чтобы сделать существующий
<c:url value="/app/some" />
render /some
вместо /app/some
Ответ 13
В моем случае все было в порядке. Но у меня проблема в контроллере
Это была моя проблема @RequestMapping (метод = RequestMethod.GET)
y измените для этого:
@RequestMapping(value = "/usuario", method = RequestMethod.GET)
и он работает
найдите контроллер с плохим значением @RequestMappgin и измените его.