Stellen Sie statische Ressourcen mit Spring bereit

1. Übersicht

In diesem Artikel wird erläutert, wie statische Ressourcen mit Spring bereitgestellt werden - sowohl mit XML- als auch mit Java-Konfiguration.

2. Verwenden von Spring Boot

Spring Boot wird mit einer vorkonfigurierten Implementierung von ResourceHttpRequestHandler geliefert , um das Bereitstellen statischer Ressourcen zu erleichtern.

Standardmäßig stellt dieser Handler statischen Inhalt aus einem der Verzeichnisse / static, / public, / resources und / META-INF / resources bereit, die sich im Klassenpfad befinden . Da sich src / main / resources normalerweise standardmäßig im Klassenpfad befindet, können wir jedes dieser Verzeichnisse dort ablegen.

Wenn wir beispielsweise eine about.html- Datei in das Verzeichnis / static in unserem Klassenpfad einfügen , können wir über //localhost:8080/about.html auf diese Datei zugreifen . Ebenso können wir das gleiche Ergebnis erzielen, indem wir diese Datei in andere erwähnte Verzeichnisse einfügen.

2.1. Benutzerdefinierte Pfadmuster

Standardmäßig stellt Spring Boot den gesamten statischen Inhalt im Stammteil der Anforderung bereit , dh / ** . Obwohl es sich um eine gute Standardkonfiguration zu handeln scheint, können wir sie über die Konfigurationseigenschaft spring.mvc.static-path-pattern ändern .

Wenn wir beispielsweise über //localhost:8080/content/about.html auf dieselbe Datei zugreifen möchten, können wir dies in unseren application.properties angeben :

spring.mvc.static-path-pattern=/content/**

In WebFlux environments, we should use the spring.webflux.static-path-pattern property.

2.2. Custom Directories

Similar to path patterns, it's also possible to change the default resource locations via the spring.resources.static-locations configuration property. This property can accept multiple comma-separated resource locations:

spring.resources.static-locations=classpath:/files/,classpath:/static-files

Here, we're serving static contents from the /files and /static-files directories inside the classpath. Moreover, Spring Boot can serve static files from outside of the classpath:

spring.resources.static-locations=file:/opt/files 

Here we're using the file resource signature, file:/, to serve files from our local disk.

3. XML Configuration

If you need to go the old fashion way with XML-based configuration, you can make good use of the mvc:resources element to point to the location of resources with a specific public URL pattern.

For example – the following line will serve all requests for resources coming in with a public URL pattern like “/resources/**” by searching in the “/resources/” directory under the root folder in our application.

Now, we can access a CSS file as in the following HTML page:

Example 3.1.


     Home   

4. The ResourceHttpRequestHandler

Spring 3.1. introduced the ResourceHandlerRegistry to configure ResourceHttpRequestHandlers for serving static resources from the classpath, the WAR, or the file system. We can configure the ResourceHandlerRegistry programmatically inside our web context configuration class.

4.1. Serving a Resource Stored in the WAR

To illustrate this, we'll use the same URL as before to point to myCss.css, but now the actual file will be located in the WAR's webapp/resources folder, which is where static resources should be placed when deploying Spring 3.1+ applications:

Example 4.1.1.

@Configuration @EnableWebMvc public class MvcConfig implements WebMvcConfigurer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry .addResourceHandler("/resources/**") .addResourceLocations("/resources/"); } }

Let's analyze the example bit. First, we configure the external-facing URI path by adding defining a resource handler. Then, we map that external-facing URI path internally to the physical path where the resources are actually located.

We can, of course, define multiple resource handlers using this simple yet flexible API.

Now – the following line in an html page would get us the myCss.css resource inside the webapp/resources directory:


    

4.2. Serving a Resource Stored in the File System

Let's say we want to serve a resource stored in the /opt/files/ directory whenever a request comes in for the public URL matching the pattern: /files/**. We simply configure the URL pattern and map it to that particular location on disk:

Example 4.2.1.

@Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry .addResourceHandler("/files/**") .addResourceLocations("file:/opt/files/"); }

*(For Windows users: The argument passed to addResourceLocations for this example would be “file:///C:/opt/files/“).

Once we configure the resource location, we can use the mapped URL pattern in our home.html to load an image stored in the file system as follows:

Example 4.2.2.


     Home   

4.3. Configuring Multiple Locations for a Resource

What if we want to look for a resource in more than one location?

We can include multiple locations with the addResourceLocations method. The list of locations will be searched in order until the resource is found. Let's take a look at Example 3.3.1.

Example 4.3.1

@Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry .addResourceHandler("/resources/**") .addResourceLocations("/resources/","classpath:/other-resources/"); }

The following curl request will display the Hello.html page stored in either the application's webappp/resources or the other-resources folder in the classpath.

curl -i //localhost:8080/handling-spring-static-resources/resources/Hello.html

5. The New ResourceResolvers

Spring 4.1. provides – with the new ResourcesResolvers – different types of resource resolvers that can be used to optimize browser performance when loading static resources. These resolvers can be chained and cached in the browser to optimize request handling.

5.1. The PathResourceResolver

This is the simplest resolver and its purpose is to find a resource given a public URL pattern. In fact, if no ResourceResolver is added to the ResourceChainRegistration, this is the default resolver.

Let's see an example:

@Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry .addResourceHandler("/resources/**") .addResourceLocations("/resources/","/other-resources/") .setCachePeriod(3600) .resourceChain(true) .addResolver(new PathResourceResolver()); }

Things to notice:

  • We are registering the PathResourceResolver in the resource chain as the sole ResourceResolver in it. See section 4.3. to check how to chain more than one ResourceResolver.
  • The resources served will be cached in the browser for 3600 seconds.
  • The chain is finally configured with the method resourceChain(true).

Now – the HTML code that, in conjunction with the PathResourceResolver, locates the foo.js script in either the webapp/resources of the webapp/other-resources folder: