I've looked all over and I can't figure out what I am doing wrong with the way I am trying to serve my index.html page in my packaged spring-boot jar file. This is my app structure:
When I run mvn clean install it packages the jar properly and actually puts the index.html file into the static folder in the jar.
Here is my MVC Conf:
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
registry.addResourceHandler("/static/**").addResourceLocations("/static/");
registry.addResourceHandler("/app/**").addResourceLocations("/app/");
registry.addResourceHandler("/**").addResourceLocations("/");
}
Anything I am not doing properly?
OK I fixed it thanks to help from multiple sources! Here is what I did so it may help someone else:
1) add this resource in the POM. I am still not sure why I need this but my app will not serve without this. Spring boot should be doing this automatically but it apparently was not.
<resources>
<resource>
<directory>src/main/resources/static</directory>
<targetPath>static</targetPath>
</resource>
</resources>
2) In my MVC configuration I added this (similar to the answer below):
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {
"classpath:/META-INF/resources/", "classpath:/resources/",
"classpath:/static/", "classpath:/public/" };
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**").addResourceLocations(CLASSPATH_RESOURCE_LOCATIONS);
}
after adding these two things, my app started serving files!
Try to add "classpath" to the resource location,
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
I believe you should read this, how to serve static content:
http://docs.spring.io/spring-boot/docs/1.4.2.RELEASE/reference/htmlsingle/#boot-features-spring-mvc-static-content
To sum it up, your browser is caching your static resources, such as CSS files or html files.
In order to break this behavior, try first clean your browser cache, in google chrome you go to settings then clear browsing data.
Secondly, add these lines to your application.properties file in order to bust the cache:
spring.resources.chain.strategy.content.enabled=true
spring.resources.chain.strategy.content.paths=/**
or add this instead:
spring.resources.chain.strategy.fixed.enabled=true
spring.resources.chain.strategy.fixed.paths=/**
spring.resources.chain.strategy.fixed.version=v12
On spring boot project, you can get this working just by extending WebMvcConfigurerAdapter and override addResourceHandlers as below
#SpringBootApplication
public class DemoApplication extends WebMvcConfigurerAdapter {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
}
}
The index page will be accessible on http://localhost:8080/static/index.html
Related
I have a Spring Boot-based project (based on spring-boot-starter-parent and spring-boot-starter-web in which I want to both serve static content (built in another module, and copied into the project with maven-resources-plugin).
With the default configuration/conventions, it looks for static content in misc. places, like classpath:/static and classpath:/public, which is useful if the static content is to be served from the root URL, which for this project is not the case.
I want to serve it off /web/ which I have successfully done by deriving from WebMvcConfigurer (and annotated the class with #Configuration) and overridden the public void addResourceHandlers(ResourceHandlerRegistry registry) method; registry.addResourceHandler("/web/**").addResourceLocations("classpath:/static/web/");
This works when explicitly referring to the file names in the /web/-folder, but I can't figure out how I can emulate the "default document" behavior, e.g. index.html should be served for /web/. If you drop off an index.html in one of the root directories for static content, it will be handled by the WelcomePageHandlerMapping.
Found the solution; I also had to override the addViewControllers() to create an explicit mapping and fix the precedence:
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/web/").setViewName("index.html");
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
}
Hello i have images folder like this
What i want to do, is upload images to that folder and display them like this localhost:8080/image.jpg , so i can display it in frontend..
Nothing wrong is with upload, but i have no idea with displaying this images with api.
I already have tried
#Configuration
public class AdditionalResourceWebConfiguration implements WebMvcConfigurer {
#Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
registry.addResourceHandler("/images/**").addResourceLocations("file:images/");
}
}
But this is not working..
What i want to do, is upload images to that folder and display them
like this localhost:8080/image.jpg
URL should be localhost:8080/images/image.jpg as you are saving the images in images folder and mapping them as /images in addResourceHandler method
#Configuration
public class AdditionalResourceWebConfiguration implements WebMvcConfigurer {
#Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
registry.addResourceHandler("/images/**")
.addResourceLocations("file:images\\");
}
}
The correct syntax of using file: is file:///. I would rather keep the static resources inside resources/static directory from where it should automatically be picked up by spring boot. Here is the documentation related to resource handling in spring
I am using Spring Boot as an API and Angular as the frontend for my Application. I build with Maven and so configured the frontend-maven-plugin so it copies all the Angular dist folder into the final jar when building.
What I would like to have is all of my controllers' mapping to have a prefix like '/api' so it becomes '/api/users', but also that my static resources mappings stay what they are, like only '/sign-up' instead of '/api/sign-up'.
So I searched for the server.context-path and server.servlet-path properties but none of them worked. Anyone can help me please ?
#Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
#Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer.addPathPrefix("/api",
HandlerTypePredicate.forAnnotation(RestController.class)
.and(HandlerTypePredicate.forBasePackage("com.company.api")));
}
}
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:
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.
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.
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.
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.
to solve the problem with your point 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}.
You can create all those images under:
/resources/public
-img
-js,...
And to access just localhost:8080/img/yourImage.png
Everything under "public" folder will be accessible
Background
I have a spring boot application which has the logo.png file added to the static folder of the resource file, which is eventually built into the jar file which is used in the execution.
This jar application need to be run in multiple instances for different clients. So what I did is create an external application.properties file which distinguish the settings for each users.
http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html
Problem
But the problem is, i need to change the logo of each instance of my application. I cannot embed the customer logos into my application jar. Rather I need to keep it external like my application.properties.
For the moment, what I have done is check for the file logo.png in the same folder of jar of execution, and if excist, read the file, get base64 data and show it in the img tag.
But I want this to be done in a proper way as static content. I need the static content to be externalized. so I can let each customer have a specific instance of the jar running with different static resource content
For example. I need to keep the external static files as below and access from the urls in my view href or src attributes of the html tags.
Summary
Required folder structure
+ runtime
- myapp-0.1.0.jar
- application.properties
+ static
- logo.png
Should be able to access
<img th:src="#{/logo.png}" />
You can use resource handlers to serve external files - e.g.
#Component
class WebConfigurer extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/ext/**").addResourceLocations("file:///yourPath/static/");
}
}
The WebMvcConfigurerAdapter is deprecated. As from Spring Boot 2.x you could use WebMvcConfigurer instead.
#Configuration
public class MediaPathConfig {
// I assign filePath and pathPatterns using #Value annotation
private String filePath = "/ext/**";
private String pathPatterns = "/your/static/path/";
#Bean
public WebMvcConfigurer webMvcConfigurerAdapter() {
return new WebMvcConfigurer() {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!registry.hasMappingForPattern(pathPatterns)) {
registry.addResourceHandler(pathPatterns)
.addResourceLocations("file:" + filePath);
}
}
};
}
}