This is the fourth article, about how to deal with the third party static resources and their static resource summary, if just want to know where to put the static resources, or how to use directly, is really had said a few words, but I’m in the article followed the source or website/lot, induced to this a few points, although is nothing source code analysis, But at least static resources to deal with the problem, not empty and said, it is a simple guide

Interested friends can go to know about the other several articles have been published, your praise is the biggest support for me, thank you!

  • The article directories

SpringBoot takeoff road -HelloWorld

(two) SpringBoot takeoff road – analysis of the principle of entry

(three) SpringBoot takeoff road -YAML configuration summary (entry must know will)

(4) SpringBoot takeoff road – static resource processing

(five) SpringBoot takeoff road -Thymeleaf template engine

(6) SpringBoot takeoff road – integration jdbctemplate-druid-mybatis

(7) SpringBoot launch road – integration of SpringSecurity (Mybatis, JDBC, memory)

(eight) SpringBoot take-off path – integration Shiro detailed tutorial (MyBatis, Thymeleaf)

SpringBoot -Swagger 2 And 3

Description:

  • SpringBoot takeoff road series of articles involved in the source code, are synchronized to github, there is a need for small partners, go down at will
    • Github.com/ideal-20/Sp…
  • Untalented and uneducated, will point to shallow knowledge, we should be a tool to see it, do not like to spray ha ~

Description:

  • I was too busy and put them all together at the same time. Later, I felt that the length of the mobile terminal was too long and the reading experience was too poor, so I decided to divide it into several articles
  • Talent and learning, will point to shallow knowledge, we right as a tool to see, do not like not angry ha ~

(1) Static resource processing mode

In the previous demo, we only dealt with directly returning some data, such as strings, etc., but if you want to really do a full Web project, there is no page and a lot of static resources (CSS, JS, etc.), according to the previous Spring development, how can you do? We’ll have a WebApp folder in main, but the SpringBoot project we’re creating doesn’t, because SpringBoot has its own set of rules for static resource placement. Let’s see

(1) The first mapping rule

A: Rule analysis

