Spring Boot 访问静态资源 CSS JS 找不到 报404

一般不怎么写前端页面,今天写使用freemarker作为模板文件,使用Spring Boot时,遇到了css、js等静态文件访问不到的问题,查看浏览器控制台发现报404错误,百度了一下,网上很多使用Spring Boot访问静态资源,访问不到,报404的例子,觉得很多例子写的不够详细,这里写一篇博客作为记录,首先需要声明的是不同版本的Spring Boot可能有不同的处理方案,本篇博客的Spring Boot版本为2.0.x的的版本,我们还是从项目说起,所有的静态资源放在classpath:/static/目录下,freemarker资源放在classpath:/templates目录下,然后启动Spring Boot应用程序,访问网页时,报css和js找不到。在Spring Boot中静态资源的访问涉及到ResourceHandler和ResourceLocations。我们查看源码可以看到它们的默认值:

@ConfigurationProperties(prefix = "spring.resources", ignoreUnknownFields = false)
public class ResourceProperties {
    private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/" };
    private String[] staticLocations = CLASSPATH_RESOURCE_LOCATIONS;
}
@ConfigurationProperties(prefix = "spring.mvc")
public class WebMvcProperties {
    private String staticPathPattern = "/**";
}

如下为当时HTML页面配置的css文件,下面的两种配置访问都报404错误,此刻就觉得有点说不通了,首先我们的静态资源放置的是SpringBoot默认的路径,静态资源解析模式也是默认的路径。但是不管怎么访问就是404错误。

<link href="layui/css/layui.css" rel="stylesheet" >
<link href="static/layui/css/layui.css" rel="stylesheet" >

无奈,我只好手动的配置静态资源的路径和匹配模式,该版本是通过继承WebMvcConfigurationSupport,并且覆盖addResourceHandlers方法,代码如下所示:

@Configuration
public class MvcConfig extends WebMvcConfigurationSupport {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
        super.addResourceHandlers(registry);
    }
}

此时,我们将静态资源配置为<link href="layui/css/layui.css" rel="stylesheet" >,好了,静态资源可以访问了,但是如果我们使用下面的代码,静态资源就又访问不到了,代码如下所示:

@Configuration
public class MvcConfig extends WebMvcConfigurationSupport {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
        super.addResourceHandlers(registry);
    }
}

如果使用上面的代码,则需要使用下面引入方式,也就是需要添加static,<link href="static/layui/css/layui.css" rel="stylesheet">。看到这里我们可能就了解了ResourceHandler和ResourceLocations的作用了,ResourceLocations配置的是静态资源的位置,如果访问的是静态资源,将会从该位置寻找资源。ResourceHandler表示是静态资源的匹配模式,也就是说访问的是/static/**路径的资源时静态资源。这里有点懵逼的是,Spring Boot配置的默认的匹配模式为/**,为什么还需要我们重新覆盖方法配置/**匹配模式。如有些问题实在找不到答案,阅读源码是最好的选择。Spring Boot的Spring MVC的自动配置在org.springframework.boot.autoconfigure.web.servlet包下的WebMvcAutoConfiguration类,我们先看其定义:

@Configuration
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class,
		ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {
}

上面的定义中有一个注解:@ConditionalOnMissingBean(WebMvcConfigurationSupport.class),表示当Spring IOC容器中存在WebMvcConfigurationSupport实例时,不会在实例化WebMvcAutoConfiguration。下面我们在分析这两个类分别做了哪些内容。

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    //获取匹配模式 默认为/**
    String staticPathPattern = this.mvcProperties.getStaticPathPattern();
    if (!registry.hasMappingForPattern(staticPathPattern)) {
       //配置静态资源的匹配模式,配置静态资源的位置
customizeResourceHandlerRegistration(registry.addResourceHandler(staticPathPattern)
.addResourceLocations(getResourceLocations(this.resourceProperties.getStaticLocations())
.setCachePeriod(getSeconds(cachePeriod))
.setCacheControl(cacheControl));
    }
}

然后查看源码发现有一个类DelegatingWebMvcConfiguration继承了WebMvcConfigurationSupport,代码如下所示:

@Configuration
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
}

我们将自己写的MvcConfig注释掉,然后写一个测试类,判断DelegatingWebMvcConfiguration是否在SpringIOC中,代码如下:

@Component
public class Test implements CommandLineRunner {
    @Autowired
    private ApplicationContext context;
    @Override
    public void run(String... args) throws Exception {
        System.out.println(context.getBean(DelegatingWebMvcConfiguration.class));
    }
}

org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration$$EnhancerBySpringCGLIB$$af9294ec@7a9c84a5,打印的结果如上,由此可见容器使用的还是WebMvcAutoConfiguration实例,这就更尴尬了,最后没办法,使用IDEA maven clean一下,可以了居然,黑人问号有没有,这里说的也是一种解决方案,Spring Boot访问不到静态资源时,而配置又没有问题时,不妨maven clean一下 或者换成eclipse,要不然就重启编辑器,重新导入项目等等。反正是很头疼的问题。这里建议使用Spring Boot官方给出的资源的放置的方案,即模板文件放在classpath:/templates下静态资源放在”classpath:/META-INF/resources/"或者 "classpath:/resources/"、 "classpath:/static/",、"classpath:/public/“下。而静态资源的模式匹配可以使用默认的/**,也可以自定义模式,这里建议使用/**,我们无需再自定义了WebMvcConfigurationSupport。最后截图Spring Boot官方推荐的资源的放置的目录:

猜你喜欢

转载自blog.csdn.net/wk19920726/article/details/108883768