Click here to Skip to main content
15,867,834 members
Articles / Web Development / Spring

Spring Boot Web Application Development using JSTL Template

Rate me:
Please Sign up or sign in to vote.
0.00/5 (No votes)
22 Oct 2019MIT11 min read 15.4K   157  
This tutorial discusses the way to setup a Spring boot application that can utilize JSTL template and taglib.

Introduction

Today's technologies are all interchangeable. That is, an idea that can be implemented in one set of technology, can also be implemented in another set of technologies. With ASP.NET MVC, the view of a page can be created with a common layout, and one or more templates, and partial views. On Java side, you can do exactly the same thing. In fact, there are multiple ways to do this. One is Apache Tiles framework; one is the Thymeleaf framework; and the other is using JSTL TagLib framework. In terms of how to use it, they are all pretty similar. The biggest difference is the syntax difference.

For this tutorial, I will be discussing the way of setting up a Spring Boot based MVC web application and using JSTL template and TagLib to create reusable JSP view template, then piece three different pages together using the template and reusable view pieces. Why JSTL and TagLib? There is no good reason. I used it in my last project. I was also able to integrate it into this tutorial pretty easily. So I decided to write about it.

The POM File

The sample application for this is created based on my previous tutorial called Creating MVC Web Application using Spring Boot with JSP and WAR Archive. In this previous tutorial, I discussed the way of creating the Spring Boot application as a WAR archive. The tutorial didn't go beyond the default setup of having the sub folder of static in the resources folder to host all the static content files. This tutorial goes one step further (or one step backwards, JSTL and TagLib are old technologies). Instead of using the static sub folder to host the static web resources, I will move the static contents to the webapp folder, and using JstlView class to render the final HTML view. This is all one needed to do on the coding side.

POM File

I took the same POM file I used in my previous tutorial and did not change a thing. It is used for building a Spring Boot MVC application:

XML
<?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>

	<artifactId>boot-jstl-war</artifactId>
	<packaging>war</packaging>
	<name>Hanbo Boot JSTL War Sample App</name>
	<description>An example of Spring Boot, JSP and WAR</description>
	<version>1.0.0</version>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.5.RELEASE</version>
	</parent>

	<properties>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-tomcat</artifactId>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
		</dependency>
		<dependency>
			<groupId>org.apache.tomcat.embed</groupId>
			<artifactId>tomcat-embed-jasper</artifactId>
			<scope>provided</scope>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>

I included JSTL as dependency in my POM project. Not sure if I needed to do it, but included just in case. Anyways, with this POM file, I can build the project, create a WAR archive. Then I can run the WAR archive on the command line.

The Web Configuration Class

One cool thing about Spring Boot is that you can build an application with minimum amount of configuration. This means a developer will be working with default settings. In my previous tutorial, I have to put static contents in the static sub folder in the resources folder. In order to use the JSTL templates and TagLib, I need to override the default configuration. Here is the new configuration class I have added to the project:

Java
package org.hanbo.boot.app.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;

@EnableWebMvc
@Configuration
public class WebConfig implements WebMvcConfigurer
{
   @Value("${web.assets.pattern}")
   private String assetsPattern;

   @Value("${web.assets.directory}")
   private String assetsDirectory;
   
   @Value("${web.jsp.filePrefix}")
   private String jspFilePrefix;
   
   @Value("${web.jsp.fileSuffix}")
   private String jspFileSuffix;

   @Override
   public void addResourceHandlers(ResourceHandlerRegistry registry)
   {
       registry
         .addResourceHandler(assetsPattern)
         .addResourceLocations(assetsDirectory);
   }
   
   @Bean
   public InternalResourceViewResolver viewResolver()
   {
      InternalResourceViewResolver viewResolver 
                         = new InternalResourceViewResolver();
      viewResolver.setViewClass(JstlView.class);
      viewResolver.setPrefix(jspFilePrefix);
      viewResolver.setSuffix(jspFileSuffix);
      
      return viewResolver;
   }
}

