Webjars 定位器不适用于基于 XML 的 Spring MVC 4.2.x 配置?

Webjars-locator doesn't work with XML based Spring MVC 4.2.x configuration?

我有一个 Spring MVC 4.2.x 项目。我正在通过基于 XML 的配置文件对其进行配置:

<servlet>
    <servlet-name>foo</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/context.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

context.xml文件中我配置了资源和annotation-driven模式:

<mvc:resources mapping="/webjars/**" location="/webjars/"/>
<mvc:annotation-driven/>

除一件事外一切正常:webjars-locator - Webjars 定位器根本不起作用


我已经开始查看 Spring MVC 源代码以了解出了什么问题,并发现 webjars-locator 通过 WebJarsResourceResolver class 工作,对象是在 ResourceChainRegistration.getResourceResolvers() class 方法中添加。

完整序列如下所示:

WebMvcConfigurationSupport.resourceHandlerMapping() >> ResourceHandlerRegistration.getHandlerMapping() >> ResourceHandlerRegistration.getRequestHandler() >> ResourceChainRegistration.getResourceResolvers(),其中添加为:

if (isWebJarsAssetLocatorPresent) {
    result.add(new WebJarsResourceResolver());
}

问题是,在上述基于 XML 的配置的情况下,不会调用此序列,也不会使用 WebMvcConfigurationSupport class。

此外,如果我添加

@EnableWebMvc
@Configuration
public class WebConfig {
}

进入项目,WebMvcConfigurationSupport 显然有效,但在 ResourceHandlerRegistration.getHandlerMapping():

protected AbstractHandlerMapping getHandlerMapping() {
    if (registrations.isEmpty()) {
        return null;
    }
...
}

registrations 为空!


毕竟,如何强制使Spring将WebJarsResourceResolver添加到解析器链中的唯一方法是:

1) 从 context.xml

中删除 <mvc:resources mapping="/webjars/**" location="/webjars/"/>

2) 将addResourceHandlers添加到WebConfig:

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry
            .addResourceHandler("/webjars/**")
            .addResourceLocations("/webjars/")
            .setCachePeriod(3600)
            .resourceChain(true)  // !!! very important
    ;
}

我的问题是:我做错了什么?为什么 XML 基础配置不会导致 WebJarsResourceResolver 被注册?

假设上下文根路径是/ctx。根据您的配置,/webjars/RESOURCE 的资源路径 实际上 映射到 /ctx/webjars/RESOURCE;与应该映射到 /webjars/RESOURCE 的普遍期望相反。

基于 Spring 4.2.x documentation and an example similar issue,您需要将 /webjars/** 映射到默认调度程序 servlet 为:

This allows for mapping the DispatcherServlet to "/" (thus overriding the mapping of the container’s default Servlet), while still allowing static resource requests to be handled by the container’s default Servlet. It configures a DefaultServletHttpRequestHandler with a URL mapping of "/**" and the lowest priority relative to other URL mappings.

这意味着添加以下内容应该可以解决问题:

<mvc:resources mapping="/webjars/**" location="/webjars/">
    <mvc:resource-chain>
        <mvc:resource-cache />
    </mvc:resource-chain>
</mvc:resources>
<mvc:annotation-driven />
<mvc:default-servlet-handler />

另一个注释 the example petclinic 使用 location="classpath:/META-INF/resources/webjars/" 用于我不确定与此处相关的 webjars。

希望对您有所帮助。


@Andremoniy 添加:

对于 Spring 4 它的标记略有不同:

<mvc:resources mapping="/webjars/**" location="/webjars/">
    <mvc:resource-chain resource-cache="true"/>
</mvc:resources>

回答您剩下的问题

它 is/was 2016 年 5 月 3 日报告的一个问题:

https://github.com/webjars/webjars/issues/1395

如本页所述,此问题还提到 Spring MVC 需要 resourceChain() 方法。我今天创建了一个 PR 来解决这个问题:

https://github.com/webjars/webjars/pull/1946

仅供参考:我试图让版本不可知 url 按照文档中描述的方式工作,但没有成功。在此过程中,我还发现了以下问题,其中提到“必须为与版本无关的 WebJars 调用 resourceChain() 方法”:

https://github.com/spring-projects/spring-framework/issues/25410