前言
Thymeleaf 是一种模板语言。那模板语言或模板引擎是什么?常见的模板语言都包含以下几个概念:数据(Data)、模板(Template)、模板引擎(Template Engine)和结果文档(Result Documents)。
Spring boot 支持多种模板语言(Thymeleaf 、Freemarker、Mustache、Groovy Templates)
Thymeleaf 跟大部分的模板语言类似,上手容易,使用简单
项目结构图
最终运行结果
下面开始一步一步的编写代码了
增加Spring boot的maven 依赖
在原有基础的pom结构中追加Swagger2的依赖
<?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> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.10.RELEASE</version> </parent> <groupId>com.example</groupId> <artifactId>spring-boot-web-thymeleaf</artifactId> <version>1.0-SNAPSHOT</version> <properties> <java.version>1.8</java.version> </properties> <dependencies> <!-- Compile --> <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>
增加一个消息类
package sample.web.ui;import java.util.Calendar;import org.hibernate.validator.constraints.NotEmpty;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(); // get set }
保存消息的接口
package sample.web.ui;public interface MessageRepository { Iterable<Message> findAll(); Message save(Message message); Message findMessage(Long id); void deleteMessage(Long id); }
使用内存保存消息
package sample.web.ui;import java.util.concurrent.ConcurrentHashMap;import java.util.concurrent.ConcurrentMap;import java.util.concurrent.atomic.AtomicLong;public class InMemoryMessageRepository implements MessageRepository { // 用来模拟主键自增 private static AtomicLong counter = new AtomicLong(); // 用来存储消息 private final ConcurrentMap<Long, Message> messages = new Concur rentHashMap<Long, Message>(); @Override public Iterable<Message> findAll() { return this.messages.values(); } @Override public Message save(Message message) { Long id = message.getId(); if (id == null) { // 生成一个ID id = counter.incrementAndGet(); message.setId(id); } // 保存消息 this.messages.put(id, message); return message; } @Override public Message findMessage(Long id) { return this.messages.get(id); } @Override public void deleteMessage(Long id) { this.messages.remove(id); } }
编写控制层代码
package sample.web.ui.mvc;import org.springframework.stereotype.Controller;import org.springframework.validation.BindingResult;import org.springframework.web.bind.annotation.*;import org.springframework.web.servlet.ModelAndView;import org.springframework.web.servlet.mvc.support.RedirectAttributes;import sample.web.ui.Message;import sample.web.ui.MessageRepository;import javax.validation.Valid;@Controller@RequestMapping("/messages")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:/messages/{message.id}", "message.id", message.getId()); } // 删除消息 @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); } }
程序入口main
package sample.web.ui.mvc;import org.springframework.stereotype.Controller;import org.springframework.validation.BindingResult;import org.springframework.web.bind.annotation.*;import org.springframework.web.servlet.ModelAndView;import org.springframework.web.servlet.mvc.support.RedirectAttributes;import sample.web.ui.Message;import sample.web.ui.MessageRepository;import javax.validation.Valid;@Controller@RequestMapping("/messages")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:/messages/{message.id}", "message.id", message.getId()); } // 删除消息 @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); } }
编写布局页面
<!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" /> <link rel="icon" th:href="@{/favicon.jpg}" href="favicon.jpg" /></head><body> <div class="container"> <div class="navbar"> <div class="navbar-inner"> <a class="brand" th:href="@{/messages}" href="#">Thymeleaf - Layout</a> <ul class="nav"> <li><a th:href="@{/messages}" href="messages.html"> Messages </a></li> </ul> </div> </div> <h1 layout:fragment="header">Layout</h1> <div layout:fragment="content">Fake content</div> </div> </body> </html>
编写列表页面
<!DOCTYPE html><html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/web/thymeleaf/layout" layout:decorator="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="@{/messages/(form)}">Create Message</a> </div> <table class="table table-bordered table-striped"> <!-- 使用下面注解类解决IntelliJ提示问题 --> <!--/*@thymesVar id="messages" type="java.util.List"*/--> <!--/*@thymesVar id="message" type="sample.web.ui.Message"*/--> <thead> <tr> <td>ID</td> <td>Created</td> <td>Summary</td> </tr> </thead> <tbody> <tr th:if="${messages.isEmpty()}"> <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" th:href="@{'/messages/' + ${message.id}}" th:text="${message.summary}"> The summary </a></td> </tr> </tbody> </table> </div></body></html>
编写增加页面
<!DOCTYPE html><html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/web/thymeleaf/layout" layout:decorator="layout"><head><title>Messages : Create</title></head><body> <h1 layout:fragment="header">Messages : Create</h1> <div layout:fragment="content" class="container"> <!-- 使用下面注解类解决IntelliJ提示问题 --> <!--/*@thymesVar id="message" type="sample.web.ui.Message"*/--> <form id="messageForm" th:action="@{/messages/(form)}" th:object="${message}" action="#" method="post"> <div th:if="${#fields.hasErrors('*')}" class="alert alert-error"> <p th:each="error : ${#fields.errors('*')}" th:text="${error}"> Validation error</p> </div> <div class="pull-right"> <a th:href="@{/messages}" href="messages.html"> Messages </a> </div> <input type="hidden" th:field="*{id}" th:class="${#fields.hasErrors('id')} ? 'field-error'" /> <label for="summary">Summary</label> <input type="text" th:field="*{summary}" th:class="${#fields.hasErrors('summary')} ? 'field-error'" /> <label for="text">Message</label> <textarea th:field="*{text}" th:class="${#fields.hasErrors('text')} ? 'field-error'"></textarea> <div class="form-actions"> <input type="submit" value="Save" /> </div> </form> </div></body></html>
编写详情页面
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/web/thymeleaf/layout" layout:decorator="layout"><head><title>Messages : View</title></head><body><!-- 使用下面注解类解决IntelliJ提示问题 --><!--/*@thymesVar id="message" type="sample.web.ui.Message"*/--> <h1 layout:fragment="header">Messages : Create</h1> <div layout:fragment="content" class="container"> <!--/*@thymesVar id="globalMessage" type=""*/--> <div class="alert alert-success" th:if="${globalMessage}" th:text="${globalMessage}">Some Success message</div> <div class="pull-right"> <a th:href="@{/messages}" 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</dd> <dt>Summary</dt> <dd id="summary" th:text="${message.summary}">A short summary... </dd> <dt>Message</dt> <dd id="text" th:text="${message.text}">A detailed message that is longer than the summary.</dd> </dl> <div class="pull-left"> <a href="messages" th:href="@{'/messages/delete/' + ${message.id}}"> delete </a> | <a href="form.html" th:href="@{'/messages/modify/' + ${message.id}}"> modify </a> </div> </div></body></html>
Spring 设置 application.properties
spring.thymeleaf.cache=falseserver.tomcat.basedir=target/tomcat server.tomcat.accesslog.enabled=true
编写日志文件 logback.xml
<?xml version="1.0" encoding="UTF-8"?><configuration> <include resource="org/springframework/boot/logging/logback/base.xml"/></configuration>
bootstrap v2.0 请到官网下载
到这里所有的类都编写完了,让我们来用用看吧
让我们打开浏览器地址栏访问
http://localhost:8080/
演示
你的运行结果对了吗?
关注我们
想要了解更多内容请关注“IT实战联盟”,也可以留言和作者互动 获取源码哦!!!