Here are some important points about this class:

  • The class implements WebMvcConfigurer interface. It used to implement a different interface. That interface is obsolete. This is the new one to be implemented.
  • By implementing the WebMvcConfigurer interface, it gives me two methods:
    • One is called addResourceHandlers which allows me to specify where the static resources should be.
    • The other one is called viewResolver. This specifies what the view resolver will be and what the prefix and suffix of files which are the page templates.
  • I inject individual property value from the "application.properties".
  • I annotate the class with two annotations, indicates the class is used for configuration.

You can find all the injected properties in file resource/application.properties.

Based on the above information, here is how you can find the static resources, like *.css, or *.js files. And the jsp/tag/jspf files:

  • The CSS files can be found in the sub folders in webapp/assets/
  • The JSP files can be found in webapp/WEB-INF/jsp/ folder.
  • The tag files can be found in webapp/WEB-INF/tags/ folder.

This is the easiest part. The next concept, how to create JSTL template and reusable HTML components, will be a little harder. In the next section, I will discuss how these can be done.

JSTL Templates and Components

Before I dig into the good stuff, here is a general overview of the way in which JSTL, taglib and JSPF work. First, I need to create a page template. The page template is a JSP page with a lot of place holders. The place holders are places where reusable pieces can be fitted into. The template file is named "<tempateName>.tag".

The reusable JSP components are just pieces of JSP or HTML code snippets. Each is defined in its own file. In the JSTL template file, these components can be included with specific tags. And additional pieces can be defined in target JSP files. The way JSTL view works is that JstlView uses the target JSP to find the template file. In the template file, first grab all the tagged reusable components from all the JSPF files; and add additional components defined in the target JSP files into a final JSP file. Then the tags in the final JPS file will be dynamically replaced with real values. At last, it will be sent to the client end. The JavaScript on the pages will be activated at the client end.

