configuring Spring MVC welcome page - spring

I was trying for two days to set up the index page using spring 4.
After many attempts I got a piece of code that worked
But I did not understand why it worked.
Could you tell me why.
public class MyWebApplicationInitializer
extends AbstractAnnotationConfigDispatcherServletInitializer
{
protected Class<?>[] getRootConfigClasses() {
return new Class[] {AplicationConfig.class};
}
protected Class<?>[] getServletConfigClasses() {
return new Class[] {WebConfiguration .class};
}
protected String[] getServletMappings() {
return new String[] {"/"};
}
}
Here's the snippet of code I found
// #Bean
// public InternalResourceViewResolver internalResourceViewResolver() {
// InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
// viewResolver.setPrefix("/WEB-INF/html/");
// viewResolver.setSuffix(".html");
// return viewResolver;
// }
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/*.html").addResourceLocations("/WEB-INF/html/");
super.addResourceHandlers(registry);
}
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController( "/" ).setViewName( "forward:/index.html" );
// registry.setOrder( Ordered.HIGHEST_PRECEDENCE );
// super.addViewControllers( registry );
}
my folders
1) why InternalResourceViewResolver do not work?
2) How does addResourceHandler and addViewController work? What are these paths?
3)And how do I add the css and javascripts file to the index page? like
<link href="/css/bootstrap.min.css" rel="stylesheet">
The page loads but this without the css and javascript files
I want to thank everyone who helped me because I'm a newbie in spring, thanks guys.

Only configuring InternalResourceViewResolver is not enough to serve static html. You also need to bind a path through controller to serve the page. As this is just a static page you can do that with
addViewControllers.
registry.addViewController("/").setViewName("index");
2.
addResourceHandlers: Add handlers to serve static resources such as images, js, and, css files from specific locations under web application root, the classpath, and others.
addViewControllers: Configure simple automated controllers pre-configured with the response status code and/or a view to render the response body. This is useful in cases where there is no need for custom controller logic -- e.g. render a home page, perform simple site URL redirects, return a 404 status with HTML content, a 204 with no content, and more.
http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/config/annotation/WebMvcConfigurer.html#addResourceHandlers-org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry-
3.
To make the resources(js, css, img) available, you need to add following configuration inside your addResourceHandlers methods.
registry.addResourceHandler("/css/**").addResourceLocations("/css/");
registry.addResourceHandler("/js/**").addResourceLocations("/js/");
registry.addResourceHandler("/img/**").addResourceLocations("/img/");
And then to include css or js in a JSP page, you can use JSTL tag c:url or Spring tag spring:url.
<link href="<c:url value="/css/styles.css" />" rel="stylesheet">
<spring:url value="/css/styles.css" var="mainCss" />
<link href="${mainCss}" rel="stylesheet" />

Related

Could not resolve view with name 'index' in Spring Boot

Spring boot: 2.3.3.RELEASE
Java: 11
I use webflux + RouterFunction + Thymeleaf and encounter the error "Could not resolve view with name 'index'".
index.html is under "resources/templates".
I put some source code looks important.
Are we not able to use Thymeleaf if we use "RouterFunction"?
Please feel free to put a comment if you need more detail.
######## handler ###########
#Component
public class ItemHandler {
public RouterFunction<ServerResponse> routes = route()
.path("/item", builder -> builder.GET("/", this::index))
.build();
public Mono<ServerResponse> index(ServerRequest request) {
Map<String, Object> attributes = new HashMap<>();
attributes.put("items", "Hello");
return ServerResponse.ok().contentType(MediaType.TEXT_HTML)
.render("index", attributes);
}
}
######## index.html ###########
<!DOCTYPE html>
<html lang="ja"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
</head>
<body>
<h1>FluxTest</h1>
</body>
</html>
######## entry point ###########
#SpringBootApplication
public class DemoWebfluxApplication {
public static void main(String[] args) {
SpringApplication.run(DemoWebfluxApplication.class, args);
}
}
The default property in charge of handling the location of static files is spring.resources.static-locations.
The default values are /META-INF/resources/, /resources/, /static/, /public/. You can either override the default values or put your index.html in one of these locations.

Spring Boot MVC Remote Templates

I want to put our templates folder in a remote host like aws-s3, currently
using a custom urlTemplateResolver and using the thymeleaf replace tag.
#Configuration
public class SpringTemplateConfiguration {
private final SpringResourceTemplateResolver springResourceTemplateResolver;
#Value("${spring.thymeleaf.cache}")
Boolean springThymeleafCache;
public SpringTemplateConfiguration(SpringResourceTemplateResolver springResourceTemplateResolver) {
this.springResourceTemplateResolver = springResourceTemplateResolver;
}
#Bean
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
UrlTemplateResolver urlTemplateResolver = new UrlTemplateResolver();
urlTemplateResolver.setCacheable(springThymeleafCache); // explicit set cacheable, otherwise it will be always cached
templateEngine.addTemplateResolver(urlTemplateResolver);
templateEngine.addTemplateResolver(springResourceTemplateResolver);
return templateEngine;
}
}
and this is the thymeleaf template
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org" th:replace="~{${url} :: html}">
</html>
is there another way to just use the templates folder from the remote host and just return the view name from the controller ??
It is possible to use another external location but not remote location which doesn't solve our problem.

Spring Boot displays images in some pages but not others

I'm facing issues with images in my Spring Boot + Thymeleaf application.
After reading a lot of fixes I'm able to show images in some of my app's pages but in other pages the images doesn't show.
I think that the number of paths in the request made is involved. It seems that requests to /myaction render pages showing images while requests to /myaction/other render pages not showing images.
In the fomer the successful request to obtain the images is:
http://localhost:8080/myapp/images/logo.png
In the latter the failed request to obtain the images is:
http://localhost:8080/myapp/myaction/images/logo.png
I append my configuration:
In my implementation of WebMvcConfigurerAdapter:
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("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
registry.addResourceHandler("/**")
.addResourceLocations(CLASSPATH_RESOURCE_LOCATIONS);
}
Controller class:
#Controller
#RequestMapping(path="/myaction")
public class PagosController {
#GetMapping(path="")
public String show(Model model) {
//...
}
#GetMapping(path="/other")
public String show2(Model model) {
//...
}
}
In my html template I load the image this way:
<img th:src="#{images/logo.png}" />
logo.png
The file logo.png is located in src/main/resources/static/images
I have no clue why this is happening. Any idea on why images are getting requested at http://localhost:8080/myapp/myaction/images/logo.png? Thanks in advance.
According to your configuration, the images are available from the root /.
So you should be able to use <img th:src="#{/images/logo.png}" /> in any page.

Spring Boot, static resources and mime type configuration

I'm facing a Spring Boot configuration issue I can't deal with...
I'm trying to build an HelloWorld example for HbbTV with Spring Boot, so I need to serve my "index.html" page with mime-type="application/vnd.hbbtv.xhtml+xml"
my index.html will be accessed as a static page, for instance http://myserver.com/index.html?param=value.
with the following code, no matter how hard I try, I get a text/html content type.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//HbbTV//1.1.1//EN" "http://www.hbbtv.org/dtd/HbbTV-1.1.1.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>MyApp HBBTV</title>
<meta http-equiv="content-type" content="Content-Type: application/vnd.hbbtv.xhtml+xml; charset=UTF-8" />
</head>
<body>
...
</body>
</html>
So I tried to add a "home()" endpoint into a #Controller to force the correct mime-type, and that works.
#RestController
public class HbbTVController {
#RequestMapping(value = "/hbbtv", produces = "application/vnd.hbbtv.xhtml+xml")
String home() {
return "someText";
}
...
}
"That works" mean the jetty server serves me a html file with the correct content-type containing the test someText.
My next try were to replace the #RestController by #Controller (same produce config), and replace "someText" by index.html
#Controller
public class HbbTVController {
#RequestMapping(value = "/hbbtv", produces = "application/vnd.hbbtv.xhtml+xml")
String home() {
return "index.html";
}
...
}
Well, it serves my index.html correctly, but the Content-Type is wrong : text/html instead of application/vnd.hbbtv.xhtml+xml.
Furthermore, I don't want to access to myserver.com/hbbtv to get index.html, but directly to myserver.com/index.html.
How could I do that ?
Thanks...
Well, finally, I found the "Spring boot compliant solution". It's the same as Jamie Birch suggested, but realized with Spring mechanisms.
Spring Boot 1:
#Configuration
public class HbbtvMimeMapping implements EmbeddedServletContainerCustomizer {
#Override
public void customize(ConfigurableEmbeddedServletContainer container) {
MimeMappings mappings = new MimeMappings(MimeMappings.DEFAULT);
mappings.add("html", "application/vnd.hbbtv.xhtml+xml; charset=utf-8");
mappings.add("xhtml", "application/vnd.hbbtv.xhtml+xml; charset=utf-8");
container.setMimeMappings(mappings);
}
}
Spring Boot 2:
#Configuration
public class HbbtvMimeMapping implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {
#Override
public void customize(ConfigurableServletWebServerFactory factory) {
MimeMappings mappings = new MimeMappings(MimeMappings.DEFAULT);
mappings.add("html", "application/vnd.hbbtv.xhtml+xml; charset=utf-8");
mappings.add("xhtml", "application/vnd.hbbtv.xhtml+xml; charset=utf-8");
factory.setMimeMappings(mappings);
}
}
I'll extend comment providen by #Cheloute
Sping boot have default mime types
https://github.com/spring-projects/spring-boot/blob/master/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/MimeMappings.java
to override already setted mime type you should remove it first
Here is example what I used to override js and css
#Configuration
public class CustomServletConfiguration implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {
#Override
public void customize(ConfigurableServletWebServerFactory factory) {
MimeMappings mappings = new MimeMappings(MimeMappings.DEFAULT);
mappings.remove("js");
mappings.add("js", "application/javascript;charset=utf-8");
mappings.remove("css");
mappings.add("css", "text/css;charset=utf-8");
factory.setMimeMappings(mappings);
factory.setPort(9000);
}
}
Can't help with the Spring Boot side, but if you get no other responses, try these:
Set the file-type as .xhtml rather than .html.
Provide a mapping from .xhtml to MIME type application/vnd.hbbtv.xhtml+xml on your Jetty server's mime.properties file. A few more details on how to do that here.

Serve static html files omitting the .html extension in the url

With the fine way to serve static html/css/js resources from src/main/resources/static, is there a way to have some form of url abstraction?
Precisely, I would like to remove the .html ending from the urls.
To return html static file without extension is the same as return view name from any of templates engines (jsp, theamleaf, freemarker), the thing here you do not need to run any templates processing on view file, you just return it as it is.
Add code below to your Spring configuration:
#Bean
public InternalResourceViewResolver internalResourceViewResolver() {
InternalResourceViewResolver internalResourceViewResolver = new InternalResourceViewResolver();
internalResourceViewResolver.setPrefix("pages/");
internalResourceViewResolver.setSuffix(".html");
return internalResourceViewResolver;
}
Be careful /pages folder should be inside your ResourceLocation
, that means ResourceLocation + "/pages/" + pageName.html in browser should give you desired file (if you already configured servicing of static files it will not be a problem for you to find your ResourceLocation, check method addResourceHandlers in your WebMvcConfigurer)
Now at your WebMvcConfigurer you can add:
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
registry.addViewController("/admin").setViewName("admin");
registry.addViewController("/contact").setViewName("contact");
registry.addViewController("/error").setViewName("index");
}
or just use it, as you would use it in usual view resolver within MVC controller
#GetMapping("/")
public String greeting() {
return "index";
}
A request mapping that ignores all URLs that have a file extension and adds .html to URLs with no file extension.
#Controller
...
#RequestMapping("/{page:^(?!.*[.].*$).*$}")
public String requestOther(#PathVariable("page") String page) {
return "/"+page+".html";
}
...
Change the "/" to a sub directory if needed e.g. "/pages/".

Resources