Resources

The Resource interface represents abstract resource. This allows you to process resources in the same way, whether the resource is specified by URL, file, byte array and etc.

The DispatcherServlet servlet provides default handling of resources. In most cases you need just save the resource file in appropriate folder like "resources/static" in your project.

resource paths

The default resource paths are defined in the ResourceProperties class.

You can register own resources path for uploading new resources or to save resources created by your application. This is very useful when application is executed as a jar file because default paths in this case are read-only.

If several paths have resources with the same file name, then the file will be taken from the first path in the registration order. Thus, you can dynamically replace a resource from a JAR file with a new resource without redeploying the application.

@Configuration
//@AutoConfigureAfter(DispatcherServletAutoConfiguration::class)
class AppConfig : WebMvcConfigurer {

override fun addResourceHandlers(registry: ResourceHandlerRegistry) {
  val locations = arrayOf(
    "file:./resources/", // our new folder
    "classpath:/META-INF/resources/",
    "classpath:/resources/",
    "classpath:/static/",
    "classpath:/public/")

  // create new resource folder and subfolder "files"
  File(File("."), "resources").apply {
      mkdirs()
      File(this, "files").mkdirs()
     }

  registry.addResourceHandler("/**") 
    .addResourceLocations(*locations)
    .setCacheControl(CacheControl.maxAge(30, TimeUnit.DAYS)
         .cachePublic())
  }
}
@Configuration
public class AppConfiJ implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        String[] locations = {
                "file:./resources/",
                "classpath:/META-INF/resources/",
                "classpath:/resources/",
                "classpath:/static/",
                "classpath:/public/"};

        File newResFolder = new File(new File("."), "resources");
        newResFolder.mkdirs();
        // additional subfolder
        new File(newResFolder, "files").mkdirs();

        registry.addResourceHandler("/**")
                .addResourceLocations(locations)
                .setCacheControl(CacheControl.maxAge(30, TimeUnit.DAYS)
                        .cachePublic());
    }
}

Also you can try set paths in the application.properties file.

spring.resources.static-location=file:./resources,classpath:static,...

loading resource

// create loader instance and load resource
val res : Resource = DefaultResourceLoader()
                        .getResource("classpath:myres.txt")

//---------------------------------
// in bean you can use injecting

@Autowired // inject loader
lateinit var resourceLoader : ResourceLoader;
...
val res : Resource = resourceLoader.getResource("classpath:myres.txt")

// inject resource directly
@Value("classpath:myres.txt")
lateinit var res : Resource;

// shorthand loading by resource class
val resArray = arrayOf(ClassPathResource(cpRes),
                       FileSystemResource(fileRes)) 

resource resolving

You can change the default resource resolver or create a chain of resolvers. PathResourceResolver must be last resolver in chain if it is used.

override fun  addResourceHandlers(registry: ResourceHandlerRegistry) {
    registry.addResourceHandler(resHandler)
      .addResourceLocations(resLocations)
      .resourceChain(true)
      .addResolver(new GzipResourceResolver())
      .addResolver(new PathResourceResolver())
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler(resHandler)
      .addResourceLocations(resLocations)
      .resourceChain(true)
      .addResolver(new GzipResourceResolver())
      .addResolver(new PathResourceResolver());
}

built-in Resource implementations

class description
UrlResource Resource implementation for java.net.URL locators. Supports resolution as a URL and also as a File in case of the "file:" protocol.
FileSystemResource Resource implementation for java.io.File and java.nio.file.Path handles with a file system target. Supports resolution as a File and also as a URL. Implements the extended WritableResource interface.
ClassPathResource Resource implementation for class path resources. Uses either a given ClassLoader or a given Class for loading resources. Supports resolution as java.io.File if the class path resource resides in the file system, but not for resources in a JAR. Always supports resolution as URL.
HttpResource Extended interface for a Resource to be written to an HTTP response.
ByteArrayResource Resource implementation for a given byte array. Creates a ByteArrayInputStream for the given byte array. Useful for loading content from any given byte array, without having to resort to a single-use InputStreamResource. Particularly useful for creating mail attachments from local content, where JavaMail needs to be able to read the stream multiple times.

built-in resource loaders

class description
DefaultResourceLoader Default implementation of the ResourceLoader interface. Will return a UrlResource if the location value is a URL, and a ClassPathResource if it is a non-URL path or a "classpath:" pseudo-URL.
FileSystemResourceLoader ResourceLoader implementation that resolves plain paths as file system resources rather than as class path resources. Plain paths will always be interpreted as relative to the current VM working directory, even if they start with a slash. Use an explicit "file:" prefix to enforce an absolute file path.
ClassRelativeResourceLoader ResourceLoader implementation that interprets plain resource paths as relative to a given java.lang.Class.

built-in resource resolvers

resolver description
PathResourceResolver Finds resources under configured locations (classpath, file system…) matching to the request path.
CachingResourceResolver Resolves resources from a Cache instance or delegates to the next Resolver in the chain.
GzipResourceResolver Finds variations of a resource with a “.gz” extension when HTTP clients support gzip compression.
VersionResourceResolver Resolves request paths containing a version string, i.e. version information about the resource being requested. This resolver can be useful to set up HTTP caching strategies by changing resources’ URLs as they are updated.