Serving static contents in Spring Boot - spring-boot

I am developing a new poc for web application from Spring Boot. The packaging type of my application in war. In this all i want is to display some contents on a jsp. For that i have created a small jsp, and requierd css/images/js files i have put in resources/static folder. So my static folder contains css/images/js folders. I've added following code in my configuration file. My configuration extends from WebMvcConfigurerAdapter
public void addResourceHandlers(ResourceHandlerRegistry registry) {
String[] pathPatterns = {"/components/**", "/images/**", "/scripts/**", "/styles/**"};
String[] resourceLocations = {"classpath:/static/components/", "classpath:/static/images/", "classpath:/static/scripts/, classpath:/static/styles/"};
registry.addResourceHandler(pathPatterns).addResourceLocations(resourceLocations);
}
However, my jsp does not get the reference of these file.
JSP Code
How to solve above problem..
Second concern, as per the spring boot reference documentation, it serves the static content which are located in static folder. that means i should be able to access files from my static folder directly in below way
http://localhost:8080/styles/main.css
But this is also not working
Third Issue - static contents are served by default servlet ..is this true that Default servlet in enabled by default in Spring Boot application
Please Help

Putting the static resources inside src/main/resources/static folder works for me without any addResourceHandlers configuration. For example, I have a css file at
src/main/resources/static/public/css/styles.css
which I refer from my JSP like this:
<link href="/public/css/styles.css" rel="stylesheet">
You should have put your JSPs inside src/main/webapp/WEB-INF, and set the packaging to war rather than jar, due to the limitations of having JSPs in Spring Boot.

Related

Automatically finding Thymeleaf templates with Spring Boot

