Introduction to Spring web applications
last modified July 13, 2020
In this tutorial, we are going to create simple web applications in Spring. Three web applications are created; each of the applications is configured in a different way.
In our Spring web applications, we use Spring 5 and Thymeleaf 3.
Spring is a popular Java application framework. Spring Boot is an effort to create stand-alone, production-grade Spring based applications with minimal effort.
There are three basic approaches to configure a Spring web application:
- XML
- Java Config
- Spring Boot autoconfiguration
Traditionally, Spring has used XML files to configure applications. Later, a new approach was created where the configuration is done in the Java configuration classes. Spring Boot autoconfiguration magic is the latest approach to configure Spring web applications.
Spring web application configuration with XML
In the first example, we create a Spring web application configured in XML files.
pom.mxl src ├───main │ ├───java │ │ └───com │ │ └───zetcode │ │ └───controller │ │ HomeController.java │ ├───resources │ └───webapp │ │ index.html │ └───WEB-INF │ │ spring-servlet.xml │ │ web.xml │ └───templates │ showMessage.html └───test └───java
This is the project structure.
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.zetcode</groupId> <artifactId>springwebfirst</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.25</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>1.7.25</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf-spring5</artifactId> <version>3.0.11.RELEASE</version> </dependency> <dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf</artifactId> <version>3.0.11.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.1.3.RELEASE</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>3.2.2</version> </plugin> </plugins> </build> </project>
This is the Maven build file. We have the following dependencies: slf4j-api
,
and slf4j-simple
for logging, javax.servlet-api
for Java Servlet
technology, thymeleaf-spring5
and thymeleaf
for the Thymeleaf template engine, and spring-webmvc
for creating Spring Web MVC
applications.
The maven-war-plugin
creates web archives (WAR).
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <context:component-scan base-package="com.zetcode"/> <mvc:annotation-driven/> <mvc:default-servlet-handler/> <bean id="templateResolver" class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver"> <property name="prefix" value="/WEB-INF/templates/"/> <property name="suffix" value=".html"/> <property name="templateMode" value="HTML"/> </bean> <bean class="org.thymeleaf.spring5.view.ThymeleafViewResolver"> <property name="templateEngine" ref="templateEngine"/> </bean> <bean id="templateEngine" class="org.thymeleaf.spring5.SpringTemplateEngine"> <property name="templateResolver" ref="templateResolver"/> </bean> </beans>
The spring-servlet.xml
configures the Spring web application.
It enables component scanning, Spring web annotations (@Controller) and configures
the Thymeleaf template.
<context:component-scan base-package="com.zetcode" />
This tells Spring where to look for classes with @Controller
,
@Repository
, @Service
, @Component
annotations and register them. In our case, we have a controller with
the @Controller
annotation.
<mvc:annotation-driven/>
The <mvc:annotation-driven/>
enables web based Spring annotations.
<mvc:default-servlet-handler/>
We need this tag to enable static HTML files. We have one static index.html
for the home page.
<bean id="templateResolver" class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver"> <property name="prefix" value="/WEB-INF/templates/"/> <property name="suffix" value=".html"/> <property name="templateMode" value="HTML"/> </bean> <bean class="org.thymeleaf.spring5.view.ThymeleafViewResolver"> <property name="templateEngine" ref="templateEngine"/> </bean> <bean id="templateEngine" class="org.thymeleaf.spring5.SpringTemplateEngine"> <property name="templateResolver" ref="templateResolver"/> </bean>
These lines configure Thymeleaf with a template engine, template view resolver, and a template resolver. In the template resolver we specify where the templates are located and their extensions.
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list> <servlet> <servlet-name>spring</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>spring</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <session-config> <session-timeout> 30 </session-timeout> </session-config> </web-app>
In the web.xml
file, we set up the Spring DispatcherServlet
and
choose the welcome file. The DispatcherServlet
is the Spring's front controller.
The servlet is mapped to the URL having *.html
extension.
package com.zetcode.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; @Controller public class HomeController { @GetMapping("/message") public String message() { return "showMessage"; } }
HTTP requests are handled by a controller. It prepares a model and returns a view.
The returned showMessage
string is mapped to the showMessage.html
file located in the WEB-INF/templates/
directory.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Message</title> </head> <body> <p> Hello there </p> </body> </html>
The showMessage.html
file displays a message.
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Home page</title> </head> <body> <p> <a href="message">Show message</a> </p> </body> </html>
The index.html
is a home page. It contains a link.
Spring web application configuration with Java config
In the second example, we create a Spring web application configured in Java
config classes. In this example, web.xml
and spring-servlet.xml
are replaced with MyWebInitializer.java
and WebConfig.java
.
pom.xml src ├───main │ ├───java │ │ └───com │ │ └───zetcode │ │ ├───config │ │ │ MyWebInitializer.java │ │ │ WebConfig.java │ │ └───controller │ │ MyController.java │ ├───resources │ └───webapp │ └───WEB-INF │ └───templates │ index.html │ showMessage.html └───test └───java
This is the project structure. The pom.xml
file is the same
as in the first example.
package com.zetcode.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.ViewResolverRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.thymeleaf.spring5.SpringTemplateEngine; import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver; import org.thymeleaf.spring5.view.ThymeleafViewResolver; @Configuration @EnableWebMvc @ComponentScan(basePackages = {"com.zetcode"}) public class WebConfig implements WebMvcConfigurer { @Autowired private ApplicationContext applicationContext; @Bean public SpringResourceTemplateResolver templateResolver() { var templateResolver = new SpringResourceTemplateResolver(); templateResolver.setApplicationContext(applicationContext); templateResolver.setPrefix("/WEB-INF/templates/"); templateResolver.setSuffix(".html"); return templateResolver; } @Bean public SpringTemplateEngine templateEngine() { var templateEngine = new SpringTemplateEngine(); templateEngine.setTemplateResolver(templateResolver()); templateEngine.setEnableSpringELCompiler(true); return templateEngine; } @Bean public ViewResolver viewResolver() { var resolver = new ThymeleafViewResolver(); var registry = new ViewResolverRegistry(null, applicationContext); resolver.setTemplateEngine(templateEngine()); registry.viewResolver(resolver); return resolver; } }
The WebConfig.java
is used instead of the spring-servlet.xml
file.
In the WebConfig
, we enable Spring web annotations with @EnableWebMvc
,
enable component scanning with @ComponentScan
and configure the Thymeleaf template engine.
package com.zetcode.config; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; public class MyWebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { return null; } @Override protected Class<?>[] getServletConfigClasses() { return new Class[]{WebConfig.class}; } @Override protected String[] getServletMappings() { return new String[]{"/"}; } }
The MyWebInitializer
class is used instead of the web.xml
file.
We specify the name of the servlet configuration class.
package com.zetcode.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; @Controller public class MyController { @GetMapping("/") public String index() { return "index"; } @GetMapping("/message") public String message() { return "showMessage"; } }
This is the controller. We have mappings for the home page and for a showMessage page.
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Message</title> </head> <body> <p>Today is a sunny day!</p> </body> </html>
The showMessage.html
file displays a message.
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Home page</title> </head> <body> <p> <a href="message.html">Show message</a> </p> </body> </html>
The index.html
is a home page. It contains a link.
Spring Boot web application
In the third example, we create a web application with Spring Boot. Spring Boot uses a different default approach. It uses JAR archives with an embedded web server.
pom.xml src ├───main │ ├───java │ │ └───com │ │ └───zetcode │ │ │ Application.java │ │ └───controller │ │ MyController.java │ └───resources │ │ application.properties │ ├───static │ │ index.html │ └───templates │ showMessage.html └───test └───java
This is the project structure.
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.zetcode</groupId> <artifactId>springbootwebfirst</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> </properties> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.0.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
This is the Maven build file. The spring-boot-starter-web
is a starter POM
for building web, including RESTful, applications using Spring MVC.
The spring-boot-starter-thymeleaf
is a starter POM for Thymeleaf template
engine.
Note that the packaging is set to JAR.
package com.zetcode.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; @Controller public class MyController { @GetMapping("/message") public String message() { return "showMessage"; } }
This is the controller class for the Spring Boot web application. A controller is decorated with
the @Controller
annotation. The controller has one mapping. The mapping resolves
to the showMessage.html
template, which is located in the
WEB-INF/templates
directory.
package com.zetcode; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
The Application
sets up the Spring Boot application.
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Message</title> </head> <body> <p>Today is a cold day</p> </body> </html>
The showMessage.html
shows a simple message.
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Home page</title> </head> <body> <p> <a href="message">Show message</a> </p> </body> </html>
The index.html
is the home page of the application containing
a link. Static resources such as plain HTML files are put into static
directory.
In this tutorial, we have created our first Spring web application.