SpringBoot集成SpringMVC之静态页配置

静态资源的支持

来到springboot的官方文档中的说明中来,web开发模块在spring-boot-features中的Developing Web Applications

SpringBoot默认静态文件存放位置

来看看静态资源的支持:static content

By default, Spring Boot serves static content from a directory called /static (or /public or /resources or /META-INF/resources) in the classpath or from the root of the ServletContext

默认的是可以访问系统根路径下的这四个文件夹。而创建springboot项目的时候,默认的只有static文件夹,那么也就意味着这里可以放置静态文件:css、js、图片等等。

修改默认访问资源前缀

官方文档说默认的访问路径是/双星, 所以默认的访问路径就应该是:根路径+静态资源名称,但是官方文档中又说,我们也可以来进行修改:

// 默认的资源路径
By default, resources are mapped on /**, 
but you can tune that with the spring.mvc.static-path-pattern property. For instance, relocating all resources to /resources/** can be achieved as follows:
spring.mvc.static-path-pattern=/resources/**

也就是说当修改了静态访问路径之后,那么再次访问静态资源路径就变成:根路径+static-path-pattern+静态资源名称

问题一:静态资源路径和SpringMVC中的DispatcherServlet中的动态资源哪个优先?

首先在官方文档中也有说明:

It uses the ResourceHttpRequestHandler from Spring MVC so that you can modify that behavior by adding your own WebMvcConfigurer and overriding the addResourceHandlers method.

也就是说,官方提供了ResourceHttpRequestHandler静态资源处理器来对静态资源提供了对应的处理。

我们在进行实验一下:在静态文件夹static下放置一下aaa.png的图片和在controller中创建一个controller来处理aaa.png的请求:

@RestController
public class HelloController {

    @RequestMapping(path = "aaa.png")
    public String testStaticOne(){
        return "hello,aaa";
    }
}

在请求的时候发现,打印出来的是:hello,aaa。

原理:首先访问controller,看看controller中能不能来进行处理,如果可以,那么controller来进行处理;如果不可以,那么静态资源解析器来进行处理。

其实这里详细的原理是因为

	protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		if (this.handlerMappings != null) {
			for (HandlerMapping mapping : this.handlerMappings) {
				HandlerExecutionChain handler = mapping.getHandler(request);
				if (handler != null) {
                  	 // SimpleUrlHandlerMapping来进行处理的
					return handler;
				}
			}
		}
		return null;
	}

修改默认静态文件存放位置

官方文档说明:

You can also customize the static resource locations by using the spring.resources.static-locations property (replacing the default values with a list of directory locations). The root Servlet context path, "/", is automatically added as a location as well.

可以自定义修改静态资源路径通过:spring.resources.static-locations。

也就是说,之前使用默认的存放静态文件夹的路径也可以发生修改:

# 应用名称
spring:
  application:
    name: springboot-static
  mvc:
    # 修改静态资源的访问前缀
    static-path-pattern: /ligres/**
  resources:
    # "classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"
    static-locations: ["classpath:/png/"]
# 应用服务 WEB 访问端口
server:
  port: 8080

那么对应的访问资源路径根据上面的配置文件应该是:http://localhost:8080/ligres/bbb.png

欢迎页配置

官方文档说明:

Spring Boot supports both static and templated welcome pages. It first looks for an index.html file in the configured static content locations. If one is not found, it then looks for an index template. If either is found, it is automatically used as the welcome page of the application.

SpringBoot支持欢迎页的配置

  • 会访问静态路径下的index.html;
  • 支持controller来处理/index请求;

但是上面因为配置了静态访问前缀,导致了欢迎页的失效。

所以修改一下静态访问前缀:

# 应用名称
spring:
  application:
    name: springboot-static
#  mvc:
    # 修改静态资源的访问前缀
#    static-path-pattern: /ligres/**
  resources:
    # "classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"
    static-locations: ["classpath:/png/"]
# 应用服务 WEB 访问端口
server:
  port: 8080

再次来进行访问png下面的index.html发现是成功的。

而在实际应用中也不需要使用过静态访问前缀,所以建议是关闭的。

源码分析

欢迎页

在web开发模式下,所有的自动配置都将会在xxxAutoConfiguration下,那么看下web开发的WebMvcAutoConfiguration

首先来看下欢迎页的配置:

@Bean
public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext, FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) {
            WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping(new TemplateAvailabilityProviders(applicationContext), applicationContext, this.getWelcomePage(), this.mvcProperties.getStaticPathPattern());
            welcomePageHandlerMapping.setInterceptors(this.getInterceptors(mvcConversionService, mvcResourceUrlProvider));
            welcomePageHandlerMapping.setCorsConfigurations(this.getCorsConfigurations());
            return welcomePageHandlerMapping;
        }

@Bean标注了的方法中的属性会自动从容器中来进行查找对应的组件。在这里直接来创建一个WelcomePageHandlerMapping对象

在创建对象的时候:

    WelcomePageHandlerMapping(TemplateAvailabilityProviders templateAvailabilityProviders, ApplicationContext applicationContext, Resource welcomePage, String staticPathPattern) {       
        if (welcomePage != null && "/**".equals(staticPathPattern)) {
            logger.info("Adding welcome page: " + welcomePage);
            this.setRootViewName("forward:index.html");
        } else if (this.welcomeTemplateExists(templateAvailabilityProviders, applicationContext)) {
            logger.info("Adding welcome page template: index");
            this.setRootViewName("index");
        }

    }

从上面中可以看到:如果静态访问前缀是/**,那么将会转发到index.html。也就是说不应该来配置静态访问前缀;

如果说没有找到,那么将会来利用controller中的/index来处理请求。

所以想要使用欢迎页的配置,有两种方式:第一种:关闭掉静态资源的访问前缀;第二种:写个controller来处理/index请求,然后来进行跳转接口

静态资源

        public void addResourceHandlers(ResourceHandlerRegistry registry) {
            if (!this.resourceProperties.isAddMappings()) {
                logger.debug("Default resource handling disabled");
            } else {
                this.addResourceHandler(registry, "/webjars/**", "classpath:/META-INF/resources/webjars/");
                this.addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), this.resourceProperties.getStaticLocations());
            }
        }

可以看到如果将spring.resources.mappings=FALSE之后,那么这里将会禁用掉静态资源的访问。

如果没有警用掉,那么将会来注册静态资源访问器,如果是webjars,那么默认的将会访问类路径下的/META-INF/resources/webjars/的请求;然后去访问static-path-pattern下的路径

        private void addResourceHandler(ResourceHandlerRegistry registry, String pattern, String... locations) {
            if (!registry.hasMappingForPattern(pattern)) {
                ResourceHandlerRegistration registration = WebMvcAutoConfiguration.AutoConfigurationResourceHandlerRegistry.addResourceHandler(registry, WebMvcAutoConfiguration.AutoConfigurationResourceHandlerRegistry.RegistrationType.AUTO_CONFIGURATION, pattern);
                registration.addResourceLocations(locations);
                registration.setCachePeriod(this.getSeconds(this.resourceProperties.getCache().getPeriod()));
                registration.setCacheControl(this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl());
                this.customizeResourceHandlerRegistration(registration);
            }
        }

可以看到上面的配置中有注册static-path-pattern路径下的路径以及缓存等等信息。

总结

如果开发的是前后端分离的项目,那么这里应该直接将spring.resources.mappings=FALSE,那么缓存也不会来进行开启。

如果使用单体项目,那么这里也可以将缓存设置为0;禁用掉缓存。

posted @ 2022-06-06 00:30  写的代码很烂  阅读(1127)  评论(0编辑  收藏  举报