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

Можно ли настроить 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>

Возможно ли это?

4b9b3361

Ответ 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 и измените его.