组态
Tomcat 7.0.47上的Servlet 3.0
春季3.1
题
我有一个特殊情况,我需要两个DispatcherServlet:一个用于处理资源请求,另一个用于处理正常的@RequestMapping类型请求.出于某种原因,我在日志中得到这个:
No mapping found for HTTP request with URI [/my-app/images/someimage.png] in DispatcherServlet with name ‘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>
如你所见,我没有< mvc:resources>对于CSS文件,因为该映射是使用@Controller动态构建LESS文件完成的. < context:component-scan base-package =“lesscss”/>照顾那一点,它似乎工作.
我以前有那些< mvc:resources>我的springmvc-servlet.xml文件中的标签,但我删除了它们.我还能错过什么?
UPDATE
我尝试将我的web.xml文件更改为使用* .ext url-patterns而不是/ dir / * kind,并且它有效.不过,我宁愿不必列出所有扩展,所以我仍然希望更好地解决这个问题.
UPDATE
我更改了< mvc:resources mapping =“/ images / **”location =“/ images /”/>到< mvc:resources mapping =“/ **”location =“/ images /”/>并删除了一个js文件,图像开始工作.在Spring中映射事物时,似乎忽略了*之前的servlet-mapping url-pattern.有没有解决的办法?
解释为什么我“需要”两个Servlet
我想我会添加这个只是为了帮助那些之前没有意识到这一点的人(比如我),并给某人一个机会,如果有的话,想出更好的解决方案.
使用< mvc:resources>时tag,创建的处理程序是常规DispatcherServlet请求处理的一部分.这意味着,如果您没有明确说明未由< mvc:resources>处理的所有资源路径.使用< mvc:mapping> (我仍在使用Spring 3.1并且不能使用< mvc:exclude-mapping>),对图像,JavaScript文件和样式表的每个请求都会运行您在< mvc:interceptors>中列出的所有HandlerInterceptors.我的应用程序中有很多拦截器,由于应用程序的结构和性质,列出所有路径都非常容易出错.不仅仅是性能损失,所有这些HandlerInterceptors的执行实际上将破坏手写的POST-redirect-GET组件.
另一种方法是检查每个HandlerInterceptor方法中正在使用哪个处理程序,但这几乎不是DRY,也容易出错,而且我不能对像OpenSessionInViewInterceptor这样的类进行这种调整而不扩展它们.我提出的避免所有这些混乱的解决方案是使用专门用于静态(ish)资源的单独servlet.
最佳答案 简单的解决方案
首先,我觉得我必须写明显(如果不是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;
}
}