So let’s take a look at SpringMVC’s configuration for the Web, CTRL + N look up WebMvcAutoConfiguration configuration class, go to addResourceHandlers, and I see an item that has to do with resource configuration, AddResourceHandlers, if you look at the source code, you can see that if you go to the /webjars/** directory, you’ll go to/meta-INF /resources/webjars/

addResourceHandlers

Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
if(! registry.hasMappingForPattern("/webjars/**")) {
    
    customizeResourceHandlerRegistration(registry.addResourceHandler("/webjars/**")
		.addResourceLocations("classpath:/META-INF/resources/webjars/")						.setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));

}
Copy the code

What does that mean? First take a look at the concept of Webjars

B: Webjars

In previous projects, if we needed some static resources, we would import files directly into the project, but Webjars introduces static resources as jar packages. Take a look:

Go to the official website: https://www.webjars.org

As you can see from WebJars, WebJars help you package web libraries such as jQuery and Bootstrap into jars that you can use quickly with dependencies

WebJars are client-side web libraries (e.g. jQuery & Bootstrap) packaged into JAR (Java Archive) files. Explicitly and easily manage the client-side dependencies in JVM-based web applications Use JVM-based build tools (e.g. Maven, Gradle, sbt, …) to download your client-side dependencies

Let’s use jquery as an example: Select the Mavan dependency

<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>jquery</artifactId>
    <version>3.5.1 track of</version>
</dependency>
Copy the code

After introducing poM, let’s review the source code we just looked at

If you visit the /webjars/** directory, you will go to/meta-INF /resources/webjars/

We found the jquery dependencies that were introduced, and you can see that everything we imported from the Webjars site is compliant with the Springboot default format, so let’s go ahead and take a look

Access format is: http://localhost:8080/webjars/ * * introduced it will automatically go/meta-inf/resources/webjars/find below, so directly from the jquery this folder can begin to write

So the access path is: http://localhost:8080/webjars/jquery/3.5.1/jquery.js

(2) The second mapping rule

A: Rule analysis

These third party web library problems give a way, but for a long time, has not said how to do their own pages, if you want to use their own static resources what to do?

Continue to look at the addResourceHandlers source code:

// Here is the first one
Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
if(! registry.hasMappingForPattern("/webjars/**")) {
   customizeResourceHandlerRegistration(registry.addResourceHandler("/webjars/**")
         .addResourceLocations("classpath:/META-INF/resources/webjars/")
         .setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
}

// Here is the second type
String staticPathPattern = this.mvcProperties.getStaticPathPattern();
if(! registry.hasMappingForPattern(staticPathPattern)) { customizeResourceHandlerRegistration(registry.addResourceHandler(staticPathPattern) .addResourceLocations(getResourceLocations(this.resourceProperties
	 .getStaticLocations()))                                     		  			      .setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
    
}
Copy the code

If you look at the /webjars/** path, you will go to/meta-INF /resources/webjars/

In the same position, let’s look at the second one, which is: To access the contents of the staticPathPattern path, go to getResourceLocations(this.resourceProperties.getStaticLocations ()

We follow the lead and keep going

String staticPathPattern = this.mvcProperties.getStaticPathPattern();
Copy the code

And finally, we found this one, and we got the path PI ** *

private String staticPathPattern = "/ * *";
Copy the code

We jump this. The resourceProperties. GetStaticLocations ()

You get a definition that looks like this

private String[] staticLocations = CLASSPATH_RESOURCE_LOCATIONS;
Copy the code

Go ahead and find such a definition again in ResourceProperties

private static final String[] CLASSPATH_RESOURCE_LOCATIONS = { 
    "classpath:/META-INF/resources/"."classpath:/resources/"."classpath:/static/"."classpath:/public/" 
};
Copy the code

Now we know the mapping rules for the second way

To access the contents of /**, go to/meta-INF /resources/, /resources/, /static/, /public/

B: Classpath

  • SRC files will be compiled into web-INF /classes, so the default classpath is there

  • When building a project with Maven, the Resources directory is the default classpath

C: testing

The following test, we respectively defined itself a js file placed in the resources folder of the resources, the static, public folder (not just create your own, static is the default, It is not possible to place the new version directly under the outer resources.

All of them are accessible after testing

Another conclusion can be drawn by comparing different tests:

Access priority: Resources > Static > Public

D: User-defined resource paths

If we also want to specify the path for static resources, a simple configuration can be done, such as the following configuration to specify the path to the Ideal and JSJSJS folders of Resources

spring.resources.static-locations=classpath:/ideal/,classpath:/jsjsjs/
Copy the code

Note: once a custom path is configured, the original autoconfiguration does not take effect

(2) Home page document processing

Continue to see WebMvcAutoConfiguration this configuration class, found a method about welcome page related welcomePageHandlerMapping, enclosing mvcProperties. GetStaticPathPattern (), The path continues, and getWelcomePage() is called again

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

Jump ahead and you’ll see two methods

Locations is defined as access to the resourceProperties. GetStaticLocations (), which is just what we discover that a few static resource folder, in getIndexHtml approach, and conducted a joining together, Find the index.html in the static resources folder

private Optional<Resource> getWelcomePage(a) {
   String[] locations = getResourceLocations(this.resourceProperties.getStaticLocations());
   return Arrays.stream(locations).map(this::getIndexHtml).filter(this::isReadable).findFirst();
}

private Resource getIndexHtml(String location) {
   return this.resourceLoader.getResource(location + "index.html");
}
Copy the code

Conclusion: The index.html under the static resources folder is the default welcome page

Don’t worry, let’s finish the processing of the icon file and test it together

Icon file processing

First of all, it should be noted that the 2.2.x source code for static resources favicon.ico has been changed in newer versions, for example

(1) Version before 2.2.x

In previous versions there was a default favicon.ico file, also known as the green leaf icon, in the WebMvcAutoConfiguration class

@Configuration
		@ConditionalOnProperty(value = "spring.mvc.favicon.enabled", matchIfMissing = true)
		public static class FaviconConfiguration implements ResourceLoaderAware {

			private final ResourceProperties resourceProperties;

			private ResourceLoader resourceLoader;

			public FaviconConfiguration(ResourceProperties resourceProperties) {
				this.resourceProperties = resourceProperties;
			}

			@Override
			public void setResourceLoader(ResourceLoader resourceLoader) {
				this.resourceLoader = resourceLoader;
			}

			@Bean
			public SimpleUrlHandlerMapping faviconHandlerMapping(a) {
				SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
				mapping.setOrder(Ordered.HIGHEST_PRECEDENCE + 1);
				mapping.setUrlMap(Collections.singletonMap("**/favicon.ico", faviconRequestHandler()));
				return mapping;
			}

			@Bean
			public ResourceHttpRequestHandler faviconRequestHandler(a) {
				ResourceHttpRequestHandler requestHandler = new ResourceHttpRequestHandler();
				requestHandler.setLocations(resolveFaviconLocations());
				return requestHandler;
			}

			private List<Resource> resolveFaviconLocations(a) {
				String[] staticLocations = getResourceLocations(this.resourceProperties.getStaticLocations());
				List<Resource> locations = new ArrayList<>(staticLocations.length + 1);
				Arrays.stream(staticLocations).map(this.resourceLoader::getResource).forEach(locations::add);
				locations.add(new ClassPathResource("/"));
				returnCollections.unmodifiableList(locations); }}Copy the code

