Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Serve dynamically changing static content with Spring Boot

Right now I have a simple Spring Boot application that serves static images that I have placed in resources/static/img. This works just fine for displaying the actual content, but there are two things I'd like to fix:

  1. I don't want any of these images to be bundled with the resulting .jar file, and I know that placing these images in the resources folder will do that.

  2. Using my current setup, in order to see a new image on the webapp, I have to add it to the folder and restart it. I would instead like Spring to serve any static content that exists in a specific folder, so I can add images while the application is running and have them automatically served at localhost:8080/img/{image name}.

I attempted to solve this by setting up a resource handler, but I'm not sure if this is any different than simply serving them from resources/static. Unfortunately, I'm still struggling with getting this configured correctly, as I'm unable to see any images at all. Here's what I tried:

@Configuration
public class StaticResourceConfiguration extends WebMvcConfigurerAdapter {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/img/**").addResourceLocations("file:" + Application.IMAGE_DIR);
        super.addResourceHandlers(registry);
    }
}

And here is my Application configuration:

@SpringBootApplication
public class Application extends SpringBootServletInitializer {

    static String IMAGE_DIR;

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Application.class);
    }

    public static void main(String[] args) throws IOException {
        SpringApplication.run(Application.class, args);
        IMAGE_DIR = new File(".").getCanonicalPath() + "/img/";
    }

}

Again, my goal is to set up a folder in the root of my project called img which will store the images that I would like the webapp to serve on localhost:8080/img/{image name}. If possible, I'd like to be able to add content to this folder while the application is running and have Spring automatically serve them without having to restart it.

Does anyone have any ideas? Thanks in advance.

like image 534
Michael Parker Avatar asked Mar 29 '16 15:03

Michael Parker


2 Answers

the problem with your approach is that you set IMAGE_DIR after spring boot application is ran and the constant IMAGE_DIR is not initialized and is null. Change it as follows:

public static void main(String[] args) throws IOException {
        IMAGE_DIR = "/opt/img/";
        SpringApplication.run(Application.class, args);
    }

and remove all File(".").getCanonicalPath() related stuff and it will work. Your approach will fit in your needs when you have new image in selected directory it can be served.

like image 161
Nikolay Rusev Avatar answered Oct 29 '22 22:10

Nikolay Rusev


A good solution for serving dynamic content with spring boot is to link a static content directory to a symbolic link with no cache and after that, you just need to rebuild symlink every time you need to reload. So in your case:

@Configuration
public class StaticResourceConfiguration extends WebMvcConfigurerAdapter {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/img/**").addResourceLocations("file:/tmp/images/").setCacheControl(CacheControl.noCache());
        super.addResourceHandlers(registry);
    }
}

After that, you change your image directory like this:

Path link = Paths.get("/tmp/images"); //Symlink
Files.deleteIfExists(link);
Files.createSymbolicLink(link, Paths.get(your_new_images_directory));

The choice of symlink /tmp/images is personal, you can choose what you want. Pay attention, your application needs to have good administrator rights for symlink creation.

like image 30
benerone Avatar answered Oct 29 '22 21:10

benerone