SpringBoot-09-Web开发静态资源处理

Web开发静态资源处理

问题

既然Spring Boot 提供了web场景的启动器,那么它是如何去处理静态资源的呢?我们的静态资源存放在什么位置呢?

SpringBoot给我们提供了大量的自动配置类,而WebMVCAutoConfiguration就是Spring Boot给我们提供来支持web开发的自动配置类。

静态资源处理规则

在过去,我们项目的静态资源(如css,js等文件)是放在webapp下,现在pom打包方式是以jar的方式,那么Spring Boot是如何去处理对于静态资源存放的问题呢?

SpringBoot中,SpringMVC的web配置都在 WebMvcAutoConfiguration 这个配置类里面,可以找到一个addResourceHandlers()的方法,该方法用于资源处理

	public void addResourceHandlers(ResourceHandlerRegistry registry) {
			if (!this.resourceProperties.isAddMappings()) {
				//已禁用默认资源处理
				logger.debug("Default resource handling disabled");
				return;
			}
			//webjars配置
			addResourceHandler(registry, "/webjars/**", "classpath:/META-INF/resources/webjars/");
			//静态资源配置
			addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> {
				registration.addResourceLocations(this.resourceProperties.getStaticLocations());
				if (this.servletContext != null) {
					ServletContextResource resource = new ServletContextResource(this.servletContext, SERVLET_LOCATION);
					registration.addResourceLocations(resource);
				}
			});
		}

通过源码分析可知:访问所有的/webjars/**,都需要去 classpath:/META-INF/resources/webjars/ 找对应的资源

我们在静态资源配置那里继续点击getStaticPathPattern()方法

	public String getStaticPathPattern() {
		return this.staticPathPattern;
	}
		private String staticPathPattern = "/**";

发现了静态资源配置的路径是"/**",访问当前项目的任意资源,它会去寻找resourceProperties这个类的静态方法getStaticLocations(),我们点进去进行分析

	public String[] getStaticLocations() {
			return this.staticLocations;
		}
	
	private String[] staticLocations = 	CLASSPATH_RESOURCE_LOCATIONS;
	private static final String[] CLASSPATH_RESOURCE_LOCATIONS = { "classpath:/META-INF/resources/",
				"classpath:/resources/", "classpath:/static/", "classpath:/public/" };

ResourceProperties的静态方法getStaticLocations包含着Spring Boot会去寻找资源的文件夹名,保存在String数组中。

结论 四个目录可以存放的静态资源被Spring Boot识别

	1. "classpath:/META-INF/resources/"
	2. "classpath:/resources/"
	3. "classpath:/static/"
	4. "classpath:/public/"

可以在resources根目录下新建对应的文件夹,来存放我们的静态文件;在application.properties中配置;

自定义静态资源

我们可以指定配置文件,哪些文件夹用来存放静态资源

		spring.web.resources.static-locations="classpath:liang/"

Spring Boot默认为我们提供3种静态资源映射规则:

  • WebJar映射
  • 默认资源映射
  • 静态首页(欢迎页映射)

WebJars映射

过去我们为了让页面更加美观,让用户有更好的体验感,Web应用提供了大量的JS和CSS,例如 jQuery,Backbone.js 和 Bootstrap 等等,放在webapp下管理,但Spring Boot项目是以JAR包的形式进行部署的,不存在webapp目录,此时WebJars就出现了,它以Jar形式为Web项目提供资源文件。

WebJars 可以将 Web 前端资源(JS,CSS 等)打成一个个的 Jar 包,然后将这些 Jar 包部署到 Maven 中央仓库中进行统一管理,当 Spring Boot 项目中需要引入 Web 前端资源时,只需要访问 WebJars 官网,找到所需资源的 pom 依赖,将其导入到项目中即可。

下图展示如何通过 WebJars 查找 JQuery 的 pom 依赖的过程。
SpringBoot-09-Web开发静态资源处理_第1张图片
webjar打包的依赖

	
<dependency>
    <groupId>org.webjars.bower</groupId>
    <artifactId>jqurey</artifactId>
    <version>3.1.1</version>
</dependency>

代码实现

  1. 在Spring项目中pom.xml添加如下依赖
<dependency>
    <groupId>org.webjars.bower</groupId>
    <artifactId>jqurey</artifactId>
    <version>3.1.1</version>
</dependency>
  1. Spring Boot 项目中引入的 jquery 的 Jar 包结构如下图。
    SpringBoot-09-Web开发静态资源处理_第2张图片
  2. 启动 Spring Boot,浏览器访问“http://localhost:8080/webjars/jquery/3.6.0/jquery.js”访问 jquery.js,结果如下图。
    SpringBoot-09-Web开发静态资源处理_第3张图片

默认静态资源映射

当访问项目中的任意资源(即"/**")时,Spring Boot会默认从以下路径中查找资源文件(优先级依次降低)

  1. classpath:/META-ING/resources/
  2. classpath:/resources/
  3. classpath:/static/
  4. classpath:/public?

这些路径又被称为静态资源文件夹,当我们请求某个静态资源时,Spring Boot会从这些存放静态资源的路径下去寻找,从优先级高的找到优先级低的,知道找到指定的静态资源为止。

存在在不同文件下的静态资源的优先级

创建上述四个文件夹

/META-INF/resources/创建1.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<h1>/META-INF/resources</h1>
</body>
</html>

/resources/创建1.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<h1>resources</h1>
</body>
</html>

/static/创建1.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<h1>static</h1>
</body>
</html>

/public/创建1.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<h1>public</h1>
</body>
</html>

通过比较可以比较出它们之间的优先级。当我们请求某个静态资源(即以“.html”结尾的请求)时,Spring Boot 会先查找优先级高的文件夹,再查找优先级低的文件夹,直到找到指定的静态资源为止。


静态首页(欢迎页)映射

静态资源文件夹下的所有 index.html 被称为静态首页或者欢迎页,它们会被 /** 映射,换句话说就是,当我们访问"localhost:8080"时,都会跳转到静态首页(欢迎页)

	注意,访问静态首页或欢迎页时,其查找顺序也遵循默认静态资源的查找顺序,
	即先查找优先级高的目录,在查找优先级低的目录,直到找到 index.html 为止。

静态页面映射原理

  • 首先找到WebMVCAutoConfiguration自动配置类,找到WelcomePageHandlerMapping()方法
		public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext,
				FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) {
				//欢迎页面映射
			WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping(
					new TemplateAvailabilityProviders(applicationContext), applicationContext, getWelcomePage(),
					this.mvcProperties.getStaticPathPattern());
					/*getWelcomePage()得到欢迎页面,getStaticPathPattern()得到一个/**,
					通过/**映射跳转到欢迎页*/
			welcomePageHandlerMapping.setInterceptors(getInterceptors(mvcConversionService, mvcResourceUrlProvider));
			//设置拦截器
			welcomePageHandlerMapping.setCorsConfigurations(getCorsConfigurations());
			//设置其他配置
			return welcomePageHandlerMapping;
		}