Can be seen as long as the configuration spring. MVC. The favicon. Enabled can selectively to decide whether to use it the default green leaf icon, such as configuration to false close the default icon

application.properties

spring.mvc.favicon.enabled=false
Copy the code

If you want to use your own custom ICONS, you can name the file Favicon.ico and place it in the static Resources folder

(2) 2.2 x version

As for the processing of icon files, some changes have been made in the later version, so there is no icon related content in the configuration class WebMvcAutoConfiguration, let’s go to Github to have a look at the changes

First locate the class

Then jump to its History and see two related changes from 21 and 22 August 2019

  • Day 21: Put the static resources folder before the classpath first

  • Day 22: Remove the default Favicon and support for services from the classpath root, i.e., no more default ICO files

(3) Developer instructions

Let’s go ahead and look at Issues and see why developers are doing this. I’ve only captured three important ones

If you want to see the complete can visit: https://github.com/spring-projects/spring-boot/issues/17925

vpavic commented on 21 Aug 2019

The default favicon served by Spring Boot could be classified as information leakage, in a similar manner like Server HTTP header (see #4730) and exception error attribute (see #7872) were.

I’d consider removing the default favicon as applications that don’t provide custom favicon will inevitably leak info about being powered by Spring Boot.


wilkinsona commented on 21 Aug 2019

This is quite tempting. While we have a configuration property (spring.mvc.favicon.enabled), it’s enabled by default. The docs also do not seem to mention that a default favicon will be served so some people may not be aware of the out-of-the-box behaviour.

If an application developer cares about the favicon they will provide their own. If they don’t care about it I doubt there’s much difference to them between serving a default icon and serving nothing.


wilkinsona commented on 21 Aug 2019

Another benefit of removing the default favicon is that we could then also remove the spring.mvc.favicon.enabled property. It’s a benefit as the property is confusing. Setting it to false does not, as the property’s name might suggest, disable serving of a favicon.ico completely. It only disables serving a favicon.ico from the root of the classpath. A favicon.ico that’s placed in one of the static resource locations will still be served.


wilkinsona commented on 21 Aug 2019

We’ve decided to remove the default favicon.ico file, the resource handler configuration, and the property. Users who were placing a custom favicon.ico in the root of the classpath should move it to a static resource location or configure their own resource mapping.

You can also translate by yourself, I briefly summarize:

  • Vpavic believes that providing a default Favicon in Spring Boot could lead to site information leakage. If the user does not set the custom icon, Spring Boot will use the default green leaf, which can lead to leakage of the site’s development framework

  • Wilkinsona think just by the way, the spring. MVC. The favicon. Enabled this property also delete, set this value to false is not disabled icon, but merely to disable the default green leaves, and want to set a developer of icon, nature will care about, Developers who don’t care about icon Settings may have some major differences from those who do, or some uncertainties

  • Therefore, in Spring Boot2.2.x, the default favicon.ico is removed, and the above property configuration in application.properties is no longer provided

  • To set the icon, simply place the icon file Favicon.ico in the static resources folder or configure the mapping yourself

(4) Test execution

Do the following to see that both the home page and icon are in effect

(5) Ending

If there is any deficiency in the article, you are welcome to leave a message to exchange, thank friends for their support!

If it helps you, follow me! If you prefer the way of reading articles on wechat, you can follow my official account

We don’t know each other here, but we are working hard for our dreams

A adhere to push original development of technical articles of the public number: ideal more than two days