How can I get Spring Boot and Thymeleaf to automatically find and map template files to be processed when accessed by the browser?
src/main/resources/templates/index.xhtml
src/main/resources/templates/bar.xhtml
src/main/resources/application.properties contains spring.thymeleaf.suffix=.xhtml
FooController.java contains #RequestMapping("/foo") and a #PostMapping method that returns bar
If I enter http://localhost:8080/ in the browser, Thymeleaf processes and displays the index.xhtml page with no extra configuration needed. But http://localhost:8080/index, http://localhost:8080/index.xhtml, and http://localhost:8080/index.html all result in 404 Not Found.
My index view does a POST to foo; FooController is activated and returns bar; and Thymeleaf processes and shows bar.xhtml, even though bar.xhtml isn't mapped anywhere in the configuration. Yet accessing http://localhost:8080/bar, http://localhost:8080/bar.xhtml, and http://localhost:8080/bar.html in a browser all result in 404 Not Found.
Why does GET http://localhost:8080/ process the index.xhtml template, but GET http://localhost:8080/index does not?
How can Thymleaf use bar as a view, but I cannot access http://localhost:8080/bar directly?
How can I configure Thymeleaf so that I can add src/main/resources/templates/example.xhtml and have it processed automatically as a template that I can access via http://localhost:8080/example in the browser, with no explicit configuration specifically for the example.xhtml file?
If I absolutely have to configure controllers (see my answer below), is there a way that I can at least do this in some declarative file, outside of my code?
As noted in Spring in Action, Fifth Edition, I can do something like this in a #Configuration class that implements WebMvcConfigurer
#Override
public void addViewControllers(final ViewControllerRegistry registry) {
registry.addViewController("/bar");
}
That will allow me to process bar.xhtml automatically. (I presume there is some default configuration registry.addViewController("/").setViewName("index"), which is why my index.xhtml file is getting processed by accessing the root path.
And I can even use the following to automatically pick up any template:
#Override
public void addViewControllers(final ViewControllerRegistry registry) {
registry.addViewController("/**");
}
Unfortunately this removes the mapping from / to /index, and also prevents accessing any static resources from src/main/resources. I'm not sure how to tell Thymeleaf to use a template if it can, and fall back to a static file if not.

Thymeleaf +Spring Boot can't find files (FileNotFoundException)

This is a bit of a silly and frustrating one:
The #Configuration is taken from a tutorial website or forum and in it a
ServletContextTemplateResolver thymeleafTemplateResolver
is created using the ServletContext provided by spring boot.
When requested, a FileNotFoundException is thrown, despite the file being in the configured resources folder.
How do I get it to find the file / load it from the resources?
For thymeleaf to resolve the classpath resources, you need to configure a ClassLoaderTemplateResolver. (You were using a ServletContextTemplateResolver)
Also check that setPrefix is set to the correct folder, eg. "/thymeleaf/" if your documents are in resources/thymeleaf/ and that setSuffix is set to ".html" (or whatever your preferred file suffix is)
To also serve static content, you can extend WebMvcConfigurer and override addResourceHandlers, to then do e.g.
registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
assuming a static folder in your resources.
(Spring controllers take precedence here)

Unable to access the html file in template folder of spring boot application

html files are placed under resources/templates/login.html directory of spring boot application(show in the screenshot), deployed it in the weblogic server and when I try to access the login.html with the below URL, it gives The webpage cannot be found message
http://localhost:7001/demo/login.html
below is the screenshot
In one of the post I found the below code snippet and tried, but it didn't work
#Configuration
public class StaticResourceConfiguration extends WebMvcConfigurerAdapter {
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {
"classpath:/META-INF/resources/", "classpath:/resources/",
"classpath:/static/", "classpath:/public/" };
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**").addResourceLocations(CLASSPATH_RESOURCE_LOCATIONS);
}
I am not getting what mistake I did, Could some one help me regarding this ...?
Spring Boot by default serves all content found under /static, /public, /resources or /META-INF/resources, see docs. So all content in your static folder should be served well (check that). But the templates folder is not a sub-folder of the static, so it will not be served. If I get you right, the templates is not supposed to be part of the URL path, right? So you could either move your login.html to the static folder, or you could add the templates folder to the classpath resource locations. Either programmatically (as you did for the other locations), or by setting the corresponding property:
spring.resources.static-locations=classpath:/templates/,classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/

Spring Web Flux cannot resolve path to static content

I am using Spring Boot 2.0.0 M1 with WebFlux to build my sample web application. After succeeding with REST endpoints I've decided to add some views to my application. I've decided to use Thymeleaf 3.x version. I know that Spring serves static content from 4 default location:
/META-INF/resources/
/resources/
/static/
/public/
I've decided to go with second example so my css file is in /resources/static/css/. However after loading my page .css file was not found.
This is a screenshot from my IDE:
I am not providing my own configuration for static directory I just want to use default one. What might be important is the fact that templates are loading just fine from the /resources/templates/ directory.
Css file is loaded like this:
<link data-th-href="#{css/bootstrap.min.css}" rel="stylesheet">
App is not using normal Controller class instead I've provided function as a Bean to define my router:
#Bean
RouterFunction<?> router(final GeneratorHandler generatorHandler) {
return route(GET("/generate"), handler::render);
}
Any ideas what's wrong here?
I've found the right solution. In your RouterFunction you need to use:
return resources("/**", new ClassPathResource("/static/"))
This will set your static directory to:
:classpath/static

How to change the way Spring Boot serves static files?

After using JHipster on a couple of new projects recently (Highly recommended ! Amazing work !), I am trying to back-port some of the concepts into an older webapp, essentially migrating it to Spring Boot and Angular.
In Spring Boot, the default location for static web resources (HTML, JS, CSS, etc.) is in a directory called public, static or resources located at the root of the classpath. Any of these directories will be picked up by spring boot and files in them will be accessible via HTTP.
In JHipster the web files are in the src/main/webapp directory. Which is the directory used by default in a classic Maven WAR project.
I like this better because :
it more clearly separates the static web stuff from the classpath resources used by the Java code
the nesting is less deep (we already have enough levels of directories nesting with Maven as it is!).
But if I just create webapp directory in my project and put my HTML files in it, they are not available via HTTP, and the build process creates the WEB-INF directory structure in it. I don't want that, and in JHipster this is not the case.
How can I configure Spring Boot to behave like it does in JHipster ?
For those not familiar with JHipster : How can I instruct Spring Boot to serve static files from a different folder, no included in the classpath ?
You can try following configuration. The idea should be pretty straight forward. It does register artifacts in assets directory.
public class AppMvcConfiguration extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// Including all static resources.
registry.addResourceHandler("/assets/**",
"/css/**",
"/img/**",
"/js/**"
).addResourceLocations("/assets/",
"/css/",
"/img/",
"/js/"
).resourceChain(true)
.addResolver(new PathResourceResolver());
super.addResourceHandlers(registry);
}
}
you can add following code in application.propertise:
spring.resources.static-locations=classpath:/webapp/
and following code in application.yaml:
resources:
static-locations: classpath:/webapp/
I recently had the same issue and simply did a text search for "robots.txt" within my jHipster generated files.
I added my new file to the assets array in angular.json and put my new file in the same location as robots.txt, which as stated earlier is webapps.

Resources