2.3. First application based on Spring MVC¶
Caution
This version is already obsolete. Please check the latest guideline.
Index
Before entering into the advanced usage of Spring MVC, it is better to understand Spring MVC by actually trying handson web application development using Spring MVC. This purpose of this chapter to understand the overall picture. Note that it does not follow the recommendations given from the next chapter onwards. (for the ease of understanding).
2.3.1. Prerequisites¶
The description of this chapter has been verified on the following environment. (For other environments, replace the contents mentioned here appropriately)
Product | Version |
---|---|
JDK | 1.6.0_33 |
Spring Tool Suite (STS) | 3.2.0 |
VMware vFabric tc Server Developer Edition | 2.8 |
Fire Fox | 21.0 |
Note
To connect to the internet via a proxy server, STS Proxy settings and Maven Proxy settings are required for the following operations.
Warning
“Spring Template Project” used in this chapter has been removed from Spiring Tool Suite 3.4; hence, the contents of this chapter can only be confirmed on “Spring Tool Suite 3.3” or before.
Refer to [coming soon] Create Project from Blank Project in case using Spring Tool Suite 3.4.
We plan to update the contents of this chapter in future.
2.3.2. Create a New Project¶
From the menu of SpringSource Tool Suite, select [File] -> [New] -> [Spring Template Project] -> [Spring MVC Project] -> [Next], and create Spring MVC project.
Note
If proxy server is being used, there is a possibility of not being able to select Spring Template Project. In order to resolve this, do the following.
- First select [window] -> [Preferences] -> [Spring] -> [Template Projects] and remove all items except “spring-defaults”.
- Then click Apply.
- After this, when [File] -> [New] -> [Spring Project] is clicked, [Spring MVC Project] can be selected from Templetes.
Enter “helloworld” in [Project Name], “com.example.helloworld” in [Please specify the top-level package] and click [Finish] on the next screen.
Following project is generated in the Package Explorer (Internet access is required)
The generated configuration file (src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml) of Spring MVC is described briefly to understand the configuration of Spring MVC.
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
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">
<!-- DispatcherServlet Context: defines this servlet's request-processing
infrastructure -->
<!-- (1) Enables the Spring MVC @Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving
up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- (2) Resolves views selected for rendering by @Controllers to .jsp resources
in the /WEB-INF/views directory -->
<beans:bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<!-- (3) -->
<context:component-scan base-package="com.example.helloworld" />
</beans:beans>
Item number | Description |
---|---|
(1)
|
Default settings of Spring MVC are configured by defining <annotation-driven />. Refer to the official website Enabling the MVC Java Config or the MVC XML Namespace of Spring framework for default configuration. |
(2)
|
Define the location of View by specifying Resolver of View. |
(3)
|
Define the package which will be target of searching components used in Spring MVC. |
Following is the com.example.helloworld.HomeController
(However, it is modified to simple form for explanation).
package com.example.helloworld;
import java.util.Date;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
/**
* Handles requests for the application home page.
*/
@Controller// (1)
public class HomeController {
private static final Logger logger = LoggerFactory
.getLogger(HomeController.class);
/**
* Simply selects the home view to render by returning its name.
*/
@RequestMapping(value = "/", method = RequestMethod.GET) // (2)
public String home(Model model) { // (3)
logger.info("Welcome home!");
Date date = new Date();
model.addAttribute("serverTime", date);
return "home"; // (4)
}
}
It is explained briefly.
Item number | Description |
---|---|
(1)
|
It can be read automatically by DI container if @Controller annotation is used. As stated earlier in “explanation of Spring MVC configuration files (3)”, it is the target of component-scan. |
(2)
|
It gets executed when the HTTP method is GET and when the Resource is (or request URL) is “/”. |
(3)
|
Set objects to be delivered to View. |
(4)
|
Return View name. Rendering is performed by WEB-INF/views/home.jsp as per the configuration in “Explanation of Spring MVC configuration files (2)”. |
The object set in Model is set in HttpServletRequest.
The value passed from Controller can be output by mentioning ${serverTime}
in home.jsp as shown below.
( However, as described below, it is necessary to perform HTML escaping since there is possibility of ${XXX} becoming a target of XSS )
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
<title>Home</title>
</head>
<body>
<h1>
Hello world!
</h1>
<P> The time on the server is ${serverTime}. </P>
</body>
</html>
2.3.3. Run on Server¶
Right click “helloworld” project in STS, and start helloworld project by executing “Run As” -> “Run On Server” -> “localhost” -> “VMware vFabric tc Server Developer Edition v2.8” -> “Finish”. Enter “http://localhost:8080/helloworld/” in browser to display the following screen.
2.3.4. Create an Echo Application¶
Lets go ahead and reate a simple application. It is a typical eco application in which message will be displayed if name is entered in the text field as given below.
2.3.4.1. Creating a form object¶
First create a form object to accept the value of text field. Create EchoForm
class in com.example.helloworld.echo
package.
It is a simple JavaBean that has only 1 property.
package com.example.helloworld.echo;
import java.io.Serializable;
public class EchoForm implements Serializable {
private static final long serialVersionUID = 2557725707095364445L;
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
2.3.4.2. Create a Controller¶
Next, create the Controller class. create the EchoController
class in “com.example.helloworld.echo” package.
package com.example.helloworld.echo;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("echo")
public class EchoController {
@ModelAttribute // (1)
public EchoForm setUpEchoForm() {
EchoForm form = new EchoForm();
return form;
}
@RequestMapping // (2)
public String index(Model model) {
return "echo/index"; // (4)
}
@RequestMapping("hello") // (5)
public String hello(EchoForm form, Model model) {// (3)
model.addAttribute("name", form.getName()); // (6)
return "echo/hello";
}
}
Item number | Description |
---|---|
(1)
|
Add
@ModelAttribute annotation to the method. Return value of such a method is automatically added to the Model.Attribute name can be specified in
@ModelAttribute , but the class name with the first letter in lower case is the default attribute name.In this case it will be
echoForm . This attribute name must match with the value of modelAttribute of form:form tag. |
(2)
|
When nothing is specified in
value attribute of @RequestMapping annotation at the method level, it is mapped to @RequestMapping added at class level.In this case,
index method is called, if <contextPath>/echo is accessed. When nothing is set in method attribute, mapping is done for any HTTP method. |
(3)
|
EchoForm object added to the model in (1) is passed as argument.
|
(4)
|
Since
echo/index is returned as View name, WEB-INF/views/echo/index.jsp is rendered by ViewResolver. |
(5)
|
Since
hello is specified in @RequestMapping annotation at method level, if <contextPath>/echo/hello is accessed, hello method is called. |
(6)
|
name entered in form is passed as it is to the View. |
2.3.4.3. Create JSP Files¶
Finally create JSP of input screen and output screen. Each file path must match with View name as follows.
- Input Screen src/main/webapp/WEB-INF/views/echo/index.jsp
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<!DOCTYPE html>
<html>
<head>
<title>Echo Application</title>
</head>
<body>
<!-- (1) -->
<form:form modelAttribute="echoForm" action="${pageContext.request.contextPath}/echo/hello">
<form:label path="name">Input Your Name:</form:label>
<form:input path="name" />
<input type="submit" />
</form:form>
</body>
</html>
Item number | Description |
---|---|
(1)
|
HTML form is constructed by using tag library. Specify the name of form object created by Controller in
modelAttribute .Refer herefor tag library.
|
The generated HTML is as follows
<body>
<form id="echoForm" action="/helloworld/echo/hello" method="post">
<label for="name">Input Your Name:</label>
<input id="name" name="name" type="text" value=""/>
<input type="submit" />
</form>
</body>
</html>
- Output Screen src/main/webapp/WEB-INF/views/echo/hello.jsp
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<!DOCTYPE html>
<html>
<head>
<title>Echo Application</title>
</head>
<body>
<p>
Hello <c:out value="${name}" />!
</p>
</body>
</html>
Output name
passed from Controller. Take countermeasures for XSS using c:out
tag.
Note
Countermeasure for XSS are taken using c:out
standard tag here. However, f:h()
function that can be used easily is provided in common library.
Refer to XSS Countermeasures for details.
Implementation of Eco application is completed here. Start the server, access the link http://localhost:8080/helloworld/echo
to access the application.
2.3.4.4. Implement Input Validation¶
Input validation is not performed in this application till this point. In Spring MVC, Bean Validation (JSR-303) and annotation based input validation can be easily implemented. For example input validation of name is performed in Eco Application.
Following dependency is added to pom.xml for using Bean Validation.
<!-- Bean Validation (JSR-303) -->
<dependency>
<artifactId>hibernate-validator</artifactId>
<groupId>org.hibernate</groupId>
<version>4.3.1.Final</version>
</dependency>
In EchoForm
, add @NotNull
annotation and @Size
annotation to name
property as follows (can be added to getter method).
package com.example.helloworld.echo;
import java.io.Serializable;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
public class EchoForm implements Serializable {
private static final long serialVersionUID = 2557725707095364446L;
@NotNull // (1)
@Size(min = 1, max = 5) // (2)
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
Item number | Description |
---|---|
(1)
|
By adding
@NotNull annotation, whether name parameter exists in HTTP request is checked. |
(2)
|
By adding
@Size(min=1, max=5) annotation, whether the size of name is more than or equal to 1 and less than or equal to 5 is checked. |
In EchoController
class, add @Valid
annotation as shown below and also use of hasErrors
method.
package com.example.helloworld.echo;
import javax.validation.Valid;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("echo")
public class EchoController {
@ModelAttribute
public EchoForm setUpEchoForm() {
EchoForm form = new EchoForm();
return form;
}
@RequestMapping
public String index(Model model) {
return "echo/index";
}
@RequestMapping("hello")
public String hello(@Valid EchoForm form, BindingResult result, Model model) { // (1)
if (result.hasErrors()) { // (2)
return "echo/index";
}
model.addAttribute("name", form.getName());
return "echo/hello";
}
}
Item number | Description |
---|---|
(1)
|
In Controller, add
@Valid annotation to the argument on which validation needs to be executed. Also add BindingResult object to arguments.Input validation is automatically performed using Bean Validation and the result is stored in
BindingResult object. |
(2)
|
It can be checked whether there is error by using
hasErrors method. |
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<!DOCTYPE html>
<html>
<head>
<title>Echo Application</title>
</head>
<body>
<form:form modelAttribute="echoForm" action="${action}">
<form:label path="name">Input Your Name:</form:label>
<form:input path="name" />
<form:errors path="name" cssStyle="color:red" /><!-- (1) -->
<input type="submit" />
</form:form>
</body>
</html>
Item number | Description |
---|---|
(1)
|
Add
form:errors tag for displaying error message when an error occurs on input screen. |
- When an empty name is sent
- Size is more than 5 characters.
The generated HTML is as follows
<body>
<form id="echoForm" action="/helloworld/echo/hello" method="post">
<label for="name">Input Your Name:</label>
<input id="name" name="name" type="text" value=""/>
<span id="name.errors" style="color:red">size must be between 1 and 5</span>
<input type="submit" />
</form>
</body>
</html>
2.3.4.5. Summary¶
The following are the learnings from this chapter.
- Setting up configuration file of Spring MVC (simplified level)
- How to do Screen Transition (simplified level)
- Way to pass values between screens.
- Simple input validation
If above points are still not understood, it is recommended to read this chapter again and start again from building the environment. This will imporve the understanding of above concepts.