Tomcat 7.0.47上的Servlet 3.0 春季3.1
我有一个特殊情况,我需要两个DispatcherServlets
:一个用于处理资源请求,一个用于处理正常的@RequestMapping
类型请求。出于某种原因,我在日志中得到了这个:
在DispatcherServlet中找不到带有URI [/my-app/images/someimage.png]的HTTP请求的映射,其名称为' resources'
这是我的web.xml
文件的样子:
<servlet>
<servlet-name>resources</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>resources</servlet-name>
<url-pattern>/css/*</url-pattern>
<url-pattern>/images/*</url-pattern>
<url-pattern>/js/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
在resources-servlet.xml
我有这个:
<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-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd"
default-autowire="byName">
<context:annotation-config />
<context:property-placeholder />
<mvc:resources mapping="/images/**" location="/images/"/>
<mvc:resources mapping="/js/**" location="/js/"/>
<context:component-scan base-package="lesscss" />
<mvc:annotation-driven />
</beans>
正如您所看到的,我对CSS文件没有<mvc:resources>
因为该映射是使用@Controller
构建LESS文件即时完成的。 <context:component-scan base-package="lesscss" />
处理这一点,似乎正在发挥作用。
我之前在<mvc:resources>
文件中有springmvc-servlet.xml
个标记,但我删除了它们。我还能错过什么?
更新
我尝试将web.xml
文件更改为使用*.ext
网址格式而非/dir/*
类型,并且有效。不过,我不必列出所有扩展名,所以我仍然希望能够更好地解决这个问题。
更新
我将<mvc:resources mapping="/images/**" location="/images/"/>
更改为<mvc:resources mapping="/**" location="/images/"/>
并删除了js
个文件,并且图片开始正常工作。在Spring中映射事物时,servlet-mapping
之前的url-pattern
*
似乎被忽略了。有办法解决这个问题吗?
我想我会添加这个只是为了帮助那些之前没有意识到这一点的人(比如我),并给某人提供一个更好的解决方案,如果有的话。
使用<mvc:resources>
标记时,创建的处理程序是常规DispatcherServlet
请求处理的一部分。这意味着,如果您没有明确说明<mvc:resources>
使用<mvc:mapping>
处理不的所有资源路径(我仍在使用Spring 3.1但无法使用<mvc:exclude-mapping>
),对图片,JavaScript文件和样式表的每个请求都会运行您在HandlerInterceptor
中列出的所有<mvc:interceptors>
。我的应用程序中有很多拦截器,由于应用程序的结构和性质,列出所有路径都非常容易出错。不仅仅是性能损失,执行所有这些HandlerInterceptor
实际上会破坏手写的POST-redirect-GET
组件。
替代方法是检查每个HandlerInterceptor
方法中使用的处理程序,但这很难干,也容易出错,而且我不能在OpenSessionInViewInterceptor
这样的类上进行此调整扩展它们。我提出的避免所有这些混乱的解决方案是使用专门用于静态(ish)资源的单独servlet。
答案 0 :(得分:2)
首先,我觉得我必须写明显(如果不是OP,那么将来可能会读到这个答案的人):
简单的解决方案就是使用单DispatcherServlet
。如果没有很强的理由,请不要使用两个servlet。
或者,您可以将资源映射到/resources/*
路径。将所有资源置于明确定义的路径下是一种常见的(最好的)做法。
现在<mvc:resources>
由ResourcesBeanDefinitionParser
处理。该组件注册了两个关键组件:SimpleUrlHandlerMapping
和ResourceHttpRequestHandler
。
第一个组件负责将请求映射到处理程序。如果您不希望此组件strip servlet mapping path,则需要设置alwaysUseFullPath flag。这可以通过自己进行<mvc:resources>
配置,也可以通过对已注册的实例进行后处理来完成。
对于使用问题中的示例进行手动配置,请设置映射和处理程序:
<context:component-scan base-package="lesscss" />
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="alwaysUseFullPath" value="true" />
</bean>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="alwaysUseFullPath" value="true"/>
</bean>
<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter" />
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="alwaysUseFullPath" value="true"/>
<property name="mappings">
<props>
<prop key="/images/**">imagesResources</prop>
<prop key="/js/**">jsResources</prop>
</props>
</property>
</bean>
<bean id="imagesResources" class="org.springframework.web.servlet.resource.ResourceHttpRequestHandler">
<property name="locations">
<list>
<value>/images/</value>
</list>
</property>
</bean>
<bean id="jsResources" class="org.springframework.web.servlet.resource.ResourceHttpRequestHandler">
<property name="locations">
<list>
<value>/js/</value>
</list>
</property>
</bean>
对于后处理方法,创建并注册bean:
public class SimpleUrlMappingConfigurer implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
return bean;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
if (bean instanceof SimpleUrlHandlerMapping) {
((SimpleUrlHandlerMapping) bean).setAlwaysUseFullPath(true);
}
return bean;
}
}