Spring Boot access static resource CSS JS can not find 404

I usually don’t write front-end pages very much. Today I wrote freemarker as a template file. When using Spring Boot, I encountered the problem of not being able to access static files such as css and js. I checked the browser console and found a 404 error. Baidu took a look. There are many online I use Spring Boot to access static resources, but I can’t access it. The example of 404 is reported. I feel that many examples are not detailed enough. Write a blog here as a record. First of all, you need to declare that different versions of Spring Boot may have different solutions. The Spring Boot version of this blog is 2.0.x. Let’s start with the project. All static resources are placed in the classpath:/static/ directory, and the freemarker resources are placed in the classpath:/templates directory, and then Spring Boot is started. The application, when accessing the web page, reports that css and js cannot be found The access to static resources in Spring Boot involves ResourceHandler and ResourceLocations. We can see their default values ​​by viewing the source code:

@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 = "/**";
}

The following is the css file configured on the HTML page at the time. The following two configuration accesses report a 404 error. At this moment, I feel a little unreasonable. First of all, our static resources are placed in the default path of SpringBoot, and the static resource analysis mode is also the default path. . But no matter how you access it, it is a 404 error.

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

Frustrated, I had to manually configure the path and matching mode of static resources. This version inherits WebMvcConfigurationSupport and overrides the addResourceHandlers method. The code is as follows:

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

At this point, we will configure the static resource as <link href="layui/css/layui.css" rel="stylesheet" >, well, the static resource can be accessed, but if we use the following code, the static resource will be again Can't access, the code is as follows:

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

If you use the above code, you need to use the following introduction method, that is, you need to add static,<link href="static/layui/css/layui.css" rel="stylesheet">. Seeing this, we may understand the role of ResourceHandler and ResourceLocations. ResourceLocations configures the location of static resources. If you are accessing static resources, you will find resources from that location. ResourceHandler represents the matching mode of static resources, that is to say, static resources are accessed when resources in the /static/** path are accessed. What is a little bit confusing here is that the default matching mode of Spring Boot configuration is /**, why do we need to re-overwrite the method configuration/** matching mode. If you can't find answers to some questions, reading the source code is the best choice. Spring Boot's Spring MVC automatic configuration is in the WebMvcAutoConfiguration class under the org.springframework.boot.autoconfigure.web.servlet package. Let's look at its definition first:

@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 {
}

There is an annotation in the above definition: @ConditionalOnMissingBean(WebMvcConfigurationSupport.class), which means that when an instance of WebMvcConfigurationSupport exists in the Spring IOC container, WebMvcAutoConfiguration will not be instantiated. Below we are analyzing what these two classes have done.

@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));
    }
}

Then check the source code and find that there is a class DelegatingWebMvcConfiguration that inherits WebMvcConfigurationSupport. The code is as follows:

@Configuration
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
}

We comment out the MvcConfig we wrote, and then write a test class to determine whether DelegatingWebMvcConfiguration is in SpringIOC. The code is as follows:

@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, the printed result is as above, it can be seen that the container is still using the WebMvcAutoConfiguration instance, which is even more embarrassing. Finally, there is no way, use IDEA maven clean, it’s okay. Is there a black question mark? Here is also a solution. When Spring Boot can’t access static resources and there is no problem with the configuration, you might as well maven clean or replace it with eclipse, otherwise Just restart the editor, re-import the project, etc. Anyway, it is a headache. It is recommended to use the resource placement scheme officially given by Spring Boot, that is, template files are placed under classpath:/templates, and static resources are placed in "classpath:/META-INF/resources/" or "classpath:/resources/", " classpath:/static/",, "classpath:/public/". The pattern matching of static resources can use the default /**, or you can customize the pattern. It is recommended to use /**. We don't need to customize WebMvcConfigurationSupport. Finally, take a screenshot of the directory where the resources officially recommended by Spring Boot are placed:

Guess you like

Origin blog.csdn.net/wk19920726/article/details/108883768