Learn to create and configure JSP view resolver in Spring Boot 3 application which uses JSP template files to render the view layer. Also, learn to build and deploy the application and serve static content in the JSP files.
1. Project Structure
For reference, the files in this application are placed as the given structure in the image.

2. Maven
To sever an application using JSP, we need the following dependencies. Note that we are using the Jakarta Servlet API which uses the Jakarta namespace required by Spring Boot 3.
- spring-boot-starter-web
- tomcat-embed-jasper
- jakarta.servlet.jsp.jstl-api
- jakarta.servlet.jsp.jstl
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jakarta.servlet.jsp.jstl</groupId>
<artifactId>jakarta.servlet.jsp.jstl-api</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>jakarta.servlet.jsp.jstl</artifactId>
<version>3.0.1</version>
</dependency>
Additionally, we must use the war packaging as jar packaging is not supported as discussed in the official documentation.
<packaging>war</packaging>
3. Application Setup
3.1. Extend SpringBootServletInitializer in the Application Class
The first step in producing a deployable war file is to provide a SpringBootServletInitializer
subclass and override its configure()
method. This makes use of Spring Framework’s Servlet 3.0 support and allows you to configure the application when it is launched by the Servlet container.
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
@SpringBootApplication
public class App extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(App.class);
}
public static void main(String[] args) {
SpringApplication.run(App.class);
}
}
3.2. Web Controller
The controller class is a regular @Controller class with request mapping annotations. Please note that we should not use the @RestController annotation, by mistake.
@Controller
public class ItemController {
@Autowired
ItemService itemService;
@RequestMapping("/view-items")
public ModelAndView viewBooks(ModelAndView model) {
model.setViewName("view-items");
model.addObject("items", itemService.getAll());
return model;
}
}
3.3. Model and Service
For reference, we are using a simple POJO Item as model and ItemService for returning a list of items. The service returns two items. In a real application, it will connect to the database and fetch the details from the database or any other source.
@Service
public class ItemService {
public List<Item> getAll() {
return List.of(new Item(1L, "Item - 1"), new Item(2L, "Item - 2"));
}
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Item {
private Long id;
private String name;
}
4. Setting up JSP View Resolver
To resolve JSP files location and automatically configure the JSP view resolver, we can have two approaches:
4.1. Using application.properties
The following properties automatically configure the Spring MVC to serve the content from the configured location and register the JstlView class. It is a specialization of InternalResourceView for JSTL pages, i.e. JSP pages.
Once registered, every view name returned from a handler will be translated to a JSP resource (for example: “home” → “/WEB-INF/jsp/home.jsp“), using this view class to enable explicit JSTL support.
spring.mvc.view.prefix=/WEB-INF/view/
spring.mvc.view.suffix=.jsp
4.2. Using Java Configuration
We can configure the JSP view resolution in the Java configuration also, as follows. Do not forget to use the @EnableWebMvc which configures the other necessary beans to support a MVC application.
@Configuration
@EnableWebMvc
public class WebMvcConfig implements WebMvcConfigurer {
@Bean
public ViewResolver viewResolver() {
final InternalResourceViewResolver bean = new InternalResourceViewResolver();
bean.setViewClass(JstlView.class);
bean.setPrefix("/WEB-INF/jsp/");
bean.setSuffix(".jsp");
return bean;
}
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.viewResolver(viewResolver());
}
}
4.3. Serving Static Content
By default, Spring MVC serves the static files (JS, CSS etc) from the following directories:
- /src/main/resources
- /src/main/resources/static
We can configure the custom URI and directory location as follows. The following configuration will serve a file http://localhost:8080/static/css/style.css from the location /src/main/resources/static/css/style.css.
@Configuration
@EnableWebMvc
public class WebMvcConfig implements WebMvcConfigurer {
//...
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/static/**")
.addResourceLocations("classpath:/static/")
.setCachePeriod(3600)
.resourceChain(true)
.addResolver(new PathResourceResolver());
}
}
5. JSP Files
The JSP files can be placed in /webapp/WEB-INF/jsp
directory as /WEB-INF/jsp
path has been configured with the view resolver. Add the webapp directory as the resources root so its content is copied to the root directory when building the project.
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
<title>View Items</title>
<link href="/static/css/style.css" rel="stylesheet">
</head>
<body>
<table>
<thead>
<tr>
<th>Id</th>
<th>Name</th>
</tr>
</thead>
<tbody>
<c:forEach items="${items}" var="item">
<tr>
<td>${item.id}</td>
<td>${item.name}</td>
</tr>
</c:forEach>
</tbody>
</table>
</body>
</html>
6. Package and Run the Application
After the code has been created, we can package the application from the terminal:
mvc clean install
It will create a war file in the target directory. We can run the war file in two ways:
- Using the
java -jar
command from the terminal. - Deploying in the Tomcat application server.
To run the application from the terminal, run the following command:
java -jar .\target\jsp-demo-1.0-SNAPSHOT.war
It will start the embedded Tomcat server and deploy the application with it.
7. Demo
After the application has been deployed, we can access a valid application URL in the browser and the JSP page will be rendered in the browser.

8. FAQs
8.1. Views are not resolved with 404 Error
In most cases, this error indicates that you are trying to run the application as embedded jar deployment or you are not using the java-jar command to run the application.
To fix this issue, you must run the application with java-jar command or deploy it inside a Tomcat server.
java -jar .\target\jsp-demo-1.0-SNAPSHOT.war
8.2. ClassNotFoundException: jakarta.servlet.jsp.jstl.core.Config
This error indicates that you are still using the javax.servlet:jstl
dependency. With the latest Spring Boot release, we must use the Jakarta namespaces so add the following dependency.
<!-- Remove javax packages -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- Add jakarta packages -->
<dependency>
<groupId>jakarta.servlet.jsp.jstl</groupId>
<artifactId>jakarta.servlet.jsp.jstl-api</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>jakarta.servlet.jsp.jstl</artifactId>
<version>3.0.1</version>
</dependency>
9. Conclusion
In this Spring Boot JSP example, we learned to serve the JSP pages in a Spring boot 3 application, configure the view resolution, and serve static content with a demo. We also learned to fix some common mistakes that developers make when serving the JSP page.
Happy Learning !!
Comments