I have SpringBoot 1.3.3 and a working Java API exposed on port 8080. However, along with this API I would like to expose an index.html file located directly under {projectName}/src/main/resources/, according to the Springboot documentation this should be served up automatically but when I navigate to http://localhost:8080/index.html I get a 404. I am not using #EnableWebMVC anywhere and have tried adding my own configuration file like below, however nothing has worked so I'm kind of at a loss. Any help would be much appreciated!
#Configuration
#EnableWebMvc
#ComponentScan
public class ServerConfiguration extends WebMvcAutoConfiguration {
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);
}
}
Put the files in /src/main/resources/public/
Related
I am newbie to Springboot and I am trying to display html page on its root(localhost:8080) path. To do so I googled and gone through -
Spring Boot not serving static content
https://spring.io/blog/2013/12/19/serving-static-web-content-with-spring-boot
Spring Boot app not serving static content
Springboot does not serve static content
Tried almost everything but none of them worked for me.
Exact problem
With out index.html file inside any of resources/(static/ or public/ or meta-inf/resources) works fine and show the list of some spring data rest. If I create an index.html file then it gives an error of 404 not found with out #EnableWebMvc annotation, if use #EnableWebMvc then it shows the list of Spring data rest apis.
Other than index.html file it show the list of Spring data api in root path, and url(localhost:8080/test.html) to other than index.html has same problem.
This problem has no effects by implementing public class StaticResourceConfiguration implements WebMvcConfigurer with this configuration to.
Starting with a simple spring boot initializer
... we can place static (html) files into one of:
(src/main/resources:)
static
resources
public
META-INF
resources
which results in the default (class path) locations, configured via the spring.resources.static-locations property.
These will be exposed through the value of spring.mvc.static-path-pattern-property (ref), by default: /**.
So a static index.html file in one of the above mentioned folders, with default config, will be accessible at:
http:localhost:8080/ (due to "welcome file mapping" -> static mapping)
and http://localhost:8080/index.html (due to the static mapping)
Accordingly: no problem with http://localhost:8080/test.html ...
Checkout at github.
So this, at least answers the "question title" "how to serve static content in springboot 2.2.6?".
The order of spring.resources.static-locations appears (index.html preferred from META-INF/resources) also to be the "precedence" of static file locations (left-to-right, first match wins).
When we add #EnableWebMvc
..."evertyhing gets broken" (context loads, but) only:
WARN ... o.s.web.servlet.PageNotFound : No mapping for GET /
WARN ... o.s.web.servlet.PageNotFound : No mapping for GET /index.html
WARN ... o.s.web.servlet.PageNotFound : No mapping for GET /test.html
..please aslo consider this: why spring-boot application doesn't require #EnableWebMvc
With "non-default config", You would have to provide more details, to find a specific solution.
But for "newbie in Springboot": starting with an intializer and "the defaults" sounds optimal! From here on, you can re-fine your configuration based on a working one.
And if you want/need the #EnableWebMvc annotation for some reason, this will result in the "previous" behavior again/restore the (2.2.6) default static content handling:
#EnableWebMvc
#SpringBootApplication
public class DemoApplication implements WebMvcConfigurer {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/**")
.addResourceLocations("classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/");
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
(Assuming no conflicts with existing configuration/resource handlers)
It's working for me
registry.addResourceHandler("//**").addResourceLocations("classpath:/static/");
Files in resources/static are not available. How I can fix it?
Hierarchy:
resources/
db/
static/
image.png
templates/
application.properties
But if I open localhost:8081/image.png I get error.
My WebConfig:
#Configuration
#EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/webjars/**")
.addResourceLocations("/webjars/");
}
}
You should add below line to your existing resource mapping:
registry.addResourceHandler("/**")
.addResourceLocations("resources/static/");
You have configured the webjars resourceHandler to serve client side script or stylesheet dependencies. but custom handler is not added to serve your image file.
Since you are overriding the addResourceHandlers (ResourceHandlerRegistry registry) method, you should provide all the resourceLocation and handler mapping in your implementation.
Please check serving-static-web-content-with-spring-boot article to have more clear idea.
Note:
If you are using spring-boot you shouldn't be overriding the above method untill explicitly required as its already taken care in WebMvcAutoConfiguration.java.
Please check below default implementation:
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!this.resourceProperties.isAddMappings()) {
logger.debug("Default resource handling disabled");
return;
}
Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
CacheControl cacheControl = this.resourceProperties.getCache()
.getCachecontrol().toHttpCacheControl();
if (!registry.hasMappingForPattern("/webjars/**")) {
customizeResourceHandlerRegistration(registry
.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/")
.setCachePeriod(getSeconds(cachePeriod))
.setCacheControl(cacheControl));
}
String staticPathPattern = this.mvcProperties.getStaticPathPattern();
if (!registry.hasMappingForPattern(staticPathPattern)) {
customizeResourceHandlerRegistration(
registry.addResourceHandler(staticPathPattern)
.addResourceLocations(getResourceLocations(
this.resourceProperties.getStaticLocations()))
.setCachePeriod(getSeconds(cachePeriod))
.setCacheControl(cacheControl));
}
}
Here give path of your image:
registry.addResourceHandler("/**").addResourceLocations("file:/path/to/your/image/");
If you would prefer to serve static content (including web pages, js, pdf, css, pdf, doc etc.) from outside of the WAR, may be that is usefull. if you wanna changed any that static contents, just you can put changed file to your content path on application server easly and serving that without deploying or restarting you application server. If you prefer this way, you can do it with a small configuration on your application server.
I have a Spring Boot application which acts as a server for my frontend, built by webpack and included into my spring boot web archive.
I use webjars to access my frontend scripts and contents.
But there is one problem. To access webjars resources I need to use pathes like:
/webjars/jar-file-name/resource-name.ext
When in my react-js frontend code I use relateve pathes:
/resource-name.ext
I want to rebind paths of webjars to serve all resources /** from /webjars/jar-file-name
I have used this do to do it https://www.webjars.org/documentation#springmvc, but this seems to not work with Spring Boot
#Configuration
#EnableWebMvc
public class MvcConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
super.addResourceHandlers(registry);
registry.addResourceHandler("/**").addResourceLocations("classpath:/META-INF/resources/webjars/jar-file-name/");
}
}
It should work with Spring MVC, but don't work in Spring Boot.
Could you please advice the right way to do it?
I think the following code would resolve your issue:
#Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
}
Here is my static content serving URL for bootstrap 3.1.0 from tutorial: http://localhost:8080/bootstrap/3.1.0/css/bootstrap.min.css
The Problem
My spring-boot application recently changed routing from host/endpoint to host/middle/endpoint. Since the change, I am running into an issue where the resources are not being found relative to the new url structure. Before, I could reference resources like css stylesheets like link(rel='stylesheet', href='css/style.css'), but now the logger shows an error saying it can't find the resource at /middleman/css/style.css.
From my research, I have found that what I need to do is use a resource handler registry. I have created one (as shown below) but it doesn't seem to be working. I think the problem is that even though I now have the resource registry, I am not referencing resources in the registry. What is the proper way to solve this problem and have all resources point load from the same place regardless of the endpoint? I very well may be missing some obvious piece of SOP
Note: This is all a dumbed down representation of my project in order to give the idea of what is going on without giving unnecessary information.
Project Structure
src
main
java
com.mystuff.cool
configurations
ResourceConfiguration.java
controllers
RoutingController.java
application
Application.java
resources
static
css
footer.css
style.css
images
place1.png
location1.png
spot1.png
favicon.ico
javascripts
layout.js
templates
home.jade
Application Class
#ComponentScan(basePackages = {"my.packages"})
#EnableAutoConfiguration
#EnableSAMLSSO
#Configuration
public class Application
{
public static void main(String[] args)
{
SpringApplication.run(new Object[]{ Application.class, ServiceConfig.class, ResourceConfiguration.class}, args);
}
}
Resource Configuration
#EnableWebMvc
#Configuration
public class ResourceConfiguration extends WebMvcConfigurerAdapter
{
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry)
{
registry.addResourceHandler("/css/**").addResourceLocations("/css/").setCachePeriod(31556926);
registry.addResourceHandler("/img/**").addResourceLocations("/img/").setCachePeriod(31556926);
registry.addResourceHandler("/js/**").addResourceLocations("/js/").setCachePeriod(31556926);
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer)
{
configurer.enable();
}
}
Controller
#Controller
public class RoutingController
{
#RequestMapping("/house/home")
public String home(Model model)
{
model.addAttribute("title", "Home is where the heart is");
commonModelTribs(model);
return "home";
}
}
Home Page
doctype html
html
title Place-spedia #{title}
link(rel='icon', href='images/favicon.ico')
link(rel='stylesheet', href='css/style.css')
script(src='javascripts/layout.js')
link(rel='stylesheet', href='css/footer.css')
body
div#footer-icons
a(href='place1')
img#place1(src="images/place1.png")
a(href='location1')
img#location1(src="images/location1.png")
a(href='spot1')
img#spot1(src='images/spot1.png')
If you are using spring boot, you don't need to worry about the resource configuration since you are already configuring the resource directory through the auto configuration. The default behavior for the autoconfiguration is to look within resources/static.
Your issue is with your href values, try inserting a leading forward slash:
link(rel='icon', href='/images/favicon.ico')
link(rel='stylesheet', href='/css/style.css')
script(src='javascripts/layout.js')
link(rel='stylesheet', href='/css/footer.css')
Spring is routing your application to a new relative path, so by putting the leading / in your href attributes, you are telling the router to look absolutely within the static directory instead of relatively from the middle directory.
I ran the spring-boot-sample-web-static project from here, made this alteration to the pom
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
And added this class to serve a duplicate page index2.html from the same static folder location:
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
#Controller
public class Rester {
#RequestMapping(value = "/rand", produces = MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
private RandomObj jsonEndpoint() {
return new RandomObj();
}
#RequestMapping(value = "/tw")
public String somePg() {
return "index2";
}
}
The json url works fine, but when I try to access localhost:8080/tw I get a blank page, and this error in the console:
2017-02-22 15:37:22.076 ERROR 21494 --- [nio-8080-exec-9] o.s.boot.web.support.ErrorPageFilter : Cannot forward to error page for request [/tw] as the response has already been committed. As a result, the response may have the wrong status code. If your application is running on WebSphere Application Server you may be able to resolve this problem by setting com.ibm.ws.webcontainer.invokeFlushAfterService to false
Am I doing something wrong?
Static files should be served from resources, not from a controller.
Spring Boot will automatically add static web resources located within
any of the following directories:
/META-INF/resources/
/resources/
/static/
/public/
refs:
https://spring.io/blog/2013/12/19/serving-static-web-content-with-spring-boot
https://spring.io/guides/gs/serving-web-content/
In Spring boot, /META-INF/resources/, /resources/, static/ and public/ directories are available to serve static contents.
So you can create a static/ or public/ directory under resources/ directory and put your static contents there. And they will be accessible by: http://localhost:8080/your-file.ext. (assuming the server.port is 8080)
You can customize these directories using spring.resources.static-locations in the application.properties.
For example:
spring.resources.static-locations=classpath:/custom/
Now you can use custom/ folder under resources/ to serve static files.
This is also possible using Java config in Spring Boot 2:
#Configuration
public class StaticConfig implements WebMvcConfigurer {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/custom/");
}
}
This confugration maps contents of custom directory to the http://localhost:8080/static/** url.
I am using :: Spring Boot :: (v2.0.4.RELEASE) with Spring Framework 5
Spring Boot 2.0 requires Java 8 as a minimum version. Many existing APIs have been updated to take advantage of Java 8 features such as: default methods on interfaces, functional callbacks, and new APIs such as javax.time.
Static Content
By default, Spring Boot serves static content from a directory called /static (or /public or /resources or /META-INF/resources) in the classpath or from the root of the ServletContext. It uses the ResourceHttpRequestHandler from Spring MVC so that you can modify that behavior by adding your own WebMvcConfigurer and overriding the addResourceHandlers method.
By default, resources are mapped on /** and located on /static directory.
But you can customize the static loactions programmatically inside our web context configuration class.
#Configuration #EnableWebMvc
public class Static_ResourceHandler implements WebMvcConfigurer {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// When overriding default behavior, you need to add default(/) as well as added static paths(/webapp).
// src/main/resources/static/...
registry
//.addResourceHandler("/**") // « /css/myStatic.css
.addResourceHandler("/static/**") // « /static/css/myStatic.css
.addResourceLocations("classpath:/static/") // Default Static Loaction
.setCachePeriod( 3600 )
.resourceChain(true) // 4.1
.addResolver(new GzipResourceResolver()) // 4.1
.addResolver(new PathResourceResolver()); //4.1
// src/main/resources/templates/static/...
registry
.addResourceHandler("/templates/**") // « /templates/style.css
.addResourceLocations("classpath:/templates/static/");
// Do not use the src/main/webapp/... directory if your application is packaged as a jar.
registry
.addResourceHandler("/webapp/**") // « /webapp/css/style.css
.addResourceLocations("/");
// File located on disk
registry
.addResourceHandler("/system/files/**")
.addResourceLocations("file:///D:/");
}
}
http://localhost:8080/handlerPath/resource-path+name
/static /css/myStatic.css
/webapp /css/style.css
/templates /style.css
In Spring every request will go through the DispatcherServlet. To avoid Static file request through DispatcherServlet(Front contoller) we configure MVC Static content.
As #STEEL said static resources should not go through Controller. Thymleaf is a ViewResolver which takes the view name form controller and adds prefix and suffix to View Layer.
As it is written before, some folders (/META-INF/resources/, /resources/, /static/, /public/) serve static content by default, conroller misconfiguration can break this behaviour.
It is a common pitfall that people define the base url of a controller in the #RestController annotation, instead of the #RequestMapping annotation on the top of the controllers.
This is wrong:
#RestController("/api/base")
public class MyController {
#PostMapping
public String myPostMethod( ...) {
The above example will prevent you from opening the index.html. The Spring expects a POST method at the root, because the myPostMethod is mapped to the "/" path.
You have to use this instead:
#RestController
#RequestMapping("/api/base")
public class MyController {
#PostMapping
public String myPostMethod( ...) {
I had to add thymeleaf dependency to pom.xml. Without this dependency Spring boot didn't find static resources.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
You can quickly serve static content in JAVA Spring-boot App via thymeleaf (ref: source)
I assume you have already added Spring Boot plugin apply plugin: 'org.springframework.boot' and the necessary buildscript
Then go ahead and ADD thymeleaf to your build.gradle ==>
dependencies {
compile('org.springframework.boot:spring-boot-starter-web')
compile("org.springframework.boot:spring-boot-starter-thymeleaf")
testCompile('org.springframework.boot:spring-boot-starter-test')
}
Lets assume you have added home.html at src/main/resources
To serve this file, you will need to create a controller.
package com.ajinkya.th.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
#Controller
public class HomePageController {
#RequestMapping("/")
public String homePage() {
return "home";
}
}
Thats it ! Now restart your gradle server. ./gradlew bootRun