点开getWelCome()方法

		//返回一个首页资源
		private Resource getWelcomePage() {
			for (String location : this.resourceProperties.getStaticLocations()) {
			//遍历所有的静态资源文件
				Resource indexHtml = getIndexHtml(location);
				//判断是否是index.html页面
				if (indexHtml != null) {
					return indexHtml;
				}
			}
			//上下文内容
			ServletContext servletContext = getServletContext();
			if (servletContext != null) {
				return getIndexHtml(new ServletContextResource(servletContext, SERVLET_LOCATION));
				//创建一个上文资源,通过/映射
			}
			return null;
		}

点开getIndexHtml()方

		private Resource getIndexHtml(String location) {
			return 
			//this.resourceLoader.getResource(location),加载静态的资源
			getIndexHtml(this.resourceLoader.getResource(location));
		}

		private Resource getIndexHtml(Resource location) {
			try {
				//判断index.html是否存在
				Resource resource = location.createRelative("index.html");
				if (resource.exists() && (resource.getURL() != null)) {
					return resource;
				}
			}
			catch (Exception ex) {
			}
			return null;
		}

通过上述,得出结论

静态首页映射的原理是Spring Boot去扫描静态资源目录下的index.html页面,同时遵循静态资源优先级原则。

测试

在项目public 路径下创建index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<h1>首页</h1>
</body>
</html>
  1. 打开启动器,就可以看到index.html的内容

SpringBoot-09-Web开发静态资源处理_第4张图片

你可能感兴趣的:(spring,boot,java,前端)