gpt4 book ai didi

spring - 如何为资源使用第二个 DispatcherServlet

转载 作者:行者123 更新时间:2023-11-28 21:49:53 30 4
gpt4 key购买 nike

配置

Tomcat 7.0.47 上的 Servlet 3.0
Spring 3.1

问题

我有一个比较特殊的情况,我需要两个 DispatcherServlets : 一个处理资源请求,一个处理正常 @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文件,但我删除了它们。我还能缺少什么?

更新

我尝试更改我的 web.xml要使用的文件 *.ext url-patterns 而不是 /dir/*亲切,而且奏效了。不过,我宁愿不必列出所有扩展,所以我仍然希望有更好的解决方案来解决这个问题。

更新

我改变了<mvc:resources mapping="/images/**" location="/images/"/><mvc:resources mapping="/**" location="/images/"/>并删除了 js 的那个文件,图像开始工作。似乎servlet-mapping url-pattern* 之前在 Spring 中映射事物时被忽略。有办法解决这个问题吗?

解释为什么我“需要”两个 Servlet

我想我会添加这个只是为了帮助以前没有意识到这一点的其他人(比如我),并让他们有机会提出更好的解决方案(如果有的话)。

使用 <mvc:resources> 时标记,创建的处理程序是常规 DispatcherServlet 的一部分请求处理。这意味着,如果您没有明确说明 <mvc:resources> 处理的所有资源路径使用 <mvc:mapping> (我仍在使用 Spring 3.1,无法使用 <mvc:exclude-mapping> ),每个对图像、JavaScript 文件和样式表的请求都会运行所有 HandlerInterceptor您是否已在 <mvc:interceptors> 中列出.我的应用程序中有很多拦截器,由于应用程序的结构和性质,列出所有路径非常容易出错。不仅仅是性能下降,执行所有这些HandlerInterceptor s 实际上会中断 POST-redirect-GET手写的组件。

另一种方法是检查每个 HandlerInterceptor 中正在使用哪个处理程序方法,但这几乎不是 DRY,也容易出错,我不能对 OpenSessionInViewInterceptor 这样的类进行调整不扩展它们。为了避免所有这些困惑,我提出的解决方案是使用一个单独的 servlet,专门用于静态(ish)资源。

最佳答案

简单的解决方案

首先,我觉得我必须写出显而易见的东西(如果不是为了 OP,那么对于将来可能会读到这个答案的其他人):

  • 简单的解决方案是只使用单个 DispatcherServlet .如果没有非常充分的理由,请不要使用两个 servlet。

  • 或者,您可以将资源映射到 /resources/*小路。将所有资源置于明确定义的路径下是一种常见(最​​佳?)做法。

复杂的解决方案

现在<mvc:resources> ResourcesBeanDefinitionParser 处理.该组件注册了两个关键组件:SimpleUrlHandlerMappingResourceHttpRequestHandler .

第一个组件负责将请求映射到处理程序。如果你不希望这个组件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;
}

}

关于spring - 如何为资源使用第二个 DispatcherServlet,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26873563/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com