thymeleaf [taɪm lif]百里香叶
官方文档http://www.thymeleaf.org/doc/tutorials/2.1/usingthymeleaf.html
http://blog.csdn.net/pdw2009/article/details/44701127
<!DOCTYPEhtml SYSTEM"http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-3.dtd">
<htmlxmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
或者使用下面的文档声明也可以,这样就没有Thymeleaf对文档的校验功能了,因为没有引入对应的DTD,而且IDE可能会提示错误,但是不影响对模板的解析。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
1.简单的表达式:
变量表达式:$ {…}
选择变量表达式:* {…}
国际化表达式:# {…}
链接的网址的表达式:@{...}
'User is of type ' + (${user.isAdmin()} ? 'Administrator' : (${user.type} ?: 'Unknown'))
4.2Variables变量
模板中获取变量值的方式,使用${},针对不同类型数据,用法如下
/*
* Access to properties using the point (.). Equivalent to calling property getters.
*/
$
{person
.father
.name
}
通过.来获取,相当于调用getter()方法
/*
* Access to properties can also be made by using brackets ([]) and writing
* the name of the property as a variable or between single quotes.
*/
$
{person
['father']['name']}
使用
[]
等同与
. []
能在某些场合完成
.
不能完成的功能
/*
* If the object is a map, both dot and bracket syntax will be equivalent to
* executing a call on its get(...) method.
*/
$
{countriesByCode
.ES
}
$
{personsByName
['Stephen Zucchini'].age
}
获取
map
集合数据
/*
* Indexed access to arrays or collections is also performed with brackets,
* writing the index without quotes.
*/
$
{personsArray
[0].name
}
获取数组
/*
* Methods can be called, even with arguments.
*/
$
{person
.createCompleteName()}
$
{person
.createCompleteNameWithSeparator('-')}
调用对象的方法,即便包含参数
Expression Utility Objects在模版中使用内置对象
内置对象,提供了很多方便的功能,日期格式化,字符串处理,数字格式化等
#dates, formatting,component extraction,etc
#calendars
#numbers,formatting numeric objects.
#strings, contains,startsWith,prepending/appending,etc
#bools
#arrays
#lists
#sets
#maps
#aggregates, creating aggregates on arrays or collections
#messages, equal to using #{}
#ids, deal with id attributes, eg: as a result of an iteration
#ctx等等,还有很多!
例子:
格式化
th:text="${#calendars.format(today,'ddMMMM yyyy')}"
具体对应使用办法详情见:http://www.thymeleaf.org/doc/tutorials/2.1/usingthymeleaf.html#appendix-b-expression-utility-objects
4.3Expressions on selections (asterisk syntax)星号的语法
Variable expressions notonly can be written in ${...}
expressions,but also in *{...}
ones.
变量表达式不仅可以用$ {…}表达式编写,也可以用在* {…}中。
There is an importantdifference, though: the asterisk syntax evaluates expressions on selectedobjects rather than on the whole context variables map. This is: as long asthere is no selected object, the dollar and the asterisk syntaxes do exactlythe same.
有一个重要的区别,虽然:星号句法表达式的值在选定的对象而不是整个上下文变量图。这就是:只要没有选定对象,美元和星号语法完全一样
And what is that objectselection thing? A th:object
attribute.Let’s use it in our user profile (userprofile.html
)page:
<div th:object="${session.user}">
<p>
Name:
<span th:text="*{firstName}">Sebastian
</span>.
</p>
<p>
Surname:
<span th:text="*{lastName}">Pepper
</span>.
</p>
<p>
Nationality:
<span th:text="*{nationality}">Saturn
</span>.
</p>
</div>
Which is exactlyequivalent to:
<div>
<p>
Name:
<span th:text="${session.user.firstName}">Sebastian
</span>.
</p>
<p>
Surname:
<span th:text="${session.user.lastName}">Pepper
</span>.
</p>
<p>
Nationality:
<span th:text="${session.user.nationality}">Saturn
</span>.
</p>
</div>
Of course, dollar andasterisk syntax can be mixed:
<div th:object="${session.user}">
<p>
Name:
<span th:text="*{firstName}">Sebastian
</span>.
</p>
<p>
Surname:
<span th:text="${session.user.lastName}">Pepper
</span>.
</p>
<p>
Nationality:
<span th:text="*{nationality}">Saturn
</span>.
</p>
</div>
When an object selectionis in place, the selected object will be also available to dollar expressionsas the #object
expressionvariable:
<div th:object="${session.user}">
<p>
Name:
<span th:text="${#object.firstName}">Sebastian
</span>.
</p>
<p>
Surname:
<span th:text="${session.user.lastName}">Pepper
</span>.
</p>
<p>
Nationality:
<span th:text="*{nationality}">Saturn
</span>.
</p>
</div>
As said, if no objectselection has been performed, dollar and asterisk syntaxes are exactlyequivalent.
<div>
<p>
Name:
<span th:text="*{session.user.name}">Sebastian
</span>.
</p>
<p>
Surname:
<span th:text="*{session.user.surname}">Pepper
</span>.
</p>
<p>
Nationality:
<span th:text="*{session.user.nationality}">Saturn
</span>.
</p>
</div>
4.4Link URLs
Let’s use this newsyntax. Meet the th:href
attribute:
<!-- Will produce 'http://localhost:8080/gtvg/order/details?orderId=3' (plus rewriting) -->
<a href="details.html"
th:href="@{http://localhost:8080/gtvg/order/details(orderId=${o.id})}">view
</a>
<!-- Will produce '/gtvg/order/details?orderId=3' (plus rewriting) -->
<a href="details.html"th:href="@{/order/details(orderId=${o.id})}">view
</a>
<!-- Will produce '/gtvg/order/3/details' (plus rewriting) -->
<a href="details.html"th:href="@{/order/{orderId}/details(orderId=${o.id})}">view
</a>
· If several parameters are needed, these will be separatedby commas 链接多参数用逗号分割like@{/order/process(execId=${execId},execType='FAST')}
· The th:href
tag allowed us to (optionally) have a work ing static href
attribute in our template, so that our template linksremained navigable by a browser when opened directly for prototyping purposes
href标记允许我们(可选的)有一个工作的静态href属性在我们的模板,可打开原型
<a th:href="@{${url}(orderId=${o.id})}">view
</a>
<a th:href="@{'/details/'+${user.login}(orderId=${o.id})}">view
</a>
Server root relative URLs服务根路径
An additional syntax can be used tocreate server-root-relative (instead of context-root-relative) URLs in order tolink to different contexts in the same server. These URLs will be specifiedlike @{~/path/to/something}
4.5Literals
Text literals
Text literals are just character stringsspecified between single quotes. They can include any character, but you shouldescape any single quotes inside them as \'.
直接写作th:text="working web application"是错误的,必须加上单引号
如果字符串中没有空格,则可以去掉单引号
<p>
Now you arelooking at a <span th:text="'working webapplication'">template file</span>.
</p>
Number literals
Numeric literals look exactly like whatthey are: numbers.
数字直接写即可
<p>The year is<span th:text="2013">1492</span>.</p>
<p>In twoyears, it will be <span th:text="2013 + 2">1494</span>.</p>
Boolean literals
The boolean literals are true and false. For example:
<div th:if="${user.isAdmin()}== false"> ...
Note that in the above example, the == false is written outside the braces, and thusit is Thymeleaf itself who takes care of it. If it were written inside thebraces, it would be the responsibility of the OGNL/SpringEL engines:
以上判断boolean类型时,==false是写在${}外面的,这是thymeleaf的语法;如果false写在${}里面则为el/ognl表达式的语法
<div th:if="${user.isAdmin()== false}"> ...
等同于${! }
<div th:if="${!user.isAdmin()}"> ...
The null literal
The null literal can be also used:
<div th:if="${variable.something}== null"> ...
These tokens allow a little bit ofsimplification in Standard Expressions. They work exactly the same as textliterals ('...'
), but they only allow letters (A-Z
and a-z
), numbers (0-9
), brackets ([
and ]
), dots (.
), hyphens (-
) andunderscores (_
). So no whitespaces, no commas, etc.
允许在标准表达式中的一点点简化。完全一样的文本文字('...'
),,只允许字母(A-Z和a-z)、数字(0-9),括号([ and ]),点(。),连字符(-)和下划线(_)。所以没有空格,没有逗号,等等。
<div th:class="content">...
</div>
instead of: 如果不包括空格
<div th:class="'content'">...
</div>
4.6Appending texts追加文本
Texts, no matter whetherthey are literals or the result of evaluating variable or message expressions,can be easily appended using the +
operator:
用+追加文本数据
th:text="'The name of the user is ' + ${user.name}"
下面4.7是一个简单的替换规则,无需+追加,用||则可以输出
4.7Literal substitutions文字替换
Literal substitutionsallow the easy formatting of strings containing values from variables withoutthe need to append literals with '...'+ '...'
.
文字替换,允许含值的变量不需要追加文本字符串的一种简单的格式
These substitutions mustbe surrounded by vertical bars (|
),like:
<span th:text="|Welcome to our application, ${user.name}!|">
Which is actuallyequivalent to:
<span th:text="'Welcome to our application, ' + ${user.name} + '!'">
Literal substitutions canbe combined with other types of expressions:
追加和替换混合使用
<span th:text="${onevar} + '' + |${twovar}, ${threevar}|">
Note: onlyvariable expressions (${...}
)are allowed inside |...|
literalsubstitutions. No other literals ('...'
),boolean/numeric tokens, conditional expressions etc. are.
4.8Arithmetic operations算术运算
Some arithmeticoperations are also available: +
, -
, *
, /
and %
.
prodStat.count
除以
2
求余是否为
0
,并赋值给
isEven
变量
th:with="isEven=(${prodStat.count} % 2 == 0)"
Note that these operatorscan also be applied inside OGNL variable expressions themselves (and in thatcase will be executed by OGNL instead of the Thymeleaf Standard Expressionengine):
th:with="isEven=${prodStat.count % 2 == 0}"
Note that textual aliasesexist for some of these operators: div
(/
), mod
(%
).
<p th:with="isEven=(888 + 2)">
<span th:text="${isEven}"></span>
</p> 页面输出:890
局部变量,th:with能定义局部变量:
<div th:with="firstPer=${persons[0]}">
<p>
The name of the first person is <span th:text="${firstPer.name}">Julius Caesar</span>.
</p>
</div>
4.9Comparators and Equality比较和判断相等
Values in expressions canbe compared with the >
, <
, >=
and <=
symbols,as usual, and also the ==
and !=
operatorscan be used to check equality (or the lack of it). Note that XML establishesthat the <
and >
symbolsshould not be used in attribute values, and so they should be substituted by <
and >
.
注意,一般页面文件尽量避免使用<和>,应使用<和>来代替
th:if="${prodStat.count}
>1"
th:text="'Execution mode is ' + ( (${execMode} == 'dev')? 'Development' : 'Production')"
Note that textual aliasesexist for some of these operators: gt
(>
), lt
(<
), ge
(>=
), le
(<=
), not
(!
).Also eq
(==
), neq
/ne
(!=
).
4.10Conditional expressions条件表达式
满足条件取前者,不满足取后者
<tr th:class="${row.even}? 'even' : 'odd'">
...
</tr>
条件表达式也可以嵌套使用圆括号:
<tr th:class="${row.even}? (${row.first}? 'first' : 'even') : 'odd'">
...
</tr>
可以省略条件不满足的表达式,如果不满足,默认返回null
<div th:class="100!=100 ? 'panel panel-warningpanel-heading'">
这里什么样式也不显示
</div>
4.11Default expressions (Elvis operator)有默认值的表达式
第一个表达式的结果只要不为null,则取第一个表达式的值
A ?: B
如果A不为空,则取A的值,反之取B
<div th:object="${session.user}">
...
<p>
Age:
<span th:text="*{age}?: '(no age specified)'">27
</span>.
</p>
</div>
等同于
<div th:object="${session.user}">
...
<p>
Age:
<span th:text="*{age != null}? *{age} : '(no age specified)'">27
</span>.
</p>
</div>
5.2Setting value to specific attributes 特定属性设置值
设置action属性
<form action="subscribe.html"th:attr="action=@{/subscribe}">
设置value属性
<input type="submit" value="Subscribe me!"th:attr="value=#{subscribe.submit}"/>
一次设置多个属性
<img src="../../images/gtvglogo.png"
th:attr="src=@{/images/gtvglogo.png},title=#{logo},alt=#{logo}"/>
以上方法指定属性赋值可以是非常实用的,但它不是最优雅的方式创建模板,thymeleaf有很多属性可以使用:
<img src="../../images/gtvglogo.png"
th:src="@{/images/gtvglogo.png}"th:title="#{logo}"th:alt="#{logo}"/>
thymeleaf 常用属性
th:abbr | th:accept | th:accept-charset |
th:accesskey | th:action | th:align |
th:alt | th:archive | th:audio |
th:autocomplete | th:axis | th:background |
th:bgcolor | th:border | th:cellpadding |
th:cellspacing | th:challenge | th:charset |
th:cite | th:class | th:classid |
th:codebase | th:codetype | th:cols |
th:colspan | th:compact | th:content |
th:contenteditable | th:contextmenu | th:data |
th:datetime | th:dir | th:draggable |
th:dropzone | th:enctype | th:for |
th:form | th:formaction | th:formenctype |
th:formmethod | th:formtarget | th:frame |
th:frameborder | th:headers | th:height |
th:high | th:href | th:hreflang |
th:hspace | th:http-equiv | th:icon |
th:id | th:keytype | th:kind |
th:label | th:lang | th:list |
th:longdesc | th:low | th:manifest |
th:marginheight | th:marginwidth | th:max |
th:maxlength | th:media | th:method |
th:min | th:name | th:optimum |
th:pattern | th:placeholder | th:poster |
th:preload | th:radiogroup | th:rel |
th:rev | th:rows | th:rowspan |
th:rules | th:sandbox | th:scheme |
th:scope | th:scrolling | th:size |
th:sizes | th:span | th:spellcheck |
th:src | th:srclang | th:standby |
th:start | th:step | th:style |
th:summary | th:tabindex | th:target |
th:title | th:type | th:usemap |
th:value | th:valuetype | th:vspace |
th:width | th:wrap | th:xmlbase |
th:xmllang | th:xmlspace | th:attrappend th:attrprepend |
· th:alt-title will set alt and title.
· th:lang-xmllang will set lang and xml:lang.
th:alt-title、th:lang-xmllang为thymeleaf两个特别的属性,它可以同时设置两个属性
接上面的<img>例子,也可以写成
<img src="../../images/gtvglogo.png"
th:src="@{/images/gtvglogo.png}"th:alt-title="#{logo}"/>
5.4Appending and prepending 追加和预追加
th:attrappend
后面追加
th:attrprepend
前面追加
例如:cssStyle=warning
<input type="button"value="Do it!"class="btn"th:attrappend="class=${'' + cssStyle}"/>
即为
<input type="button"value="Do it!"class="btn warning"/>
5.5 Fixed-value boolean attributes固定值的boolean类型
XHTML/HTML5中,有一些特殊的属性,要么没有值,要么为某个固定的值
checked
selected
disabled
mutiple
readonly
如果计算结果为true,则使用它的固定值,否则不处理。
<inputtype="checkbox" name="active" th:checked="true"/>
都包含以下属性
th:async | th:autofocus | th:autoplay |
th:checked | th:controls | th:declare |
th:default | th:defer | th:disabled |
th:formnovalidate | th:hidden | th:ismap |
th:loop | th:multiple | th:novalidate |
th:nowrap | th:open | th:pubdate |
th:readonly | th:required | th:reversed |
th:scoped | th:seamless | th:selected |
6.1Iteration basics 迭代 each
<table>
<tr>
<th>
NAME
</th>
<th>
PRICE
</th>
<th>
IN STOCK
</th>
</tr>
<tr th:each="prod : ${prods}">
<td th:text="${prod.name}">
Onions
</td>
<td th:text="${prod.price}">
2.41
</td>
<td th:text="${prod.inStock}? #{true} : #{false}">
yes
</td>
</tr>
</table>
6.2Keeping iteration status迭代状态
使用迭代时,可跟踪迭代的状态,包括以下数据:
· The current iteration index, starting with 0.This is the index property.
当前迭代索引,从0开始。这是索引属性。
· The current iteration index, starting with 1.This is the count property.
当前迭代索引,从1开始。这是计数属性。
· The total amount of elements in the iterated variable.This is the size property.
迭代变量中的元素的总量。这是大小属性。
· The iter variable for each iteration.This is the current property.
每个迭代iter变量。这是当前属性
· Whether the current iteration is even or odd. These arethe even/odd boolean properties.
当前的迭代是否是偶数还是奇数。这些都是偶数/奇数的布尔属性
· Whether the current iteration is the first one. This isthe first boolean property.
是否当前的迭代是第一个。这是第一个布尔属性
· Whether the current iteration is the last one. This isthe last boolean property.
是否当前的迭代是最后一个。这是最后一个布尔属性
在th:each中,在iter variable变量后面,定义一个status variable,通过该变量来获取遍历过程中的状态
<tr th:each="prod,iterStat : ${prods}"th:class="${iterStat.odd}? 'odd'">
如果没有显式设置一个状态变量,thymeleaf会自动为我们提供一个来使用,通过在iter variable后面添加后缀Stat来使用。
<tr th:each="prod: ${prods}"th:class="${prodStat.odd}? 'odd'">
7.1Simple conditionals: “if” and “unless”条件语句
当th:if条件成立时,该标签中其它th:*标签才会发挥作用,如果条件不成立,则th:*不会执行
<a href="comments.html"
th:href="@{/product/comments(prodId=${prod.id})}"
th:if="${not #lists.isEmpty(prod.comments)}">view
</a>
另外,还可以用th:unless,进行条件控制。如果条件为真,则th:*不会执行。
<a href="comments.html"
th:href="@{/comments(prodId=${prod.id})}"
th:unless="${#lists.isEmpty(prod.comments)}">view
</a>
7.2Switch statements选择语句
<div th:switch="${user.role}">
<p th:case="'admin'">
User is an administrator
</p>
<p th:case="#{roles.manager}">
User is a manager
</p>
<p th:case="*">
User is some other thing
</p>
</div>
th:case="*"
: 默认选项
8.1Including template fragments模板重用
th:fragment
th:include
用法:
在某个标签中使用th:fragment属性定义一个变量名,然后在其他模板中通过th:include,即可引入。
we define a /WEB-INF/templates/footer.html
file containing this code, byusing the th:fragment
attribute.
在footer.html中定一个名称叫copy
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-4.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<body>
<div th:fragment="copy">
©
2011 The Good Thymes Virtual Grocery
</div>
</body>
</html>
usingone of theth:include
or th:replace
attributes:
从文件名称为footer的模板中引入名称为copy的fragment
<body>
<div th:include="footer :: copy"></div>
</body>
th:include中同样可以嵌套使用表达式
<div th:include="footer :: (${user.isAdmin}? #{footer.admin} : #{footer.normaluser})"></div>
th:include
引入fragment中定义的内容
th:substituteby / th:replace
引入fragment所在标签和内容,并替换当前的标签
<footer th:fragment="copy">
©
2011 The Good Thymes Virtual Grocery
</footer>
用th:include和th:replace引用
<body>
<div th:include="footer :: copy"></div>
<div th:replace="footer :: copy"></div>
</body>
编译后,你会发现th:repalce会将内容引入,并替换掉标签:
<body>
<div>
©
2011 The Good Thymes Virtual Grocery
</div>
<footer>
©
2011 The Good Thymes Virtual Grocery
</footer>
</body>
12.1Text inlining 内连
好处:简化书写
弊端:以prototype呈现(静态地打开网页),将原样显示
用法,在标签上定义th:inline="text"
该标签中任意地方都可以使用内联样式获取数据
<p>Hello,
<span th:text="${session.user.name}">Sebastian
</span>!
</p>
th:inline
<p th:inline="text">Hello, [[${session.user.name}]]!
</p>
在标签上定义th:inline="text",该标签内部任意地方都可以使用内联样式获取数据
parent tag中定义
<body th:inline="text">
...
<p>hello:[[${session.user.name}]]</p>
...
<body>
12.2Script inlining (JavaScript and Dart)
<script th:inline="javascript">
/*
<![CDATA[*/
var username = /*[[${session.user.name}]]*/ 'Sebastian';
/*]]>*/
</script>
thymeleaf将自动对user对象进行转换,而且转换为javascript中的user对象
删除模板片段使用th:remove属性
th:remove的值如下:
1.all:删除包含标签和所有的孩子。
2.body:不包含标记删除,但删除其所有的孩子。
3.tag:包含标记的删除,但不删除它的孩子。
4.all-but-first:删除所有包含标签的孩子,除了第一个。
5.none:什么也不做。这个值是有用的动态评估。
<tr class="odd" th:remove="all">
something-------
</tr>
th:remove属性可以采取任何Thymeleaf标准表达式,只要允许它返回一个字符串值(all, tag, body, all-but-first or none)。
这意味着删除可能是有条件的:
<a href="/something" th:remove="${condition}? tag : none">Link text not to be removed</a>
th:remove
把null
等同于 none
,所以下面和上面的其实是一样的
<a href="/something" th:remove="${condition}? tag">Link text not to be removed</a>
因此,如果${condition}
is 是false,将返回null,因此没有删除会被执行。
Removing template fragments
th:remove 为了静态显示时提供充分的数据,但是在模板被解析后,又不需要这些模拟的数据,需要将其删除
可选属性:
th:remove="all", 删除所有
th:remove="all-but-first",删除所有,但保留第一个
th:remove="body", 删除内容,但保留标签
th:remove="tag", 删除标签,但保留内容
在Java世界的MVC框架里,使用的视图技术不少,最基本的是JSP,还有知名的FreeMarker和Velocity等模板引擎。Thymeleaf也是一款优秀的模板引擎,它在HTML5/XHTML的视图层表现的很好,也能在离线情况下处理任何XML文件。它是完全可以替代JSP+JSTL的。
下面是来自于Thymeleaf官方的Q&A:
Q: 和FreeMarker,Velocity相比,Thymeleaf表现得怎样呢?
A:FreeMarker和Velocity都是软件领域杰出的作品,但它们在解决模板问题上的处理哲学和Thymeleaf不一样。
Thymeleaf强调的是自然模板,也就是允许模板作为产品原型使用(笔者注:因为其后缀名就是.html,可以直接在浏览器打开),而FreeMarker和Velocity不行。并且Thymeleaf的语法更简洁、更和目前Web开发的趋势相一致。其次,从架构的角度看,FreeMarker和Velocity更像个文本处理器,所以它们能够处理很多类型的内容,而Thymeleaf是基于XML的,只能处理XML格式的数据。因此这样看,FreeMarker和Velocity更通用些,但恰恰如此,Thymeleaf更能利用XML的特性,尤其是在Web应用中。
spring-boot-web-ui及thymeleaf基本使用
视图控制层代码demo如下:
1. @Controller
2. @RequestMapping("/")
3. public class MessageController {
4. private final MessageRepository messageRepository;
5.
6. @Autowired
7. public MessageController(MessageRepository messageRepository) {
8. this.messageRepository = messageRepository;
9. }
10.
11. @RequestMapping
12. public ModelAndView list() {
13. Iterable<Message> messages = this.messageRepository.findAll();
14. return new ModelAndView("messages/list", "messages", messages);
15. }
16.
17. @RequestMapping("{id}")
18. public ModelAndView view(@PathVariable("id") Message message) {
19. return new ModelAndView("messages/view", "message", message);
20. }
21.
22. @RequestMapping(params = "form", method = RequestMethod.GET)
23. public String createForm(@ModelAttribute Message message) {
24. return "messages/form";
25. }
26.
27. @RequestMapping(method = RequestMethod.POST)
28. public ModelAndView create(@Valid Message message, BindingResult result,
29. RedirectAttributes redirect) {
30. if (result.hasErrors()) {
31. return new ModelAndView("messages/form", "formErrors", result.getAllErrors());
32. }
33. message = this.messageRepository.save(message);
34. redirect.addFlashAttribute("globalMessage", "Successfully created a new message");
35. return new ModelAndView("redirect:/{message.id}", "message.id", message.getId());
36. }
37.
38. @RequestMapping("foo")
39. public String foo() {
40. throw new RuntimeException("Expected exception in controller");
41. }
42.
43.}
注:@Controller:1:spring的控制层。2:spring的注解之一放在类名之前3:spring配置文件中如果配置了扫描包路径,自动检测该注释的类并注入。4:spring控制层可以接收请求,并且返回响应。
@RequestMapping:用户请求路径是http://localhost:8080/项目名/类的@RequestMapping的value值/方法的@RequestMapping的value值。
@Autowired:依赖注入。
@PathVariable:rest访问方式获取参数传递
ModelAndView:一次性返回model和view2个对象,有7个构造函数,用来设定返回对象和视图,也可以用set方法设置。
@ModelAttribute:获取页面传递参数。也可以这样用
1. @ModelAttribute("user")
2. public User addAccount() {
3. return new User("jz","123");
4. }
5.
6. @RequestMapping(value = "/helloWorld")
7. public String helloWorld(@ModelAttribute("user") User user) {
8. user.setUserName("jizhou");
9. return "helloWorld";
10.}
@SessionAttributes("user")用户同上只是使用范围不同而已。
RedirectAttributes:我的理解是controller控制层跳转到控制层传递参数用的。
@Valid:对实体类的一个验证。验证符合jpa的标准。要和BindingResult result配合使用,如果验证不通过的话,result.hasErrors(),跳转 。如一个实体类标准:
1. import javax.validation.constraints.Min;
2. import javax.validation.constraints.NotNull;
3. import org.hibernate.validator.constraints.NotBlank;
4.
5. public class User {
6.
7. private String username;
8.
9. private String password;
10.
11. private int age;
12.
13. @NotBlank(message="用户名不能为空")
14. public String getUsername() {
15. return username;
16. }
17.
18. public void setUsername(String username) {
19. this.username = username;
20. }
21.
22. @NotNull(message="密码不能为null")
23. public String getPassword() {
24. return password;
25. }
26.
27. public void setPassword(String password) {
28. this.password = password;
29. }
30.
31. @Min(value=10, message="年龄的最小值为10")
32. public int getAge() {
33. return age;
34. }
35.
36. public void setAge(int age) {
37. this.age = age;
38. }
39.
40.}
最后个方法就是抛出页面异常.
html主要用ThyMeleaf标签,Thymeleaf是一个XML/XHTML/HTML5模板引擎,可用于Web与非Web环境中的应用开发。它是一个开源的Java库,基于Apache License 2.0许可,由Daniel Fernández创建,该作者还是Java加密库Jasypt的作者。
form.html代码如下:
1. <!DOCTYPE html>
2. <html xmlns:th="http://www.thymeleaf.org"
3. xmlns:layout="http://www.ultraq.net.nz/web/thymeleaf/layout"
4. layout:decorator="layout">
5. <head>
6. <title>Messages : Create</title>
7. </head>
8. <body>
9. <h1 layout:fragment="header">Messages : Create</h1>
10. <div layout:fragment="content"
11. class="container">
12. <form id="messageForm"
13. th:action="@{/(form)}"
14. th:object="${message}"
15. action="#"
16. method="post">
17. <div th:if="${#fields.hasErrors('*')}"
18. class="alert alert-error">
19. <p th:each="error : ${#fields.errors('*')}"
20. th:text="${error}">
21. Validation error
22. </p>
23. </div>
24. <div class="pull-right">
25. <a th:href="@{/}" href="messages.html">
26. Messages
27. </a>
28. </div>
29. <label for="summary">Summary</label>
30. <input type="text"
31. th:field="*{summary}"
32. th:class="${#fields.hasErrors('summary')} ? 'field-error'"/>
33. <label for="text">Message</label>
34. <textarea
35. th:field="*{text}"
36. th:class="${#fields.hasErrors('text')} ? 'field-error'"></textarea>
37. <div class="form-actions">
38. <input type="submit" value="Create"/>
39. </div>
40. </form>
41. </div>
42. </body>
43.</html>
list.html代码如下:
1. <!DOCTYPE html>
2. <html xmlns:th="http://www.thymeleaf.org"
3. xmlns:layout="http://www.ultraq.net.nz/web/thymeleaf/layout"
4. layout:decorator="layout">
5. <head>
6. <title>Messages : View all</title>
7. </head>
8. <body>
9. <h1 layout:fragment="header">Messages : View all</h1>
10. <div layout:fragment="content" class="container">
11. <div class="pull-right">
12. <a href="form.html" th:href="@{/(form)}">Create Message</a>
13. </div>
14. <table class="table table-bordered table-striped">
15. <thead>
16. <tr>
17. <td>ID</td>
18. <td>Created</td>
19. <td>Summary</td>
20. </tr>
21. </thead>
22. <tbody>
23. <tr th:if="${messages.empty}">
24. <td colspan="3">
25. No messages
26. </td>
27. </tr>
28. <tr th:each="message : ${messages}">
29. <td th:text="${message.id}">1</td>
30. <td th:text="${#calendars.format(message.created)}">
31. July 11, 2012 2:17:16 PM CDT
32. </td>
33. <td>
34. <a href="view.html"
35. th:href="@{'/' + ${message.id}}"
36. th:text="${message.summary}">
37. The summary
38. </a>
39. </td>
40. </tr>
41. </tbody>
42. </table>
43. </div>
44. </body>
45.</html>
view.html代码如下:
1. <html xmlns:th="http://www.thymeleaf.org"
2. xmlns:layout="http://www.ultraq.net.nz/web/thymeleaf/layout"
3. layout:decorator="layout">
4. <head>
5. <title>Messages : View</title>
6. </head>
7. <body>
8. <h1 layout:fragment="header">Messages : Create</h1>
9. <div layout:fragment="content"
10. class="container">
11. <div class="alert alert-success"
12. th:if="${globalMessage}"
13. th:text="${globalMessage}">
14. Some Success message
15. </div>
16. <div class="pull-right">
17. <a th:href="@{/}" href="list.html">
18. Messages
19. </a>
20. </div>
21. <dl>
22. <dt>ID</dt>
23. <dd id="id" th:text="${message.id}">123</dd>
24. <dt>Date</dt>
25. <dd id="created"
26. th:text="${#calendars.format(message.created)}">
27. July 11, 2012 2:17:16 PM CDT
28. </dd>
29. <dt>Summary</dt>
30. <dd id="summary"
31. th:text="${message.summary}">
32. A short summary...
33. </dd>
34. <dt>Message</dt>
35. <dd id="text"
36. th:text="${message.text}">
37. A detailed message that is longer than the summary.
38. </dd>
39. </dl>
40. </div>
41. </body>
42.</html>
注th标签的引用就是首先要注入标签头,xmlns:th="http://www.thymeleaf.org"放入html标签内就可以了,
# 代表 获取对象 从 messages bundle 也就是消息的资源本地化文件
$ 表示从model里面获取
1. <div class="col-sm-9">
2. <input type="text" th:field="*{id}" placeholder="Order Id" class="col-xs-10 col-sm-5" />
3. <p style="color:red" th:if="${#fields.hasErrors('*{id}')}" th:errors="*{id}"></p>
4. </div>
th:fragment=“public” 相当于include标签
th:each="user : ${users}" 相当于c:foreach 使用时候
如上面
<tr th:each="user : ${users}">
<td th:text="${user.id}">01</td>
<td th:text="${user.name}">朱遇平</td>
<td th:text="${user.xx}">java</td>
<td th:text="${user.xx}">程序员</td>
</tr>
th:href="@{/}"动态设置url参数
<form action="#"th:action="@{/users/add}" th:object="${myuser}"method="post">
这里th:Object表示表单与 改myuser注入的实体映射,
在表单 th:field="*{id} 则表示 该表单的值 与 myuser的id绑定
th:if="${#fields.hasErrors('*')}"
th:if="${#strings.isEmpty(status)}"
${not #strings.isEmpty(status)}
if判断显示。
1. <div class="col-sm-9">
2. <input type="text" th:field="*{id}" placeholder="Order Id" class="col-xs-10 col-sm-5" />
3. <p style="color:red" th:if="${#fields.hasErrors('*{id}')}" th:errors="*{id}"></p>
4. </div>
th:errors错误信息显示如上图
http://blog.csdn.net/pdw2009/article/details/44410659
数据访问模式:
${...},变量引用模式,比如${myBean.property},如果用springDialect,则使用的是springEL,如果不用spring,则用的ognl。
*{...},选择表达式,一般是th:object之后,直接取object中的属性。当没有选取对象时,其功能等同${...},*{firstName}也等同于${#object.firstName},#object代表当前选择的对象。
@{...}链接url的表达式。th:href="@{/xxx/aa.do(id=${o.id})",会自动进行url-encoding的处理。@{...}内部可以是需要计算的表达式,比如:
th:href=”@{'/details/'+${user.login}(orderId=${o.id})}"
#{...},i18n,国际化。
需要注意的:
#{${welcomeMsgKey}(${session.user.name})}:i18n message支持占位。各个表达式支持嵌套。
Eclipse下,html中thymeleaf自动提示的设定
在SpringMvc配置thymeleaf时,遇到html中输入th: 没有自动提示的现象,
打开eclipse的插件安装,Help—>Installationsnew SoftWare—>add
插件地址为: http://www.thymeleaf.org/eclipse-plugin-update-site/
一路next,最后重启Eclipse即可
http://www.cnblogs.com/java-zhao/p/5502398.html
http://www.oschina.net/question/779083_2148086
https://yq.aliyun.com/articles/25409
<!-- thymeleaf -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!--
devtools可以实现页面热部署(即页面修改后会立即生效,这个可以直接在application.properties文件中配置spring.thymeleaf.cache=false来实现),
实现类文件热部署(类文件修改后不会立即生效),实现对属性文件的热部署。
即devtools会监听classpath下的文件变动,并且会立即重启应用(发生在保存时机),注意:因为其采用的虚拟机机制,该项重启是很快的
-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional><!-- optional=true,依赖不会传递,该项目依赖devtools;之后依赖myboot项目的项目如果想要使用devtools,需要重新引入-->
</dependency>
1. devtools reload的原理:
2. 用两个ClassLoader去加载类,一个加载器加载第三库的jar这些jar很少更改,另外一个restart ClassLoader加载你正在开发的资源。这样,当文件更改时,restart ClassLoader会被throw away,一个新的restart ClassLoader会生成加载开发的类文件。这样的加载机制比冷启动快很多。
· 默认情况下,/META-INF/maven,/META-INF/resources,/resources,/static,/templates,/public这些文件夹下的文件修改不会使应用重启,但是会重新加载(devtools内嵌了一个LiveReload server,当资源发生改变时,浏览器刷新)。
· 如果想改变默认的设置,可以自己设置不重启的目录:spring.devtools.restart.exclude=static/**,public/**,这样的话,就只有这两个目录下的文件修改不会导致restart操作了。
· 如果要在保留默认设置的基础上还要添加其他的排除目录:spring.devtools.restart.additional-exclude
如果想要使得当非classpath下的文件发生变化时应用得以重启,使用:spring.devtools.restart.additional-paths,这样devtools就会将该目录列入了监听范围。
http://blog.jobbole.com/72992/
http://www.thymeleaf.org/doc/tutorials/2.1/usingthymeleaf.html#what-is-thymeleaf
热部署:
1.build.gradle
1.1.引入jar包,添加配置
"org.springframework.boot:spring-boot-starter-thymeleaf",
"org.springframework.boot:spring-boot-devtools:1.3.0.RELEASE"
1.2.bootRun {
addResources = true
} ####如果没有该项配置,devtools不会起作用,即应用不会restart,###但不添加似乎也是可以使用的
2. application.yml
spring.thymeleaf.cache:false
3.通过System
.
setProperty
(
"spring.devtools.restart.enabled"
,
"false"
);
关闭自动重启
4.代码配置
@Configuration
public class GTVGApplication {
private static TemplateEngine templateEngine;
static {
initializeTemplateEngine();
}
private static void initializeTemplateEngine() {
ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver();
// XHTML is the default mode, but we set it anyway for better
// understanding of code
templateResolver.setTemplateMode("XHTML");
// This will convert "home" to "/WEB-INF/templates/home.html"
templateResolver.setPrefix("/WEB-INF/templates/");
templateResolver.setSuffix(".html");
// Template cache TTL=1h. If not set, entries would be cached until
// expelled by LRU
templateResolver.setCacheTTLMs(3600000L);
templateEngine = new TemplateEngine();
templateEngine.setTemplateResolver(templateResolver);
}
}
标签具体使用及对比
http://blog.csdn.net/pdw2009/article/details/44701127
传统标签使用
<form:inputText name="userName"value="${user.name}"/>
改为
<input type="text" name="userName" value="James Carrot" th:value="${user.name}" />
1. 引入jar包
maven:在pom文件中加入引用的包
<dependency>
<groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactI>
</dependency>
gradle:在build文件中加入引用的包
org.springframework.boot:spring-boot-starter-thymeleaf
2. 配置文件
在spring-boot下,默认约定了Controller试图跳转中thymeleaf模板文件的的前缀prefix是”classpath:/templates/”,后缀suffix是”.html”
这个在application.properties配置文件中是可以修改的 (可以在类里面指定,也可以在yml配置文件里面配置,由项目配置决定)
如下配置可以修改试图跳转的前缀和后缀
spring.thymeleaf.prefix: /templates/
spring.thymeleaf.suffix: .html
#清除模版引擎中的缓存,页面修改后不需要重启
项目得打成war包
3. 引擎常用基础点
1、在html页面中引入thymeleaf命名空间,即<htmlxmlns:th=http://www.thymeleaf.org></html>,此时在html模板文件中动态的属性使用th:命名空间修饰
2、引用静态资源文件,比如CSS和JS文件,语法格式为“@{}”,如@{/js/bootstrap/bootstarp.js }会引入/static目录下的/js/bootstrap/bootstarp.js文件
3、访问spring-mvc中model的属性,语法格式为“${}”,如${user.id}可以获取model里的user对象的id属性
4、循环,在html的标签中,加入th:each=“value:${list}”形式的属性,如<span th:each=”user:${users}”></span>可以迭代users的数据
5、判断,在html标签中,加入th:if=”表达式”可以根据条件显示html元素
<span th:if="${not #lists.isEmpty(blog.publishTime)}">
<span id="publishtime" th:text="${#dates.format(blog.publishTime,'yyyy-MM-ddHH:mm:ss')}"></span>
</span>
以上代码表示若blog.publishTime时间不为空,则显示时间
6、时间的格式化,
${#dates.format(blog.publishTime,'yyyy-MM-ddHH:mm:ss')}
表示将时间格式化为”yyyy-MM-ddHH:mm:ss”格式化写法与Java格式化Date的写法是一致的。
7、字符串拼接,有两种形式
比如拼接这样一个URL:/blog/delete/{blogId}
第一种:th:href="'/blog/delete/' + ${blog.id}"
第二种:th:href="${'/blog/delete/' + blog.id}"