- Install eclipse Kepler
- Create new Maven project
- Check Create a simple project
- Provide options :
- Group Id = com.company
- Artifact Id = example1
- Packaging = war
- Click create
- It will create structure like :
- # src/main/java
- # src/main/resources
- # src/test/java
- # src/test/resources
- > src/main/webapp
- > JRE system lib (Default JRE set in eclipse)
- > pom.xml
- Provide Spring boot dependencies :
...
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.1.RELEASE</version>
</parent>
<properties>
<main.basedir>${basedir}/../..</main.basedir>
<thymeleaf.version>3.0.2.RELEASE</thymeleaf.version>
<thymeleaf-layout-dialect.version>
2.0.4
</thymeleaf-layout-dialect.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-thymeleaf</artifactId>
</dependency>
<dependencies>
</project>
- It will add all the Spring boot dependencies under Maven dependencies
- Put static contents of Bootstrap CSS and jQuery APIs :
# src/main/resources/static/css/bootstap.min.css
# src/main/resources/static/js/jquery-1.7.2.js# src/main/resources/static/js/jquery.validate.js# src/main/resources/static/favicon.ico - Create application.properties under resources and add configuration :
# Allow Thymeleaf templates to be reloaded at dev time
spring.thymeleaf.cache: false
spring.thymeleaf.mode: html
- Create some java classes for data model and manipulate data
public class Message {
private Long id;
@NotEmpty(message = "Message is required.")
private String text;
@NotEmpty(message = "Summary is required.")
private String summary;
private Calendar created = Calendar.getInstance();
// getters and setters
}
2. MessageRepository.java
public interface MessageRepository {
Iterable<Message> findAll();
Message save(Message message);
Message findMessage(Long id);
void deleteMessage(Long id);
}
3. InMemoryMessageRepository.java
public class InMemoryMessageRepository
implements MessageRepository {
private static AtomicLong counter = new AtomicLong();
private final ConcurrentMap<Long, Message> messages =
new ConcurrentHashMap<Long, Message>();
public Iterable<Message> findAll() {
return this.messages.values();
}
public Message save(Message message) {
Long id = message.getId();
if (id == null) {
id = counter.incrementAndGet();
message.setId(id);
}
this.messages.put(id, message);
return message;
}
public Message findMessage(Long id) {
return this.messages.get(id);
}
public void deleteMessage(Long id) {
this.messages.remove(id);
}
}
- Create master Application with main(), bean to access data and Converter bean
public class Application {
@Bean
public MessageRepository messageRepository() {
return new InMemoryMessageRepository();
}
@Bean
public Converter<String, Message> messageConverter() {
return new Converter<String, Message>() {
public Message convert(String id) {
return messageRepository().
findMessage(Long.valueOf(id));
}
};
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
- Create the Controller to handle different application path
@Controller
@RequestMapping ("/")
public class MessageController {
private final MessageRepository messageRepository;
public MessageController(MessageRepository messageRepository){
this.messageRepository = messageRepository;
}
@GetMapping
public ModelAndView list() {
Iterable<Message> messages=this.messageRepository.findAll();
return new ModelAndView("messages/list", "messages", messages);
}
@GetMapping("{id}")
public ModelAndView view(@PathVariable("id") Message message){
return new ModelAndView("messages/view", "message", message);
}
@GetMapping(params = "form")
public String createForm(@ModelAttribute Message message) {
return "messages/form";
}
@PostMapping
public ModelAndView create(@Valid Message message,
BindingResult result, RedirectAttributes redirect) {
if (result.hasErrors()) {
return new ModelAndView("messages/form", "formErrors",
result.getAllErrors());
}
message = this.messageRepository.save(message);
redirect.addFlashAttribute("globalMessage",
"Successfully created a new message");
return new ModelAndView("redirect:/{message.id}",
"message.id", message.getId());
}
@RequestMapping("foo")
public String foo() {
throw new RuntimeException("Expected exception in controller");
}
@GetMapping(value = "delete/{id}")
public ModelAndView delete(@PathVariable("id") Long id) {
this.messageRepository.deleteMessage(id);
Iterable<Message> messages = this.messageRepository.findAll();
return new ModelAndView("messages/list", "messages", messages);
}
@GetMapping(value = "modify/{id}")
public ModelAndView modifyForm(@PathVariable("id") Message message) {
return new ModelAndView("messages/form", "message", message);
}
@RequestMapping (path="/name", method=RequestMethod.GET)
public String getName() {
return "Hello World";
}
}
- Create pages :
> src/main/resources/templates/messages/form.html
> src/main/resources/templates/messages/list.html
> src/main/resources/templates/messages/view.html
> src/main/resources/templates/layout.html
layout.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/web/thymeleaf/layout">
<head>
<title>Layout</title>
<link rel="stylesheet" th:href="@{/css/bootstrap.min.css}"
href="../../css/bootstrap.min.css" />
</head>
<body>
<div class="container">
<div class="navbar">
<div class="navbar-inner">
<a class="brand"
href="https://github.com/ultraq/thymeleaf-layout-dialect">
Thymeleaf - Layout
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/web/thymeleaf/layout">
<head>
<title>Layout</title>
<link rel="stylesheet" th:href="@{/css/bootstrap.min.css}"
href="../../css/bootstrap.min.css" />
</head>
<body>
<div class="container">
<div class="navbar">
<div class="navbar-inner">
<a class="brand"
href="https://github.com/ultraq/thymeleaf-layout-dialect">
Thymeleaf - Layout
</a>
<ul class="nav">
<li>
<a th:href="@{/}" href="messages.html"> Messages </a>
</li>
</ul>
</div>
</div>
</ul>
</div>
</div>
<h1 layout:fragment="header">Layout</h1>
<div layout:fragment="content">Fake content</div>
</div>
</body>
</html>
</div>
</body>
</html>
list.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/web/thymeleaf/layout"
layout:decorate="layout">
<head>
<title>Messages : View all</title>
</head>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/web/thymeleaf/layout"
layout:decorate="layout">
<head>
<title>Messages : View all</title>
</head>
<body>
<h1 layout:fragment="header">Messages : View all</h1>
<div layout:fragment="content" class="container">
<div class="pull-right">
<a href="form.html" th:href="@{/(form)}">Create Message</a>
</div>
<table class="table table-bordered table-striped">
<thead>
<tr>
<td>ID</td>
<td>Created</td>
<td>Summary</td>
</tr>
</thead>
<tbody>
<tr th:if="${messages.empty}">
<td colspan="3">No messages</td>
</tr>
<tr th:each="message : ${messages}">
<td th:text="${message.id}">1</td>
<td th:text="${#calendars.format(message.created)}">
July 11,2012 2:17:16 PM CDT
</td>
<td><a href="view.html"
<td><a href="view.html"
th:href="@{'/' + ${message.id}}"
th:text="${message.summary}">
th:text="${message.summary}">
The summary
</a>
</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
</tr>
</tbody>
</table>
</div>
</body>
</html>
view.html
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/web/thymeleaf/layout"
layout:decorate="layout">
<head>
<title>Messages : View</title>
</head>
<body>
<h1 layout:fragment="header">Messages : Create</h1>
<div layout:fragment="content" class="container">
<div class="alert alert-success" th:if="${globalMessage}"
th:text="${globalMessage}">Some Success message</div>
xmlns:layout="http://www.ultraq.net.nz/web/thymeleaf/layout"
layout:decorate="layout">
<head>
<title>Messages : View</title>
</head>
<body>
<h1 layout:fragment="header">Messages : Create</h1>
<div layout:fragment="content" class="container">
<div class="alert alert-success" th:if="${globalMessage}"
th:text="${globalMessage}">Some Success message</div>
<div class="pull-right">
<a th:href="@{/}" href="list.html"> Messages </a>
</div>
<dl>
<dt>ID</dt>
<dd id="id" th:text="${message.id}">123</dd>
<dt>Date</dt>
<dd id="created"
<a th:href="@{/}" href="list.html"> Messages </a>
</div>
<dl>
<dt>ID</dt>
<dd id="id" th:text="${message.id}">123</dd>
<dt>Date</dt>
<dd id="created"
th:text="${#calendars.format(message.created)}">
July 11, 2012 2:17:16 PM CDT
July 11, 2012 2:17:16 PM CDT
</dd>
<dt>Summary</dt>
<dd id="summary" th:text="${message.summary}">
<dt>Summary</dt>
<dd id="summary" th:text="${message.summary}">
A short summary...
</dd>
<dt>Message</dt>
<dd id="text" th:text="${message.text}">
</dd>
<dt>Message</dt>
<dd id="text" th:text="${message.text}">
A detailed message that is longer than the summary.
</dd>
</dl>
</dl>
<div class="pull-left">
<a href="messages" th:href="@{'/delete/' + ${message.id}}">
delete
<a href="messages" th:href="@{'/delete/' + ${message.id}}">
delete
</a> |
<a href="form.html" th:href="@{'/modify/' + ${message.id}}">
modify
</a>
</div>
</div>
</body>
</html>
</div>
</div>
</body>
</html>
form.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/web/thymeleaf/layout"
layout:decorate="layout">
<head>
<title>Messages : View all</title>
</head>
<body>
<h1 layout:fragment="header">Messages : View all</h1>
<div layout:fragment="content" class="container">
<div class="pull-right">
<a href="form.html" th:href="@{/(form)}">Create Message</a>
</div>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/web/thymeleaf/layout"
layout:decorate="layout">
<head>
<title>Messages : View all</title>
</head>
<body>
<h1 layout:fragment="header">Messages : View all</h1>
<div layout:fragment="content" class="container">
<div class="pull-right">
<a href="form.html" th:href="@{/(form)}">Create Message</a>
</div>
<table class="table table-bordered table-striped">
<thead>
<tr>
<td>ID</td>
<td>Created</td>
<td>Summary</td>
</tr>
</thead>
<tbody>
<tr th:if="${messages.empty}">
<td colspan="3">No messages</td>
</tr>
<tr th:each="message : ${messages}">
<td th:text="${message.id}">1</td>
<td th:text="${#calendars.format(message.created)}">
July 11, 2012 2:17:16 PM CDT
</td>
<td>
<td>
<a href="view.html" th:href="@{'/' + ${message.id}}"
th:text="${message.summary}"> The summary </a>
th:text="${message.summary}"> The summary </a>
</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
</tr>
</tbody>
</table>
</div>
</body>
</html>
- Run the application by right click on Application.java and choose "Run as Java application" as a Java application
After embedded tomcat start, you can access resources using request path and controller :
http://localhost:8080/