The target JSP file is not like the JSP files. It is more like a XML file that specifies what the JSTL template to be used; what would be the content of the JSP body; and the HTML contents of the missing components in the template (which hasn't been filled). All these will create a JSP page that can be filled with the actual value. When the MVC controller calls and returns a ModelAndView object, the data inside will be used to dynamically create the final page.

The JSTL Template Page

In my sample project, I have a file in sub folder webapp/WEB-INF/tags, called "pageTemplate.tag". The content of this file looks like this:

HTML
<%@tag description="Overall Page template" pageEncoding="UTF-8"%>
<%@attribute name="additionalCss" fragment="true" %>
<%@attribute name="additionalJs" fragment="true" %>

<!DOCTYPE HTML>

<html>
   <head>
      <%@ include file="htmlHead.jspf" %>
   </head>
   
   <body class="subpage">
      <%@ include file="header.jspf" %>

      <section class="wrapper">
         <div class="inner">
            <jsp:doBody/>
         </div>
      </section>
         
      <%@ include file="footer.jspf" %>
      
      <%@ include file="jsFooter.jspf" %>
   </body>
</html>

If you look at this file, you can see it is like a rough draft of a HTML page. It is incomplete. Many places are just place holder. On the very top, you see this:

HTML
<%@tag description="Overall Page template" pageEncoding="UTF-8"%>
<%@attribute name="additionalCss" fragment="true" %>
<%@attribute name="additionalJs" fragment="true" %>

The second and third lines define two places that can be added later by the JstlView object. Then, there are four places where you can see this:

HTML
...
      <%@ include file="htmlHead.jspf" %>
...
      <%@ include file="header.jspf" %>

...
      <%@ include file="footer.jspf" %>
      
      <%@ include file="jsFooter.jspf" %>
...

These four places are importing the HTML snippet defined in the JSPF files into this template. This is how reusable HTML/JSP components can be used in multiple target JSP files. Pretty neat, isn't it?

And in the middle of this template, I have defined this:

jsp
<section class="wrapper">
   <div class="inner">
      <jsp:doBody/>
   </div>
</section>

This is where I would render the page specific html/jsp component in the target JSP file. Before we get to the target JSP file, let's take a look at the reusable HTML/JSP components defined in the JSPF files.

The JSPF Components

These four places define where to fetch the reusable components. Those four are taking the jspf files in the same folder where the tag file (JSTL template file) is, and use to fill these places. Here is one of the jspf file, "header.jspf":

jsp
<header id="header">
   <div class="inner">
      <a href="${pageContext.request.contextPath}/" class="logo">
          <strong>Spring Boot</strong> JSTL Template</a>
      <nav id="nav">
         <a href="${pageContext.request.contextPath}/">Home</a>
         <a href="${pageContext.request.contextPath}/posts">Posts</a>
         <a href="${pageContext.request.contextPath}/updates">Updates</a>
      </nav>
      <a href="#navPanel" class="navPanelToggle"><span class="fa fa-bars"></span></a>
   </div>
</header>

The code snippet above will replace the tag where the file is referenced. And the JSP code segments in the JSPF will be dynamically replaced with real value in later stage of JSP to HTML rendering.

Template file and the reusable components are not enough. The last piece to get the whole setup to work is to have a target JSP page that will specify how these thing can be put together. How this target JSP file works will be discussed next.

The Final JSP Page

In order to demonstrate the reusable-ness of the template and jsp/html components defined with JSPF files, I have created three different actions in my test MVC controller. Each will display a page that looks different but uses the same template and the components.

Here is a JSP file that will demonstrate how the final JSP page works with JstlView object, here is the content of this JSP page:

jsp
<%@page contentType="text/html" trimDirectiveWhitespaces="true" pageEncoding="UTF-8"%>
<%@taglib prefix="t" tagdir="/WEB-INF/tags" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%>

<t:pageTemplate>
   <jsp:attribute name="additionalCss">
   </jsp:attribute>
   <jsp:attribute name="additionalJs">
   </jsp:attribute>
   <jsp:body>
      <article class="12u$(large)">
         <header class="align-left">
            <h3>Senor Philip</h3>
            <p>Last updated on 10/10/2019 - By HanBo</p>
         </header>
         <div class="row">
            <section class="12u$(large)">
               <p>Reference from <a href="https://www.wikipedia.org">Wikipedia</a>.
               <p>Philip relied on skillful civil servants, 
               such as Guillaume de Nogaret and Enguerrand de Marigny, 
               to govern the kingdom rather than on his nobles. 
               Philip and his advisors were instrumental in the transformation 
               of France from a feudal country to a centralized state. 
               The king, who sought an uncontested monarchy, 
               compelled his vassals by wars and restricted feudal usages. 
               His ambitions made him highly influential in European affairs. 
               His goal was to place his relatives on foreign thrones. 
               Princes from his house ruled in Naples and Hungary. 
               He tried and failed to make another relative the Holy Roman Emperor. 
               He began the long advance of France eastward by 
               taking control of scattered fiefs.</p>
            </section>
         </div>
      </article> 
      <article class="12u$(large)">
         <header class="align-left">
            <h3>Senor Philip Takes the World</h3>
            <p>Last updated on 10/08/2019 - By HanBo</p>
         </header>
         <div class="row">
            <section class="12u$(large)">
               <p>Reference from <a href="https://www.wikipedia.org">Wikipedia</a>.
               <p>The constant deficits led Philip to order the arrest of the Lombard merchants, 
               who had earlier made him extensive loans on the 
               pledge of repayment from future taxation.
               The Lombards' assets were seized by government agents and the crown 
               extracted 250,000 LT by forcing the Lombards to purchase French nationality. 
               Despite this draconian measure, the deficits continued to stack up in 1293. 
               By 1295, Philip had replaced the Templars with the Florentine Franzesi bankers 
               as his main source of finance. The Italians could raise huge loans far beyond 
               the capacities of the Templars, and Philip came to rely on them more and more. 
               The royal treasure was transferred from the Paris Temple 
               to the Louvre around this time.</p>
            </section>
         </div>
      </article> 
   </jsp:body>
</t:pageTemplate>

The top part of this JSP page, are all the jstl tags that I can use later in the subsequent rendering of the JSP content. The most important one is this one:

jsp
...
<%@taglib prefix="t" tagdir="/WEB-INF/tags" %>
...

This will import the taglig namespace into this target JSP page, and enable me to specify the page template I can use. The name of the page template would be the file name of the tag file, in this case, it is "pageTemplate.tag". The attribute tagdir defines the folder where JstlView can find the template file. Here is the code that specifies the template to be used:

jsp
...
<t:pageTemplate>
...
</t:pageTemplate>

Remember this in the tag file?

jsp
<section class="wrapper">
   <div class="inner">
      <jsp:doBody/>
   </div>
</section>

How do we supply the body content for this <jsp:doBody/>? Here, it is defined in the target JSP file:

jsp
<jsp:body>
   <article class="12u$(large)">
      <header class="align-left">
         <h3>Senor Philip</h3>
         <p>Last updated on 10/10/2019 - By HanBo</p>
      </header>
      <div class="row">
         <section class="12u$(large)">
            <p>Reference from <a href="https://www.wikipedia.org">Wikipedia</a>.
            <p>Philip relied on skillful civil servants,
            such as Guillaume de Nogaret and Enguerrand de Marigny,
            to govern the kingdom rather than on his nobles.
            Philip and his advisors were instrumental in the
            transformation of France from a feudal country to a centralized state.
            The king, who sought an uncontested monarchy, compelled his vassals
            by wars and restricted feudal usages. His ambitions made him
            highly influential in European affairs. His goal was to place
            his relatives on foreign thrones. Princes from his house ruled
            in Naples and Hungary. He tried and failed to make another relative
            the Holy Roman Emperor. He began the long advance of France
            eastward by taking control of scattered fiefs.</p>
         </section>
      </div>
   </article>
   <article class="12u$(large)">
      <header class="align-left">
         <h3>Senor Philip Takes the World</h3>
         <p>Last updated on 10/08/2019 - By HanBo</p>
      </header>
      <div class="row">
         <section class="12u$(large)">
            <p>Reference from <a href="https://www.wikipedia.org">Wikipedia</a>.
            <p>The constant deficits led Philip to order the arrest
            of the Lombard merchants, who had earlier made him extensive
            loans on the pledge of repayment from future taxation.
            The Lombards' assets were seized by government agents
            and the crown extracted 250,000 LT by forcing the Lombards
            to purchase French nationality. Despite this draconian measure,
            the deficits continued to stack up in 1293. By 1295,
            Philip had replaced the Templars with the Florentine Franzesi bankers
            as his main source of finance. The Italians could raise huge loans
            far beyond the capacities of the Templars, and Philip came to rely
            on them more and more. The royal treasure was transferred from the
            Paris Temple to the Louvre around this time.</p>
         </section>
      </div>
   </article>
</jsp:body>

The above <jsp:body>...<jsp:body> will replace the <jsp:doBody> section.

Also, in this same target JSP file, I have these in it:

jsp
<jsp:attribute name="additionalCss">
</jsp:attribute>
<jsp:attribute name="additionalJs">
</jsp:attribute>

The above section means not adding anything new when rendering the final JSP page for this place holder section for this target JSP file. In a different target JSP file, called "WEB-INF/jsp/updates.jsp", I have this which defines additional CSS files and JS files to be included:

jsp
<jsp:attribute name="additionalCss">
   <link rel="stylesheet" href="${pageContext.request.contextPath}/assets/css/mystyle.css" />
</jsp:attribute>
<jsp:attribute name="additionalJs">
   <script src="${pageContext.request.contextPath}/assets/js/myscript.sj"></script>
</jsp:attribute>

Next, all we need are a controller and action methods to bring these pages to live, which will be discussed in the following section.

MVC Controller

MVC controller for this sample application looks the same as in my previous tutorial. That is, there is no special coding needed. Just a super brief explanation on how MVC works with Spring MVC framework. First, we define a class and annotate the class with annotation @Controller. We can either add @RequestMapping to the class or add it to the method. @RequestMapping annotation is used to specify the HTTP routing, so that request (specified by URL and HTTP method) can be handled by the right class and the specific method in the class.

Inside the method that handles the request, usually, I use ModelAndView as the return object. This unique class will specify a view page and a set of data models that can be used to render the page. Behind the scene, since we are using the JstlView object for the rendering, it will take the JSP page, find the master template, and render all the place holders with reusable components, and finally use the data models to create the final page. Here is the whole controller class:

Java
package org.hanbo.boot.app.controllers;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class IndexController
{
   @RequestMapping(value = "/", method = RequestMethod.GET)
   public ModelAndView index()
   {
      ModelAndView retVal = new ModelAndView();
      retVal.setViewName("index");
      return retVal;
   }

   @RequestMapping(value = "/posts", method = RequestMethod.GET)
   public ModelAndView posts()
   {
      ModelAndView retVal = new ModelAndView();
      retVal.setViewName("posts");
      return retVal;
   }
   
   @RequestMapping(value = "/updates", method = RequestMethod.GET)
   public ModelAndView updates()
   {
      ModelAndView retVal = new ModelAndView();
      retVal.setViewName("updates");
      return retVal;
   }
}

As seen, in this class, there are three methods. Each of the methods will render a page. The URLs for these three methods are:

  • http://localhost:8080/ - The index page
  • http://localhost:8080/posts - The page that lists three posts
  • http://localhost:8080/updates - The page that lists two updates

All the pages are populated with dummy data, but they do use the same master template, and all the same components.

How to Run Sample Application

To build the sample application, execute the following command on the command line:

mvn clean install

The command will download all the dependencies, compile the source code, and package the application as a war archive.

To import the project into the Eclipse, run the following command on the command line:

mvn eclipse:eclipse

Finally, to run the application, execute the following command on the command line:

java -jar target\boot-jstl-war-1.0.0.war

Then try the three URLs, each should display a different page. The index page should display as the following:

Image 1

On the index page, there are links to the other two pages, look for them at the upper left corner of the page. The second page is the "posts" page, here is an screenshot:

Image 2

Finally, the "updates" page looks like this:

Image 3

Summary

This tutorial discusses the way of creating a Spring Boot based MVC web application that utilizes JSTL template and taglib components. In the tutorial, I have discussed the following:

  • The POM file configuration needed for the application, for build and packaging.
  • The application configuration for setting up the JstlView, the folders for the page template, and for the static resources.
  • The JSP page template, the place holders in the template, reusable HTML/JSP components and how to import them into the template, the definition of the target JSP page, the MVC controller, and the action methods for rendering the pages.
  • How to build and run the sample application.

This is the last tutorial that I wrote for 2019. Not my best work, but I had to document it because it is useful. When one works with MVC framework, reusable templates are always useful. It is always a good practice to slice a page into different components, and fit them for different page display. The downside to this is that when this is misused, the target JSP page can be very hard to understand. Regardless, I choose this approach because it helps avoid duplicating HTML codes within multiple pages. Hence, it makes these HTML code snippets reusable.

Credits where credits are due. For this tutorial, I used the page template from the web site templated.co. The template I used is called "Projection".

History

  • 10/20/2019 - Initial draft

License

This article, along with any associated source code and files, is licensed under The MIT License


Written By
Team Leader The Judge Group
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
-- There are no messages in this forum --