一、在Spring中使用thymeleaf的步骤
1.配置
In order to use Thymeleaf with Spring, you’ll need to configure three beans that enable Thymeleaf-Spring integration:
A ThymeleafViewResolver that resolves Thymeleaf template views from logical view names
A SpringTemplateEngine to process the templates and render the results
A TemplateResolver that loads Thymeleaf templates
ThymeleafViewResolver is an implementation of Spring MVC ’s ViewResolver . Just like any view resolver, it takes a logical view name and resolves a view. But in this case,that view is ultimately a Thymeleaf template.
Notice that the ThymeleafViewResolver bean is injected with a reference to theSpringTemplateEngine bean. SpringTemplateEngine is a Spring-enabled Thymeleaf engine for parsing templates and rendering results based on those templates. As you can see, it’s injected with a reference to the TemplateResolver bean.
TemplateResolver is what ultimately locates the templates. It’s configured much as you previously configured InternalResourceViewResolver with prefix and suffix properties. The prefix and suffix are applied to the logical view name to locate the Thymeleaf template. Its templateMode property is also set to HTML5 , indicating that the templates resolved are expected to render HTML5 output.
(1)Java配置
package spittr.web; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.thymeleaf.spring4.SpringTemplateEngine;
import org.thymeleaf.spring4.view.ThymeleafViewResolver;
import org.thymeleaf.templateresolver.ServletContextTemplateResolver;
import org.thymeleaf.templateresolver.TemplateResolver; @Configuration
@EnableWebMvc
@ComponentScan("spittr.web")
public class WebConfig extends WebMvcConfigurerAdapter { @Bean
public ViewResolver viewResolver(SpringTemplateEngine templateEngine) {
ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
viewResolver.setTemplateEngine(templateEngine);
return viewResolver;
}
@Bean
public SpringTemplateEngine templateEngine(TemplateResolver templateResolver) {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver);
return templateEngine;
} @Bean
public TemplateResolver templateResolver() {
TemplateResolver templateResolver = new ServletContextTemplateResolver();
templateResolver.setPrefix("/WEB-INF/views/");
templateResolver.setSuffix(".html");
//indicating that the templates resolved are expected to render HTML5 output
templateResolver.setTemplateMode("HTML5"); return templateResolver;
} @Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
} }
(2)Xml配置
<bean id="viewResolver"
class="org.thymeleaf.spring3.view.ThymeleafViewResolver"
p:templateEngine-ref="templateEngine" />
<bean id="templateEngine"
class="org.thymeleaf.spring3.SpringTemplateEngine"
p:templateResolver-ref="templateResolver" />
<bean id="templateResolver" class=
"org.thymeleaf.templateresolver.ServletContextTemplateResolver"
p:prefix="/WEB-INF/templates/"
p:suffix=".html"
p:templateMode="HTML5" />
2.定义Thymeleaf模板
(1)标签介绍
<a th:href="@{/spitter/register}">Register</a> <div th:fragment="header"> <img th:src="@{/resources/images/spitter_logo_50.png}" border="0" /></a> <div id="header" th:include="page :: header"></div>
<form method="POST" th:object="${spitter}"> <div class="errors" th:if="${#fields.hasErrors('*')}">
<ul>
<li th:each="err : ${#fields.errors('*')}"
th:text="${err}">Input is incorrect</li>
</ul>
</div> <label th:class="${#fields.hasErrors('firstName')}? 'error'">First Name</label>:
<input type="text" th:field="*{firstName}"
th:class="${#fields.hasErrors('firstName')}? 'error'" /><br/> <span th:text="${spitter.username}">username</span><br/> <li th:each="spittle : ${spittleList}"
th:id="'spittle_' + ${spittle.id}">
<div class="spittleMessage" th:text="${spittle.message}">Spittle message</div>
<div>
<span class="spittleTime" th:text="${spittle.time}">spittle timestamp</span>
<span class="spittleLocation" th:text="'{' + ${spittle.latitude} + ', ' + ${spittle.longitude} + ')'">lat, long</span>
</div>
</li>
thymeleaf标签的优势是定在原生的html里,不会破坏原来的html结构,可以用浏览器直接打开,只是动态计算的东西无效。
(2)home.html
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<title>Spitter</title>
<link rel="stylesheet"
type="text/css"
th:href="@{/resources/style.css}"></link>
</head>
<body>
<div id="header" th:include="page :: header"></div> <div id="content">
<h1>Welcome to Spitter</h1> <a th:href="@{/spittles}">Spittles</a> |
<a th:href="@{/spitter/register}">Register</a> <br/> View: <span th:text="${view}">unknown</span>
</div>
<div id="footer" th:include="page :: copy"></div>
</body>
</html>
(2.1)registerForm.html
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<title>Spitter</title>
<link rel="stylesheet" type="text/css"
th:href="@{/resources/style.css}"></link>
</head>
<body>
<div id="header" th:include="page :: header"></div> <div id="content">
<h1>Register</h1> <form method="POST" th:object="${spitter}">
<div class="errors" th:if="${#fields.hasErrors('*')}">
<ul>
<li th:each="err : ${#fields.errors('*')}"
th:text="${err}">Input is incorrect</li>
</ul>
</div>
<label th:class="${#fields.hasErrors('firstName')}? 'error'">First Name</label>:
<input type="text" th:field="*{firstName}"
th:class="${#fields.hasErrors('firstName')}? 'error'" /><br/> <label th:class="${#fields.hasErrors('lastName')}? 'error'">Last Name</label>:
<input type="text" th:field="*{lastName}"
th:class="${#fields.hasErrors('lastName')}? 'error'" /><br/> <label th:class="${#fields.hasErrors('email')}? 'error'">Email</label>:
<input type="text" th:field="*{email}"
th:class="${#fields.hasErrors('email')}? 'error'" /><br/> <label th:class="${#fields.hasErrors('username')}? 'error'">Username</label>:
<input type="text" th:field="*{username}"
th:class="${#fields.hasErrors('username')}? 'error'" /><br/> <label th:class="${#fields.hasErrors('password')}? 'error'">Password</label>:
<input type="password" th:field="*{password}"
th:class="${#fields.hasErrors('password')}? 'error'" /><br/>
<input type="submit" value="Register" /> </form>
</div>
<div id="footer" th:include="page :: copy"></div>
</body>
</html>
解析:
a)由<form th:object="${spitter}">指定了对象,By using th:field="*{firstName}", you get both a value attribute set to the value of firstName and also a name attribute set to firstName .
b)<li th:each>:
The th:each attribute on the <li> tag instructs Thymeleaf to render the <li> one time for each error,assigning the current error in each iteration to a variable named err .
The <li> tag also has a th:text attribute. This attribute instructs Thymeleaf to evaluate an expression (in this case, the value of the err variable) and render its value as the body of the <li> tag. In effect, there will be one <li> for each error, displaying
the text of that error.
c)You may be wondering about the difference between the expressions wrapped with ${} and those wrapped with *{} . The ${} expressions (such as ${spitter} ) are variable expressions. Normally, these are Object-Graph Navigation Language ( OGNL )expressions (http://commons.apache.org/proper/commons-ognl/). But when used with Spring, they’re SpEL expressions. In the case of ${spitter} , it resolves to the model property whose key is spitter .
As for *{} expressions, they’re selection expressions. Whereas variable expressions are evaluated against the entire SpEL context, selection expressions are evaluated on a selected object. In the case of the form, the selected object is the one given in the
(3)page.html
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"> <body> <div th:fragment="header">
<a th:href="@{/}">
<img th:src="@{/resources/images/spitter_logo_50.png}" border="0" /></a>
</div> <div>Content goes here</div> <div th:fragment="copy">Copyright © Craig Walls</div>
</body> </html>
(4)spittles.html
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<title>Spitter</title>
<link rel="stylesheet"
type="text/css"
th:href="@{/resources/style.css}" ></link>
</head>
<body>
<div id="header" th:include="page :: header"></div> <div id="content">
<div class="spittleForm">
<h1>Spit it out...</h1>
<form method="POST" name="spittleForm">
<input type="hidden" name="latitude" />
<input type="hidden" name="longitude" />
<textarea name="message" cols="80" rows="5"></textarea><br/>
<input type="submit" value="Add" />
</form>
</div>
<div class="listTitle">
<h1>Recent Spittles</h1>
<ul class="spittleList">
<li th:each="spittle : ${spittleList}"
th:id="'spittle_' + ${spittle.id}">
<div class="spittleMessage" th:text="${spittle.message}">Spittle message</div>
<div>
<span class="spittleTime" th:text="${spittle.time}">spittle timestamp</span>
<span class="spittleLocation" th:text="'{' + ${spittle.latitude} + ', ' + ${spittle.longitude} + ')'">lat, long</span>
</div>
</li>
</ul>
</div>
</div> <div id="footer" th:include="page :: copy"></div>
</body>
</html>
(5)spittle.html
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<title>Spitter</title>
<link rel="stylesheet"
type="text/css"
th:href="@{/resources/style.css}"></link>
</head>
<body>
<div id="header" th:include="page :: header"></div> <div id="content">
<div class="spittleView">
<div class="spittleMessage" th:text="#{spittle.message}">Spittle message</div>
<div>
<span class="spittleTime" th:text="#{spittle.time}">spittle timestamp</span>
</div>
</div>
</div>
<div id="footer" th:include="page :: copy"></div> </body>
</html>
(6)profile.html
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<title>Spitter</title>
<link rel="stylesheet"
type="text/css"
th:href="@{/resources/style.css}"></link>
</head>
<body>
<div id="header" th:include="page :: header"></div> <div id="content">
<h1>Your Profile</h1>
<span th:text="${spitter.username}">username</span><br/>
<span th:text="${spitter.firstName}">First</span> <span th:text="${spitter.lastName}">Last</span><br/>
<span th:text="${spitter.email}">email</span>
</div> <div id="footer" th:include="page :: copy"></div>
</body>
</html>
二、SpringMVC view层的总结
Thymeleaf is a compelling option because it enables the creation of natural templates that are still pure HTML and can be edited and viewed in the raw as if they were static HTML , but still render dynamic model data at runtime. Moreover, Thymeleaf templates are largely decoupled from servlets, enabling them to be used in places where JSP s can’t.