目录
一、Thymeleaf简介
二、集成Thymeleaf
三、Thymeleaf常用语法
一、Thymeleaf简介
Thymeleaf是面向Web和独立环境的现代服务器Java模板引擎,能够处理HTML,XML,JavaScript,CSS甚至纯文本。
Thymeleaf旨在提供一个优雅的、高度可维护的创建模板的方式。为了实现这一目标,Thymeleaf建立在自然模板的概念上,将其逻辑注入到模板文件中,不会影响模板设计原型。这改善了设计的沟通,弥合了设计和开发团队之间的差距。
Thymeleaf从设计之初就遵循Web标准——特别是HTML5标准,如果需要,Thymeleaf允许创建完全符合HTML5验证标准的模板。
二、集成Thymeleaf
通过Maven新建一个名为springboot-thymeleaf
的项目。
1.引入依赖
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-thymeleaf
org.projectlombok
lombok
1.18.8
2.编写配置文件
spring:
thymeleaf:
# 在构建URL时用于查看名称的前缀,默认为classpath:/templates/
prefix: classpath:/templates/
# 在构建URL时附加到视图名称的后缀,默认为.html
suffix: .html
# 模板模式,默认为HTML
mode: HTML
# 模板文件编码,默认为UTF-8
encoding: UTF-8
# 是否启用模板缓存,默认为true,表示启用,false不启用
cache: false
# 在呈现模板之前是否检查模板存在与否,默认为true
check-template: true
# 是否检查模板位置存在与否,默认为true
check-template-location: true
更多的配置可以查看ThymeleafProperties
类:
3.准备模板
首先按照配置文件中配置的模板前缀在resources
下创建一个templates
目录,用于存放模板。然后创建如下名为hello.html
的模板:
Hello Thymeleaf
th:text文本替换会转义html标签,不解析html
th:utext文本替换不会转义html标签,会解析html
标签中的xmlns:th="http://www.thymeleaf.org
声明使用Thymeleaf标签。th:text
属性会计算表达式的值将结果设置为标签的标签体。但它会转义HTML标签,HTML标签会直接显示在浏览器上。th:utext
属性不会转义HTML标签,HTML标签会被浏览器解析。${hello}
是一个变量表达式,它包含一个OGNL(Object-Graph Navigation Language)的表达式,它会从上下文中获取名为hello
的变量,然后在模板上进行渲染。
4.Controller层
创建Controller并将模板中要获取的变量设置到Model对象中,如果Controller类上使用的是@Controller
注解,则可以返回跟模板名称相同的字符串(不包括前缀和后缀),视图解析器会解析出视图具体地址并生成视图,然后返回给前端控制器进行渲染:
package com.rtxtitanv.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
/**
* @author rtxtitanv
* @version 1.0.0
* @name com.rtxtitanv.controller.ThymeleafController
* @description ThymeleafController
* @date 2021/7/3 19:23
*/
@Controller
public class ThymeleafController {
@GetMapping("/hello")
public String hello(Model model) {
model.addAttribute("hello", "Hello Thymeleaf ");
return "hello";
}
}
运行项目,浏览器访问http://localhost:8080/hello,发现数据成功渲染到模板:
如果Controller类上使用的是@RestController
注解,则需要将视图添加到ModelAndView对象中并返回:
package com.rtxtitanv.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
/**
* @author rtxtitanv
* @version 1.0.0
* @name com.rtxtitanv.controller.TestController
* @description TestController
* @date 2021/7/3 19:43
*/
@RequestMapping("/test")
@RestController
public class TestController {
@GetMapping("/hello")
public ModelAndView hello() {
ModelAndView modelAndView = new ModelAndView("hello");
modelAndView.addObject("hello", "hello thymeleaf ");
return modelAndView;
}
}
运行项目,浏览器访问http://localhost:8080/test/hello,发现数据成功渲染到模板:
三、Thymeleaf常用语法
1.标准表达式
(1)变量表达式
${}
表达式实际上是在上下⽂中包含的变量的映射上执行的OGNL(Object-Graph Navigation Language)对象。例如:${session.user.name}
。
在Spring MVC启用的应用程序中,OGNL将被替换为SpringEL,但其语法与OGNL相似(实际上,在大多数常见情况下完全相同)。
模板variable.html
如下:
User实体类:
package com.rtxtitanv.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author rtxtitanv
* @version 1.0.0
* @name com.rtxtitanv.model.User
* @description User
* @date 2021/7/3 19:37
*/
@AllArgsConstructor
@NoArgsConstructor
@Data
public class User {
private Long id;
private String username;
private String password;
}
ThymeleafController
中新增以下方法:
@GetMapping("/variable")
public String variable(Model model) {
model.addAttribute("user", new User(1L, "赵云", "qwe123"));
return "variable";
}
效果:
在${}
表达式中还可以使用基本对象和工具类对象。这些对象都以#
开头。基本对象:
#ctx
:上下文对象。
#vars
:上下文变量。
#locale
:上下文区域设置。
#request
:(仅在Web Contexts中)HttpServletRequest对象。
#response
:(仅在Web上下⽂中)HttpServletResponse对象。
#session
:(仅在Web上下⽂中)HttpSession对象。
#servletContext
:(仅在Web上下⽂中)ServletContext对象。
工具类对象:
#execInfo
:有关正在处理的模板的信息。
#messages
:用于在变量表达式中获取外部化消息的方法,与使用#{}语法获取的方式相同。
#uris
:转义URL/URI部分的方法。
#conversions
:执行配置的转换服务的方法。
#dates
:java.util.Date
对象的方法。
#calendars
:类似于#dates
,但对应java.util.Calendar
对象。
#numbers
:用于格式化数字对象的方法。
#strings
:字符串对象的方法。
#objects
:一般对象的方法。
#bools
:布尔相关方法。
#arrays
:Array的方法。
#lists
:List的方法。
#sets
:Set的方法。
#maps
:Map的方法。
#aggregates
:在数组或集合上创建聚合的方法。
#ids
:处理可能重复的id属性的方法。
这些对象的详细方法可以查看官方文档:https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#appendix-a-expression-basic-objects。
(2)选择表达式(星号语法)
星号语法*{}
计算所选对象而不是整个上下文的表达式。也就是说,只要没有选定的对象(选定对象为th:object
属性的表达式结果),$
和*
语法就会完全相同。
模板asterisk.html
如下:
选择表达式(星号语法)
*语法
$语法
$和*混合使用
对象选择到位时所选对象将作为#object表达式变量可⽤于$表达式
没有执⾏对象选择时$和*语法等效
ThymeleafController
中新增以下方法:
@GetMapping("/asterisk")
public String star(Model model) {
model.addAttribute("user", new User(1L, "赵云", "qwe123"));
return "asterisk";
}
效果:
(3)URL表达式
URL表达式的语法为@{}
。使用th:href
属性可以对链接进行渲染。
模板url.html
如下:
注意:
th:href
属性会计算要使用的URL并将该值设置为
标签的
href
属性。URL中允许使用表达式的URL参数,设置多个参数将以
,
分隔。
URL路径中也可以使用变量模板,即可以设置rest风格的参数。
/
开头的相对URL将自动以应用上下文名称为前缀。如果cookie未启用或还未知道,可能会在相对URL中添加
;jsessionid=...
后缀以便保留会话。这被称为URL重写。
th:href
属性允许在模板中有一个静态的
href
属性,这样在直接打开原型模板时,模板链接可以被导航。
ThymeleafController
中新增以下方法:
@GetMapping("/url")
public String url(Model model) {
model.addAttribute("user", new User(1L, "赵云", "qwe123"));
model.addAttribute("url", "/user/update");
return "url";
}
效果:
从上到下依次点击5个链接和提交表单的结果:
(4)字面量
字面量(Literals)分为:
文本文字(Text literals):包含在单引号之间的字符串,可以包含任何字符,其中的单引号需要\'转义。
数字字面量(Number literals):数字。
布尔字面量(Boolean literals):包含true和false。
null字面量(The null literal):null。
文本符号(Literal tokens):数字,布尔和null字面量实际是文本符号的特殊情况,文本符号不需要引号包围,只允许使用字母(A-Z和a-z)、数字(0-9)、括号、点(.)、连字符(-)和下划线(_)。
模板literal.html
如下:
字面量
文本文字: ⽂本文字只是包含在单引号之间的字符串,可以包含任何字符,其中的单引号需要\'转义
数字字面量: 数字字面量就是数字
布尔字面量: 布尔字⾯量包含true和false
null字面量: Thymeleaf标准表达式语法中也可以使⽤null字⾯量
文本符号: 数字,布尔和null字面量实际上是⽂本符号的特殊情况
ThymeleafController
中新增以下方法:
@GetMapping("/literal")
public String literal(Model model) {
model.addAttribute("flag", false);
return "literal";
}
效果:
(5)文本操作
这里的文本操作包含:
追加文本(Appending texts),即字符串连接:无论是文本常量还是表达式结果都可以使用+
运算符进行拼接。
字面替换(Literal substitutions):字面替换可以轻松地对包含变量值的字符串进行格式化,而不需要在字面后加+
,这些替换必需用|
包围。使用字面替换也可以实现和追加文本相同的效果。
模板text.html
如下:
文本操作(字符串连接)
方式1(+):
方式2(|):
方式3(+与|混合):
方式4(#strings.concat):
方式5(#strings.append):
方式6(#strings.prepend):
方式7(#strings.arrayJoin):
ThymeleafController
中新增以下方法:
@GetMapping("/text")
public String text(Model model) {
model.addAttribute("user", new User(1L, "赵云", "qwe123"));
return "text";
}
效果:
(6)运算符
运算符:
算数运算符:+
、-
、*
、/
(div
)、%
(mod
)。
比较运算符:>
(gt
)、<
(lt
)、>=
(ge
)、<=
(le
)。
等值运算符:==
(eq
)、!=
(ne
)。
布尔运算符:and
、or
、!
(not
)。
模板operation.html
如下:
运算符
算术运算符:+、-、*、/(div)、%(mod)
比较和等值运算符:>(gt)、<(lt)、>=(ge)、<=(le)、==(eq)、!=(ne)
x > 5:
y le 2:
(x * y) < 50:
y ge x:
x == y:
x ne y:
布尔运算符:and、or、!(not)
y lt x and -x gt -y:
-x <= -y or y >= x:
!(x != y):
not (x eq y):
ThymeleafController
中新增以下方法:
@GetMapping("/operation")
public String operator(Model model) {
model.addAttribute("x", 10);
model.addAttribute("y", 3);
return "operation";
}
效果:
(7)条件表达式
条件表达式:
If-then:(if) ? (then)
。if
表达式结果为true
,则条件表达式结果为then
表达式结果,否则为null。
If-then-else:(if) ? (then) : (else)
。if
表达式结果为true
,则条件表达式结果为then
表达式结果,否则为else
表达式结果。
Default(默认表达式):(value) ?: (defaultvalue)
。value
不为null,则结果为value
,否则结果为defaultvalue
。
模板conditional-expr.html
如下:
条件表达式、默认表达式、_符号
成绩是否及格:
成绩是否是正常数据:
成绩对应的级别:
年龄:
默认表达式嵌套示例:
年龄: 没有年龄数据
ThymeleafController
中新增以下方法:
@GetMapping("/conditional/expr")
public String conditionExpr(Model model) {
model.addAttribute("grade", 85);
model.addAttribute("age", null);
return "conditional-expr";
}
效果:
grade
设置为-1,age
设置为20。效果如下:
2.设置属性
使用th:attr
属性可以设置标签的任何属性值,th:attr
只需要通过一个表达式将值赋给对应的属性,并且还可以通过,
分隔的形式设置多个属性值。不过使用th:attr
设置属性不太优雅,所以用的不多,一般使用其他th:*属性的形式设置指定属性,例如要设置value
属性,可以使用th:value
,要设置action
属性,可以使用th:action
,要设置href
属性,可以使用th:href
,具体都有哪些属性可以这样设置可以参考官方文档。
th:attrprepend
和th:attrappend
可以给属性设置前缀和后缀。Thymeleaf标准方言中还有两个特定的附加属性th:classappend
和th:styleappend
,用于将CSS的class或style样式追加到元素中,而不覆盖现有属性。
HTML中有布尔属性这个概念,布尔属性没有值,并且一旦这个布尔属性存在则意味着属性值为true。但是在XHTML中,这些属性只取它本身作为属性值。例如checked
属性。Thymeleaf标准方言允许通过计算条件表达式的结果来设置这些属性的值,如果条件表达式结果为true,则该属性将被设置为其固定值,如果评估为false,则不会设置该属性。
Thymeleaf支持使用HTML5自定义属性语法data-{prefix}-{name}
来处理模板,这不需要使用任何命名空间。Thymeleaf使这种语法自动适用于所有的方言(不仅仅是标准的方法)。
模板attr.html
如下:
ThymeleafController
中新增以下方法:
@GetMapping("/attr")
public String attr(Model model) {
model.addAttribute("success", "成功");
model.addAttribute("active", true);
return "attr";
}
效果:
f12查看源码可见属性设置成功:
active
设置为false。checkbox没有选中,查看源码也没有设置checked
属性:
3.条件判断
th:if
属性可以通过判断一个条件是否满足,来决定是否将模板片段显示在结果中,只有满足条件才将模板片段显示在结果中。而th:unless
属性则正好与th:if
属性相反。通过th:switch
和th:case
可以在模板中使用一种与Java中的Swicth语句等效的结构有条件地显示模板内容。
模板conditional.html
如下:
条件判断
年龄大于18并且用户等级等于6,则显示此元素
与if条件判断相反,年龄小于18或用户等级不等于6,则显示此元素
表达式的值不为null,th:if判定此表达式的值为true
表达式的值为null,th:if判定此表达式的值为false
值是数字并且不为0,判定此表达式的值为true
值是数字但为0,判定此表达式的值为false
值是一个字符并且不为0,判定此表达式的值为true
值是一个字符串,不是false,off或no,判定此表达式的值为true
值是字符串false,判定此表达式的值为false
值是字符串off,判定此表达式的值为false
值是字符串no,判定此表达式的值为false
青铜
白银
黄金
铂金
钻石
王者
无段位
注意:
th:if
属性不仅仅以布尔值作为判断条件。它将按照以下规则判定指定的表达式值为true:
如果表达式的值不为null。(如果表达式的值为null,
th:if
判定此表达式的值为false。)
如果值为布尔值,则为true。如果值是数字且不为0。
如果值是一个字符且不为0。如果值是一个字符串,不是"false",“off"或"no”。
如果值不是布尔值,数字,字符或字符串。
同一个Switch语句中只要第一个th:case
的值为true,则其他的th:case
属性将被视为false。Switch语句的default选项指定为th:case=“*”
。
ThymeleafController
中新增以下方法:
@GetMapping("/conditional")
public String condition(Model model) {
Map map = new HashMap<>();
map.put("age", 10);
map.put("userLevel", 6);
map.put("rank", 5);
model.addAllAttributes(map);
return "conditional";
}
效果:
age
设置为20,userLevel
设置为6,rank
设置为0。效果如下:
4.循环迭代
使用th:each
属性可以迭代以下对象:
任何实现java.util.Iterable
接口的对象。
任何实现java.util.Enumeration
接口的对象。
任何实现java.util.Iterator
接口的对象。其值将被迭代器返回,不需要在内存中缓存所有值。
任何实现java.util.Map
接口的对象。迭代map时,迭代变量将是java.util.Map.Entry
类型。
任何数组。
任何其将被视为包含对象本身的单值列表。
(1)迭代List
模板each-list.html
如下:
循环迭代List
id
username
password
index
count
size
current
even
odd
first
last
状态变量是在使用th:each
时Thymeleaf提供的一种用于跟踪迭代状态的机制。状态变量在th:each
属性中通过在迭代变量之后直接写其名称来定义,用,
分隔。与迭代变量一样,状态变量的作用范围也是th:each
属性所在标签定义的代码片段中。如果没有显式地设置状态变量,Thymeleaf总是会创建一个名为迭代变量名加上Stat
后缀的状态变量。
ThymeleafController
中新增以下方法:
@GetMapping("/each/list")
public String eachList(ModelMap model) {
List users = new ArrayList<>();
users.add(new User(1L, "刘备", "123132"));
users.add(new User(2L, "关羽", "321231"));
users.add(new User(3L, "张飞", "213312"));
model.addAttribute("users", users);
return "each-list";
}
效果:
(2)迭代Map
模板each-map.html
如下:
循环迭代Map
id
username
password
key
index
count
size
current
even
odd
first
last
id
username
password
key
index
count
size
current
even
odd
first
last
ThymeleafController
中新增以下方法:
@GetMapping("/each/map")
public String eachMap(Model model) {
Map map = new HashMap<>(16);
map.put("user1", new User(1L, "刘备", "123132"));
map.put("user2", new User(2L, "关羽", "321231"));
map.put("user3", new User(3L, "张飞", "213312"));
model.addAttribute("userMap", map);
return "each-map";
}
效果:
(3)迭代Array
模板each-array.html
如下:
循环迭代Array
id
username
password
index
count
size
current
even
odd
first
last
ThymeleafController
中新增以下方法:
@GetMapping("/each/array")
public String eachArray(Model model) {
User[] users = {new User(1L, "刘备", "123132"), new User(2L, "关羽", "321231"), new User(3L, "张飞", "213312")};
model.addAttribute("users", users);
return "each-array";
}
效果:
5.模板布局
(1)引用模板片段
th:fragment
属性可以用来定义模板片段,th:insert
、th:replace
和th:include
(Thymeleaf3.0不再推荐使用)属性可以引用模板片段。
首先创建一个名为footer.html
的模板文件用来包含模板片段,然后定义一个名为copy1
的片段:
然后在名为layout.html
的模板中引用该片段:
ThymeleafController
中新增以下方法:
@GetMapping("/layout")
public String layout(Model model) {
return "layout";
}
效果:
引用模板片段语法中的~{}
是可选的,以下代码与之前的等价:
效果:
th:insert
、th:replace
和th:include
都能引用模板片段,直接在页面中还看不出三者的区别。为了更明显地看出区别,在footer.html
模板中新增以下片段:
然后在layout.html
模板中分别使用th:insert
、th:replace
和th:include
进行引用:
th:insert将指定片段插⼊到指定宿主标签的标签体中
th:replace实际上⽤指定的⽚段替换其宿主标签
th:include只插⼊此⽚段的内容到指定宿主标签的标签体中
效果:
按F12查看源码可以看出区别:
所以三者区别为:
th:insert
将指定片段插入到指定宿主标签的标签体中。
th:replace
实际上用指定的片段替换其宿主标签。
th:include
只插入此片段的内容到指定宿主标签的标签体中。
引用模板片段的规范语法有以下三种格式:
~{templatename::selector}
:包含在名为templatename的模板上通过指定的selector匹配的片段。selector可以只是一个片段名称。
~{templatename}
:包含名为templatename的整个模板。
~{::selector}
或~{this::selector}
:包含在同一模板中与指定selector匹配的片段。如果在表达式出现的模板上没有找到,模板调用(插入)的堆栈会向最初处理的模板(root)遍历,直到selector在某个层次上匹配。
templatename和selector都可以是表达式。模板片段中可以包含任何th:*属性,一旦在目标模板中引用了片段,这些属性将被计算并且它们能够引用目标模板中定义的任何上下文变量。
通过th:replace="~{footer}"
可以引用整个footer.html
:
效果:
在layout.html
模板中新增以下几个片段:
在layout.html
模板中引用frag和input片段:
效果:
selector写成一个条件表达式,可以通过条件来决定引用的片段:
将变量flag
设置到Model中:
model.addAttribute("flag", true);
效果:
flag
设置为fasle时的效果:
由于标签选择器的强大功能,没有使用th:fragment
属性的片段可以通过id
属性来引用。在footer.html
模板中新增以下片段:
没有使用th:fragment属性的片段可以通过id属性来引用
在layout.html
模板中引用该片段:
可以通过id属性来引⽤没有th:fragment属性的⽚段
效果:
(2)参数化的模板片段
th:fragment
定义的片段可以指定一组参数。在footer.html
模板中新增以下片段:
在layout.html
模板中分别用以下两种语法引用该片段:
引用定义了参数的模板片段语法1
引用定义了参数的模板片段语法2,可以改变参数顺序
将变量var1
和var2
设置到Model中:
model.addAttribute("var1", "参数1");
model.addAttribute("var2", "参数2");
效果:
即使片段没有定义参数,也可以调用片段中的局部变量。在footer.html
模板中新增以下片段:
在layout.html
模板中分别通过以下语法调用片段中的局部变量:
没有定义参数的模板片段中的局部变量的调用语法1
没有定义参数的模板片段中的局部变量的调用语法2
引用定义参数的模板片段的两种语法中,第一种语法不能调用没有定义参数的片段中的局部变量,只有第二种语法能调用。
注意:片段的局部变量规范 - 无论是否具有参数签名 - 都不会导致上下文在执行前被清空。片段仍然能访问调用模板中正在使用的每个上下文变量。
效果:
使用th:assert
可以进行模板内部断言,它可以指定逗号分隔的表达式列表,如果每个表达式的结果都为true,则正确执行,否则引发异常。在footer.html
模板中新增以下片段:
在layout.html
模板中引用该片段:
将变量user
设置到Model中:
model.addAttribute("user", new User(1L, "赵云", "qwe123"));
效果: 只将id设置为null,访问模板出现以下异常:
只将username设置为空,访问模板出现以下异常:
只将password设置为空,访问模板出现以下异常:
(3)灵活布局
通过片段表达式不仅可以指定文本类型、数字类型、对象类型的参数,还可以指定标记片段作为参数。这种方式可以使模板布局变得非常灵活。
下面进行一个页面布局的简单模拟测试,首先在templates
下新建一个layout
目录,用于存放一些组件模板。
layout/footer.html
:
layout/header.html
:
layout/left.html
:
在templates
下新建一个基础模板base.html
:
common title
common header
common left
common content
common footer
然后在名为layout-home.html
的模板中引用base.html
中的片段:
ThymeleafController
中新增以下方法:
@GetMapping("/layout/home")
public String layoutHome(Model model) {
return "layout-home";
}
效果:
使用特殊片段表达式~{}
可以指定没有标记。在layout-home.html
中通过以下代码引用base.html
中的片段:
效果:
_
符号也可以用作片段参数。在layout-home.html
中通过以下代码引用base.html
中的片段:
_
符号导致common_div片段中的th:replace="${footer}"
不被执行,从而该div标签使用原型文本。
效果:
~{}
和_
符号可以通过简单优雅的方式实现执行片段的条件插入。在layout-home.html
中通过以下代码引用base.html
中的片段:
参数中的每一个condition
条件可以根据实际业务需求灵活控制。这里为了测试方便,都使用的相同条件。
将变量condition
设置到Model中:
model.addAttribute("condition", false);
效果:
在layout-home.html
中通过以下代码引用base.html
中的片段:
效果:
条件也可以不在参数中进行判断,还在common_div片段的th:replace
属性中进行判断。在layout-home.html
中通过以下代码引用base.html
中的片段:
base.html
中的common_div片段:
Common header
Common left
Common content
Common footer
效果:
6.局部变量
Thymeleaf的局部变量是指定义在模板片段中的变量,该变量的作用域为所在模板片段。th:each
中的迭代变量就是一个局部变量,作用域为th:each
所在的标签范围,可用于该标签内优先级低于th:each
的任何其他th:*属性,可用于该标签的任何子元素。使用th:with
属性可以声明局部变量。
在local.html
模板中使⽤th:with
属性声明局部变量:
ThymeleafController
中新增以下方法:
@GetMapping("/local")
public String local(Model model) {
User[] users = {new User(1L, "刘备", "123132"), new User(2L, "关羽", "321231"), new User(3L, "张飞", "213312")};
model.addAttribute("users", users);
return "local";
}
效果:
局部变量只能在声明的标签内使用。在local.html
模板中新增以下内容:
访问模板会报错:
可以同时定义多个局部变量。在local.html
模板中新增以下内容:
效果:
th:with
属性允许重⽤在同⼀属性中定义的变量。在local.html
模板中新增以下内容:
效果:
7.属性优先级
多个th:*属性在同一个标签中的执行顺序由优先级决定。所有Thymeleaf属性都定义了一个数字优先级,以确定了它们在标签中执行的顺序,数字越小优先级越高:
Order
Feature
Attributes
1
Fragment inclusion
th:insert
th:replace
2
Fragment iteration
th:each
3
Conditional evaluation
th:if
th:unless
th:switch
th:case
4
Local variable definition
th:object
th:with
5
General attribute modification
th:attr
th:attrprepend
th:attrappend
6
Specific attribute modification
th:value
th:href
th:src
...
7
Text (tag body modification)
th:text
th:utext
8
Fragment specification
th:fragment
9
Fragment removal
th:remove
优先级意味着属性位置发生变化,也会得出相同的结果。
8.注释和块
(1)标准HTML/XML注释
标准HTML/XML注释
可以在Thymeleaf模板中的任何地方使用。这些注释中的任何内容都不会被Thymeleaf处理,并将逐字复制到结果中。
这里直接运行项目访问local.html
模板,查看模板源码可见HTML注释没有被处理,保持原样:
(2)ThymeLeaf解析器级注释
解析器级注释块
在Thymeleaf解析时会将
之间的所有内容从模板中删除。当此模板静态打开时,这些注释块可用于显示代码。
修改local.html
模板的其中一个注释为如下内容:
查看源码可见注释已从模板中删除:
(3)Thymeleaf专有注释
Thymeleaf允许定义特殊注释块
,在Thymeleaf解析时会将
标记删除,但不删除标记之间的内容。当此模板静态打开时,会显示注释标记。
修改local.html
模板的其中一个注释为如下内容:
查看源码发现只删除了标记部分,中间的内容保留:
(4)th:block标签
th:block
标签是Thymeleaf标准方言中唯一的元素处理器。th:block
是一个允许模板开发者指定想要的任何属性的属性容器,Thymeleaf会执行这些属性并让这个块消失,但它的内容保留。
模板block.html
如下:
使用th:block
可以轻松地迭代同级标签,例如在中为每个迭代元素创建多个时使用th:block
就很简单。
ThymeleafController
中新增以下方法:
@GetMapping("/block")
public String block(Model model) {
List users = new ArrayList<>();
users.add(new User(1L, "刘备", "123132"));
users.add(new User(2L, "关羽", "321231"));
users.add(new User(3L, "张飞", "213312"));
model.addAttribute("users", users);
return "block";
}
效果:
查看源码:
在和原型注释块结合时很有用:
效果:
9.内联 (1)内联表达式
[[]]
或[()]
中的表达式为内联表达式,可以直接将表达式写入HTML文本。任何在th:text
或th:utext
属性中使用的表达式都可以出现在[[]]
或[()]
中。[[]]
等价于th:text
,会转义html标签;[()]
等价于th:utext
,不会转义html标签。
模板inline.html
如下:
内联
th:text和th:utext
Hello World !
Hello World !
内联表达式
Hello [[${user.username}]] !
Hello [(${user.username})] !
ThymeleafController
中新增以下方法:
@GetMapping("/inline")
public String inline(Model model) {
model.addAttribute("user", new User(1L, "赵云 ", "this is \"pass\" word"));
return "inline";
}
效果:
注意,静态打开模板文件时,内联表达式会显示出来,这样就无法将其作为原型设计了。静态打开inline.html
模板的效果如下:
在有些情况下可能需要禁用内联,比如需要输出[[]]序列时。通过th:inline="none"
可以禁用内联。在模板inline.html
中新增以下内容:
这是一个二维数组:[[1, 2, 3], [4, 5]]
访问模板时会报如下错误:
在刚才的代码中增加禁用内联:
禁用内联
这是一个二维数组:[[1, 2, 3], [4, 5]]
效果:
(2)内联JavaScript
使用th:inline="javascript"
启用内联JavaScript。
在模板inline.html
中新增以下内容:
效果:
查看源码,可见输出的字符串进行了转义,是格式正确的JavaScript字符串,因为使用[[]]
在输出${user.password}
表达式的时候进行了转义:
查看Console中打印的日志:
注释掉let password = [[${user.password}]];
,新增let password = [(${user.password})];
。查看源码,由于[()]
不会进行转义,可见输出的字符串没有转义,是格式错误的JavaScript代码:
查看Console,发现有语法错误:
如果通过附加内联表达式的方式来构建脚本的一部分,可能会需要输出未转义的字符串,所以这个功能也很有用。
内联JavaScript可以通过在注释中包含内联表达式作为JavaScript自然模板。下面注释掉let password = [(${user.password})];
,新增如下代码:
// 在JavaScript注释中包含(转义)内联表达式,Thymeleaf将忽略在注释之后和分号之前的所有内容
let password = /*[[${user.password}]]*/ "default password";
查看源码:
查看Console中打印的日志:
发现"default password"
确实被忽略了。以静态方式打开模板时变量password
的值就为"default password"
了:
JavaScript内联表达式结果不限于字符串,还会自动地将Strings、Numbers、Booleans、Arrays、Collections、Maps、Beans(有getter和setter方法)这些对象序列化为JavaScript对象。下面在Controller中新增以下代码:
Map map = new HashMap<>(16);
map.put("user1", new User(1L, "刘备", "123132"));
map.put("user2", new User(2L, "关羽", "321231"));
map.put("user3", new User(3L, "张飞", "213312"));
model.addAttribute("userMap", map);
script
标签内新增以下代码,Thymeleaf会将userMap对象转换为JavaScript对象:
// userMap为一个Map对象,Thymeleaf会将其转换为JavaScript对象
let userMap = /*[[${userMap}]]*/ null;
console.log("userMap:", userMap);
// 遍历userMap
for (let key in userMap) {
console.log(key + ": " + "{id: " + userMap[key].id
+ ", username: " + userMap[key].username + ", password: " + userMap[key].password + "}");
}
查看源码发现Thymeleaf已经将其转换为JavaScript对象:
查看Console中打印的日志:
(3)内联CSS
使用th:inline="css"
启用内联CSS。
在模板inline.html
中新增以下内容:
将变量element
、align
和color
设置到Model中:
model.addAttribute("element", "h1");
model.addAttribute("align", "center");
model.addAttribute("color", "#2876A7");
访问模板,对齐生效,颜色未生效:
查看源码,发现color的值多了一个\
:
这是由于[[]]
会进行转义,所以多了一个\
。这里不需要对其转义,所以需要使用[()]
。将代码修改为color: [(${color})];
。访问模板,发现样式都生效了:
查看源码,没有多出\
了:
内联CSS也允许通过在注释中包含内联表达式作为CSS自然模板,使CSS可以静态和动态的工作。将
的代码修改为如下内容:
模板动态打开时的效果:
查看源码:
以静态方式打开的效果:
查看源码:
10.国际化
这里简单模拟一下国际化功能,通过语言切换应用对应语言的国际化配置文件。
(1)创建国际化配置文件
在resources/i18n
目录下创建如下配置文件。
index.properties
:
user.register=注册
user.login=登录
index.language=语言
index.language.chinese=中文
index.language.english=英文
index_en_US.properties
:
user.register=Register
user.login=Login
index.language=Language
index.language.chinese=Chinese
index.language.english=English
index_zh_CN.properties
:
user.register=注册
user.login=登录
index.language=语言
index.language.chinese=中文
index.language.english=英文
(2)新增配置
在application.yml
中新增以下配置:
spring:
messages:
# 配置消息源的基本名称,默认为messages,这里配置为国际化配置文件的前缀
basename: i18n.index
(3)创建模板
模板i18n.html
如下:
#{}
为消息表达式,用于引用消息字符串。而消息字符串通常保存在外部化文本中,消息字符串形式为key=value,通过#{key}
可以引用特定的消息。而根据不同的语言从与其对应的外部化文本中获取同一个key的消息,可以实现国际化。
(4)配置国际化解析器
package com.rtxtitanv.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.thymeleaf.util.StringUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Locale;
/**
* @author rtxtitanv
* @version 1.0.0
* @name com.rtxtitanv.config.WebConfig
* @description 配置自定义国际化解析器
* @date 2021/7/6 16:25
*/
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Bean
public LocaleResolver localeResolver() {
return new MyLocaleResolver();
}
/**
* 自定义LocaleResolver
*/
public static class MyLocaleResolver implements LocaleResolver {
@Override
public Locale resolveLocale(HttpServletRequest request) {
// 接收语言参数
String lang = request.getParameter("lang");
// 使用默认语言
Locale locale = Locale.getDefault();
// 语言参数不为空就设置为该语言
if (!StringUtils.isEmptyOrWhitespace(lang)) {
String[] s = lang.split("_");
locale = new Locale(s[0], s[1]);
}
return locale;
}
@Override
public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {}
}
}
(5)Controller
@GetMapping(value = {"/index", "/"})
public String index() {
return "i18n";
}
(5)测试
访问模板,默认语言为中文:
点击英文链接切换语言为英文:
点击中文链接切换语言为中文:
11.常用工具类对象
之前在文中已经简单地总结了Thymeleaf中的工具类对象和它的作用。这里结合实例来总结一下常用工具类对象具体方法的使用,由于工具类对象较多,这里就总结Dates、Numbers和Strings的具体使用方法。至于其他对象的方法,可以参考官方文档。
(1)Dates
模板date.html
如下:
工具类对象Dates
格式化日期格式1(format):
格式化日期格式2(format):
获取年(year):
获取月(month):
获取日(day):
获取时(hour):
获取分(minute):
获取秒(second):
获取毫秒(millisecond):
获取月份名称(monthName):
获取星期索引,1为星期日,2为星期1,···,7为星期六(dayOfWeek):
获取星期名称(dayOfWeekName):
创建当前date和time(createNow):
创建当前date,time设置为00:00(createToday):
ThymeleafController
中新增以下方法:
@GetMapping("/dates")
public String dates(Model model) {
model.addAttribute("date", new Date());
return "dates";
}
效果:
(2)Numbers
模板number.html
如下:
工具类对象Numbers
整数格式化 - 设置最小整数位数为3(formatInteger):
整数格式化 - 设置最小整数位数为6(formatInteger):
整数格式化 - 设置千位分隔符为.(formatInteger):
整数格式化 - 设置千位分隔符为,(formatInteger):
整数数组格式化(arrayFormatInteger):
[[${element}]]
小数格式化 - 设置最小整数位数为5且精确保留3位小数位数(formatDecimal)
小数格式化 - 设置千位分隔符为.且小数点分隔符为,(formatDecimal)
货币格式化(formatCurrency):
百分比格式化 - 设置最小整数位数为2且精确保留3位小数(formatPercent):
创建整数数字序列 - 序列从1到10步长为3(sequence):
[[${n}]]
ThymeleafController
中新增以下方法:
@GetMapping("/numbers")
public String numbers(Model model) {
Integer[] numArray = {1000, 666, 88888};
model.addAttribute("num", 99999);
model.addAttribute("num2", 66.6658932);
model.addAttribute("nums", numArray);
return "numbers";
}
效果:
(3)Strings
模板strings.html
如下:
工具类对象Strings
字符串转换(toString):
检查字符串是否为空(isEmpty):
字符串为空时使用默认值(defaultString):
检查字符串是否以指定片段开头(startsWith):
检查字符串是否以指定片段结尾(endsWith):
检查字符串是否包含指定片段(contains):
判断两个字符串是否相等(equals):
判断两个字符串是否相等,忽略大小写(equalsIgnoreCase):
获取字符串长度(length):
字符串转换为大写字母(toUpperCase):
字符串转换为小写字母(toLowerCase):
片段在字符串中的索引(indexOf):
字符串去除空格(trim):
字符串省略(abbreviate):
字符串截取,从指定索引开始截取到末尾(substring):
字符串截取指定开始索引到结束索引之间的部分,不包含结束索引字符(substring):
截取指定字符串第一次出现前的字符串(substringBefore):
截取指定字符串第一次出现后的字符串(substringAfter):
字符串替换(replace):
从字符串头部向前追加(prepend):
从字符串尾部向后追加(append):
字符串连接(concat):
字符串连接(concatReplaceNulls):
字符串拆分(arraySplit):
[[${element}]]
字符串组合(arrayJoin):
随机字符串(randomAlphanumeric):
ThymeleafController
中新增以下方法:
@GetMapping("/strings")
public String strings(Model model) {
model.addAttribute("user", new User(1L, "SpringBoot-Thymeleaf-Strings-Test", ""));
model.addAttribute("str", "SpringBoot Thymeleaf Strings Test");
model.addAttribute("strs", new String[] {"SpringBoot", "Thymeleaf", "Strings", "Test"});
return "strings";
}
效果:
代码示例
Github:https://github.com/RtxTitanV/springboot-learning/tree/master/springboot2.x-learning/springboot-thymeleaf
Gitee:https://gitee.com/RtxTitanV/springboot-learning/tree/master/springboot2.x-learning/springboot-thymeleaf
到此这篇关于SpringBoot2.x 集成 Thymeleaf的文章就介绍到这了,更多相关SpringBoot2.x 集成 Thymeleaf内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
你可能感兴趣的:(SpringBoot2.x 集成 Thymeleaf的详细教程)
FPC在智能眼镜中的应用探索【新立电子】
珠海新立电子科技有限公司
智能眼镜 fpc柔性线路板 fpc软板
在智能穿戴设备领域,智能眼镜具有独特的便携性、交互性和功能性等特点,智能眼镜的设计追求轻薄、美观与高度集成化。传统刚性电路板因体积庞大、难以弯曲,无法满足智能眼镜的复杂结构需求,而FPC其轻薄、柔软、可弯曲的特性,成为智能眼镜电路板的理想选择。在智能眼镜中,FPC的应用无处不在。它不仅是连接显示屏、摄像头、传感器、电池等关键组件,同时还承担着信号传输、电源管理等。例如,在摄像头模块中,FPC将摄像
C进阶 自定义类型
一只自律的鸡
C进阶 c语言 开发语言
目录前言一结构体二结构体的存储三位段四枚举五联合体总结前言我们之前学习的intchardouble......都是内置类型,但是我们今天所学习的是自定义类型,比如联合体,结构体,枚举一结构体结构体是一些值的集合,这些值统称为成员变量,每个成员都是可以用不同的的基本数据类型结构体的使用场景:结构体的意义在于可以进行封装一个整体的所有变量,这个是十分便捷的,这样就可以不用重复的操作进行重复的定义相同的
七个合法学习黑客技术的平台,让你从萌新成为大佬
黑客白帽子黑爷
学习 php 开发语言 web安全 网络
1、HackThisSite提供在线IRC聊天和论坛,让用户交流更加方便。网站涵盖多种主题,包括密码破解、网络侦察、漏洞利用、社会工程学等。非常适用于个人提高网络安全技能2、HackaDay涵盖多个领域,包括黑客技术、科技、工程和DIY等内容,站内提供大量有趣的文章、视频、教程和新闻,帮助用户掌握黑客技术和DIY精神。3、OffensiveSecurity一个专门提供网络安全培训和认证的公司,课程
C 语言文件操作详解
15Moonlight
c语言 开发语言
目录1.什么是文件1.1文件名1.2程序文件1.3数据文件2.文件的打开和关闭2.1流和标准流2.1.1流2.1.2标准流2.2文件指针2.3文件的打开和关闭3.文件的顺序读写3.1顺序读写函数3.2使用示例3.2.1fgetc和fputc3.2.2fgets和fputs3.2.3fscanf和fprintf3.2.4fread和fwrite3.3功能对比3.4scanf/fscanf/sscan
第十一章:服务器信道管理模块
转调
仿Rabbit消息队列 c++ 消息队列
目录第一节:模块介绍第二节:通信协议第三节:信道模块实现3-1.类型别名定义3-2.Channel类3-3.ChannelManager类下期预告:该模块在mqserver目录下实现。第一节:模块介绍服务器信道的作用是处理来自于客户端的各种请求,然后返回一个响应,那么客户端都有哪些请求呢?比如:交换机的声明与创建、队列的声明与创建、绑定与解绑等。请求的种类如此多,信道要怎么识别这些请求,执行对应的
【MySQL | 四、 表的基本查询(增删查改)】
ヾ慈城
mysql android adb
目录表的增删查改Create(创建)表数据的插入替换Retrieve(读取)1.全列查询2.指定列查询3.表达式查询4.为查询结果指定别名5.去重查询WHERE条件查询排序筛选分页查询Update(更新)Delete(删除)删除整张表数据插入查询结果聚合函数groupbyhaving和where的区别1.作用范围不同2.执行顺序不同查询语句执行顺序分析1.**`SELECT`查询语句**2.**`
SQL笔记#数据更新
月吟荧静
SQL笔记 sql 笔记 数据库
一、数据的插入(INSERT语句的使用方法)1、什么是INSERT首先通过CREATETABLE语句创建表,但创建的表中没有数据;再通过INSERT语句向表中插入数据。--创建表ProductInsCREATETABLEProductIns(product_idCHAR(4)NOTNULL,product_nameVARCHAR(100)NOTNULL,product_typeVARCHAR(32
【2025年】全国CTF夺旗赛-从零基础入门到竞赛,看这一篇就稳了!
白帽黑客鹏哥
web安全 CTF 网络安全大赛 python Linux
基于入门网络安全/黑客打造的:黑客&网络安全入门&进阶学习资源包目录一、CTF简介二、CTF竞赛模式三、CTF各大题型简介四、CTF学习路线4.1、初期1、html+css+js(2-3天)2、apache+php(4-5天)3、mysql(2-3天)4、python(2-3天)5、burpsuite(1-2天)4.2、中期1、SQL注入(7-8天)2、文件上传(7-8天)3、其他漏洞(14-15
Java-- 异常--try/catch/finally 的执行顺序
刘小炮吖i
Java后端开发面试题 Java java 开发语言 面试
直接说结论:当catch或者finally中有return语句时,catch和finally代码块之后的程序部分将不会被执行到。如果catch和finally中都存在return语句,最终的返回值将是finally中的return语句所指定的值。无论try代码块中是否出现异常,只要try或catch执行到了return之前,finally代码块都会被执行。为了代码的可读性和健壮性,尽量避免在try
Java中字符流和字节流的区别
刘小炮吖i
Java后端开发面试题 Java java 开发语言
相同点在Java的I/O体系中,字节流和字符流都配备了缓冲机制的实现类,以此显著提升数据读写的效率。字符流:借助BufferedReader和BufferedWriter,它们在处理字符数据时,会将数据先缓存起来,减少与底层数据源或目标的交互次数,从而加速操作。例如,当逐行读取大文本文件时,BufferedReader的缓冲功能能避免频繁的磁盘I/O操作。字节流:BufferedInputStre
SQLite自增列相关内容
秦时明月之君临天下
SQLite sqlite jvm 数据库
文章目录相关知识创建表插入数据查看自增列重置自增列注意事项参考文档相关知识SQLite的自增用法和MySQL类似:使用的关键字是AUTOINCREMENT(MySQL用的是AUTO_INCREMENT)。AUTOINCREMENT关键字会增加额外的CPU、内存、磁盘空间和磁盘I/O开销,如果不是严格需要的话,应该避免使用。它通常是不需要的。在SQLite中,具有INTEGERPRIMARYKEY类
【现代前端框架中本地图片资源的处理方案】
Gazer_S
前端框架 前端 缓存 javascript chrome
现代前端框架中本地图片资源的处理方案前言在前端开发中,正确引用本地图片资源是一个常见但容易被忽视的问题。我们不能像在HTML中那样简单地使用相对路径,因为JavaScript模块中的路径解析规则与HTML不同,且现代构建工具对静态资源有特殊的处理机制。本文将详细探讨在webpack和Vite等构建工具中处理本地图片引用的各种方法。传统方式的局限性在传统开发中,我们可能习惯这样引用图片:constl
Mysql疑难报错排查 - Field ‘XXX‘ doesn‘t have a default value
m0_74823408
面试 学习路线 阿里巴巴 mysql 数据库
项目场景:数据库环境:mysql8;工程使用:MyBatisPlus表情况:问题描述某一个插入语句使用了MyBatisPlus的save方法,因为end_time1end_time2都并没有值,所以在MyBatisPlus默认情况下,并不会在插入语句中提及,最终提取其SQL:INSERTINTOaaaa(serial_no,business_date,market_no,report_code)V
hivePB级迁移方案
我要用代码向我喜欢的女孩表白
数据库 bigdata-大数据专栏 hive
1、评估磁盘空间大小、调整副本数、设置heapsize大小2、distcp-i-skipcrccheck源端到目标端,迁移3、元数据迁移,建表,替换location地址,或者导出db4、表分区修复5、配置增量T-1迁移或者T-26、校验历史分区脚本,表结构,大小,文件数7、根据ditcp不对的,进行补数脚本,删分区,重拉8、任务校验,客户跑完任务后,校验指定分区的count数和内容的md59、任务
Redis Cluster集群详解
高冷小伙
redis 数据库 缓存
数据分片(Sharding)哈希槽(HashSlot)机制:集群将数据划分为16384个哈希槽,每个键通过CRC16(key)%16384计算归属的槽。槽分配给多个主节点,每个节点负责一部分槽(例如:3节点集群中,每个节点可能管理约5461个槽)。动态槽分配:节点增减时,槽可动态迁移,支持在线扩容/缩容(如CLUSTERADDSLOTS命令)。跨槽操作限制:事务、Lua脚本需确保所有键在同一槽(可
解锁高效开发新姿势:Trae AI编辑器深度体验
Williams10
AI工具集 人工智能 编辑器
解锁高效开发新姿势:TraeAI编辑器深度体验在软件开发领域,效率就是生命。字节跳动新推出的AI编辑器Trae,就像一把神奇的钥匙,为开发者打开了高效开发的大门。最近我深入体验了Trae,今天就来和大家分享一下使用感受。文章目录解锁高效开发新姿势:TraeAI编辑器深度体验Trae是什么?核心功能大揭秘实际使用场景展示实用使用教程安装与初始设置项目导入与创建日常使用技巧Trae是什么?Trae是字
深入探讨Ceph:分布式存储架构的未来
深度Linux
ceph 分布式 架构 C/C++
在数字化浪潮汹涌澎湃的当下,数据量呈爆发式增长,传统存储系统在应对海量数据存储、高并发访问以及灵活扩展等方面,逐渐显得力不从心。分布式存储技术应运而生,成为解决现代数据存储难题的关键方案,而Ceph作为分布式存储领域的佼佼者,正日益受到广泛关注和应用。Ceph以其卓越的性能、高可靠性、强大的扩展性以及开源的特性,在众多分布式存储系统中脱颖而出,被广泛应用于云计算、大数据、人工智能等前沿领域。无论是
STL两级空间配置器<128kb(内存池+自由链表)与一级空间配置器(mmap(),allocate())
zjkzjk7711
c++ 链表 开发语言
STL的两级空间配置器(Two-LevelAllocator)STL(标准模板库)中的两级空间配置器(Two-LevelAllocator)是SGISTL(SiliconGraphicsSTL)设计的内存管理机制,用于提高小对象(≤128B)和大对象(>128B)的分配效率。1.什么是两级空间配置器?在SGISTL的__default_alloc_template(SGISTL的默认分配器)中,采
C++ STL std::vector 底层实现
zjkzjk7711
c++
C++STLstd::vector底层实现std::vector是C++STL中最常用的动态数组容器,其底层实现依赖于连续内存块,并采用动态扩容策略来管理内存。1.std::vector的底层数据结构std::vector内部维护三个指针templateclassvector{private:T*_start;//指向数据存储的起始位置T*_finish;//指向数据存储的末尾(size)T*_e
dynamic_cast和static_cast和const_cast
zjkzjk7711
服务器 linux 运维
dynamic_cast在C++中的作用dynamic_cast是C++运行时类型转换(RTTI,Run-TimeTypeIdentification)的一部分,主要用于:安全的多态类型转换检查类型的有效性向下转换(Downcasting)跨类层次的指针或引用转换它只能用于带有虚函数的类,否则dynamic_cast将无法工作。1.dynamic_cast的作用1.1向下转换(Downcastin
transformer中seq_len参数的设置
yuweififi
transformer 深度学习 人工智能
在Transformer模型中,seq_len(序列长度)是一个关键的超参数,下面从不同方面详细介绍它的具体含义和作用:一、基本定义seq_len表示输入到Transformer模型中的序列所允许的最大长度。在自然语言处理任务里,文本会被拆分成一个个的单词、子词或者字符,这些元素构成了一个序列。seq_len就是对这个序列中元素数量的上限规定,它决定了模型输入和输出的维度。二、具体使用输入处理文本
pytorch基础 nn.embedding
yuweififi
pytorch 人工智能 nlp
nn.Embedding是PyTorch中的一个模块,用于创建嵌入层(embeddinglayer),它将离散的索引(例如词汇表中的单词索引)映射为固定大小的稠密向量。这是许多NLP模型(包括Transformer)中的基本组件。示例用法:importtorchimporttorch.nnasnn#定义一个嵌入层vocab_size=10000#词汇表大小embedding_dim=512#嵌入向
pytorch基础-layernormal 与 batchnormal
yuweififi
pytorch 人工智能 python
nn.LayerNorm(层归一化)和nn.BatchNorm(批量归一化)是深度学习中常用的两种归一化方法,都有助于提高模型的训练效率和稳定性,但它们在归一化维度、应用场景、计算方式等方面存在明显区别,以下为你详细介绍:1、归一化维度nn.LayerNorm:对单个样本的特征维度进行归一化。无论输入数据的形状如何,它会计算每个样本在特征维度上的均值和方差,然后进行归一化。例如,对于一个形状为(b
javaweb将上传的图片保存在项目文件webapp下的upload文件夹下
yuren_xia
后端技术 前端技术 web app java tomcat eclipse
前端HTML表单(upload.html)首先,创建一个HTML页面,允许用户选择并上传图片。图片上传上传图片注意:表单的method设置为"post",enctype需设置成"multipart/form-data"2.后端Servlet(UploadServlet.java)接下来,创建一个Servlet来处理文件上传请求,并将上传的图片保存到webapp/load目录下。packagecom
anaconda 创建虚拟环境
yuweififi
环境搭建
1.打开AnacondaPrompt2.创建环境condacreate--nametorchpython=3.62.输入activatetorch安装的anacondapython虚拟环境打开,torch为创建的env名字3.condainfo--env查看所有创建的环境4.关闭环境deactivate切记先激活环境
通俗理解闭包
yuren_xia
前端技术 javascript
JavaScript在ES6之前并没有类的概念,但通过原型链和闭包,开发者可以实现类似继承和封装的功能(原型链实现继承,闭包实现封装)。ES6引入了类语法,但闭包仍然是实现私有数据封装的重要手段之一。另外,使用闭包还可用于保存上下文信息等场景。一、定义从函数角度闭包是指有权访问另一个函数作用域中的变量的函数。即使外部函数已经返回,闭包仍然可以访问外部函数内部的变量。例如:functionouter
【Multipath网络层协议】MPTCP工作原理
码上为赢
Multipath精通之路 multipath MPTCP
常见网络层多路径协议介绍MPTCP(MultipathTCP)MPTCP是在传统TCP基础上进行扩展的协议,它允许在源端和目的端之间建立多个TCP子流,这些子流可以通过不同的网络路径传输数据。例如,一台笔记本电脑同时连接了Wi-Fi网络和以太网网络,当使用MPTCP进行数据传输时,它可以将数据分别通过Wi-Fi和以太网这两条不同的路径发送到目标服务器,从而充分利用两条链路的带宽。LISP(Loca
最好Wordpree+Apache+PHP安装教程
伶星37
apache php 开发语言
前提需要PHP的安装最少需要7.4以上Mysql的安装,直接默认最新版就行APache服务器(HTTP服务器,只有用这个你的软件才能在服务器上运行)安装apache安装sudoaptinstallapache2查看防火墙sudoufwapplist如果有Apache那么就可以直接访问安装PHP版本7.4就可以sudoaptinstallphp-mysqlsudosystemctlrestartap
【C++】:STL详解 —— list类
-元清-
重制C++版 c++ 开发语言
目录list的概念list的构造函数list的大小size()resize()empty()list的插入push_front()和emplace_front()push_back()和emplace_back()insert()和emplace()list的删除pop_front()pop_back()erase()remove()remove_if()unique()clear()list的拼
后端开发技巧:提升代码质量与系统性能
wenbin_java
java spring boot maven mybatis
引言后端开发是构建高效、稳定应用的核心环节。无论是处理复杂的业务逻辑,还是优化系统性能,后端开发者都需要掌握一系列技巧和最佳实践。本文将分享一些实用的后端开发技巧,帮助你提升代码质量、优化系统性能并确保应用的安全性。1.提升代码质量的技巧1.1遵循编码规范统一风格:使用工具(如Checkstyle、ESLint)确保代码风格一致。命名规范:变量、函数、类名应具有描述性,避免使用缩写。1.2模块化与
html
周华华
html
js
1,数组的排列
var arr=[1,4,234,43,52,];
for(var x=0;x<arr.length;x++){
for(var y=x-1;y<arr.length;y++){
if(arr[x]<arr[y]){
&
【Struts2 四】Struts2拦截器
bit1129
struts2拦截器
Struts2框架是基于拦截器实现的,可以对某个Action进行拦截,然后某些逻辑处理,拦截器相当于AOP里面的环绕通知,即在Action方法的执行之前和之后根据需要添加相应的逻辑。事实上,即使struts.xml没有任何关于拦截器的配置,Struts2也会为我们添加一组默认的拦截器,最常见的是,请求参数自动绑定到Action对应的字段上。
Struts2中自定义拦截器的步骤是:
make:cc 命令未找到解决方法
daizj
linux 命令未知 make cc
安装rz sz程序时,报下面错误:
[root@slave2 src]# make posix
cc -O -DPOSIX -DMD=2 rz.c -o rz
make: cc:命令未找到
make: *** [posix] 错误 127
系统:centos 6.6
环境:虚拟机
错误原因:系统未安装gcc,这个是由于在安
Oracle之Job应用
周凡杨
oracle job
最近写服务,服务上线后,需要写一个定时执行的SQL脚本,清理并更新数据库表里的数据,应用到了Oracle 的 Job的相关知识。在此总结一下。
一:查看相关job信息
1、相关视图
dba_jobs
all_jobs
user_jobs
dba_jobs_running 包含正在运行
多线程机制
朱辉辉33
多线程
转至http://blog.csdn.net/lj70024/archive/2010/04/06/5455790.aspx
程序、进程和线程:
程序是一段静态的代码,它是应用程序执行的蓝本。进程是程序的一次动态执行过程,它对应了从代码加载、执行至执行完毕的一个完整过程,这个过程也是进程本身从产生、发展至消亡的过程。线程是比进程更小的单位,一个进程执行过程中可以产生多个线程,每个线程有自身的
web报表工具FineReport使用中遇到的常见报错及解决办法(一)
老A不折腾
web报表 finereport java报表 报表工具
FineReport使用中遇到的常见报错及解决办法(一)
这里写点抛砖引玉,希望大家能把自己整理的问题及解决方法晾出来,Mark一下,利人利己。
出现问题先搜一下文档上有没有,再看看度娘有没有,再看看论坛有没有。有报错要看日志。下面简单罗列下常见的问题,大多文档上都有提到的。
1、address pool is full:
含义:地址池满,连接数超过并发数上
mysql rpm安装后没有my.cnf
林鹤霄
没有my.cnf
Linux下用rpm包安装的MySQL是不会安装/etc/my.cnf文件的,
至于为什么没有这个文件而MySQL却也能正常启动和作用,在这儿有两个说法,
第一种说法,my.cnf只是MySQL启动时的一个参数文件,可以没有它,这时MySQL会用内置的默认参数启动,
第二种说法,MySQL在启动时自动使用/usr/share/mysql目录下的my-medium.cnf文件,这种说法仅限于r
Kindle Fire HDX root并安装谷歌服务框架之后仍无法登陆谷歌账号的问题
aigo
root
原文:http://kindlefireforkid.com/how-to-setup-a-google-account-on-amazon-fire-tablet/
Step 4: Run ADB command from your PC
On the PC, you need install Amazon Fire ADB driver and instal
javascript 中var提升的典型实例
alxw4616
JavaScript
// 刚刚在书上看到的一个小问题,很有意思.大家一起思考下吧
myname = 'global';
var fn = function () {
console.log(myname); // undefined
var myname = 'local';
console.log(myname); // local
};
fn()
// 上述代码实际上等同于以下代码
m
定时器和获取时间的使用
百合不是茶
时间的转换 定时器
定时器:定时创建任务在游戏设计的时候用的比较多
Timer();定时器
TImerTask();Timer的子类 由 Timer 安排为一次执行或重复执行的任务。
定时器类Timer在java.util包中。使用时,先实例化,然后使用实例的schedule(TimerTask task, long delay)方法,设定
JDK1.5 Queue
bijian1013
java thread java多线程 Queue
JDK1.5 Queue
LinkedList:
LinkedList不是同步的。如果多个线程同时访问列表,而其中至少一个线程从结构上修改了该列表,则它必须 保持外部同步。(结构修改指添加或删除一个或多个元素的任何操作;仅设置元素的值不是结构修改。)这一般通过对自然封装该列表的对象进行同步操作来完成。如果不存在这样的对象,则应该使用 Collections.synchronizedList 方
http认证原理和https
bijian1013
http https
一.基础介绍
在URL前加https://前缀表明是用SSL加密的。 你的电脑与服务器之间收发的信息传输将更加安全。
Web服务器启用SSL需要获得一个服务器证书并将该证书与要使用SSL的服务器绑定。
http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后
【Java范型五】范型继承
bit1129
java
定义如下一个抽象的范型类,其中定义了两个范型参数,T1,T2
package com.tom.lang.generics;
public abstract class SuperGenerics<T1, T2> {
private T1 t1;
private T2 t2;
public abstract void doIt(T
【Nginx六】nginx.conf常用指令(Directive)
bit1129
Directive
1. worker_processes 8;
表示Nginx将启动8个工作者进程,通过ps -ef|grep nginx,会发现有8个Nginx Worker Process在运行
nobody 53879 118449 0 Apr22 ? 00:26:15 nginx: worker process
lua 遍历Header头部
ronin47
lua header 遍历
local headers = ngx.req.get_headers()
ngx.say("headers begin", "<br/>")
ngx.say("Host : ", he
java-32.通过交换a,b中的元素,使[序列a元素的和]与[序列b元素的和]之间的差最小(两数组的差最小)。
bylijinnan
java
import java.util.Arrays;
public class MinSumASumB {
/**
* Q32.有两个序列a,b,大小都为n,序列元素的值任意整数,无序.
*
* 要求:通过交换a,b中的元素,使[序列a元素的和]与[序列b元素的和]之间的差最小。
* 例如:
* int[] a = {100,99,98,1,2,3
redis
开窍的石头
redis
在redis的redis.conf配置文件中找到# requirepass foobared
把它替换成requirepass 12356789 后边的12356789就是你的密码
打开redis客户端输入config get requirepass
返回
redis 127.0.0.1:6379> config get requirepass
1) "require
[JAVA图像与图形]现有的GPU架构支持JAVA语言吗?
comsci
java语言
无论是opengl还是cuda,都是建立在C语言体系架构基础上的,在未来,图像图形处理业务快速发展,相关领域市场不断扩大的情况下,我们JAVA语言系统怎么从这么庞大,且还在不断扩大的市场上分到一块蛋糕,是值得每个JAVAER认真思考和行动的事情
安装ubuntu14.04登录后花屏了怎么办
cuiyadll
ubuntu
这个情况,一般属于显卡驱动问题。
可以先尝试安装显卡的官方闭源驱动。
按键盘三个键:CTRL + ALT + F1
进入终端,输入用户名和密码登录终端:
安装amd的显卡驱动
sudo
apt-get
install
fglrx
安装nvidia显卡驱动
sudo
ap
SSL 与 数字证书 的基本概念和工作原理
darrenzhu
加密 ssl 证书 密钥 签名
SSL 与 数字证书 的基本概念和工作原理
http://www.linuxde.net/2012/03/8301.html
SSL握手协议的目的是或最终结果是让客户端和服务器拥有一个共同的密钥,握手协议本身是基于非对称加密机制的,之后就使用共同的密钥基于对称加密机制进行信息交换。
http://www.ibm.com/developerworks/cn/webspher
Ubuntu设置ip的步骤
dcj3sjt126com
ubuntu
在单位的一台机器完全装了Ubuntu Server,但回家只能在XP上VM一个,装的时候网卡是DHCP的,用ifconfig查了一下ip是192.168.92.128,可以ping通。
转载不是错:
Ubuntu命令行修改网络配置方法
/etc/network/interfaces打开后里面可设置DHCP或手动设置静态ip。前面auto eth0,让网卡开机自动挂载.
1. 以D
php包管理工具推荐
dcj3sjt126com
PHP Composer
http://www.phpcomposer.com/
Composer是 PHP 用来管理依赖(dependency)关系的工具。你可以在自己的项目中声明所依赖的外部工具库(libraries),Composer 会帮你安装这些依赖的库文件。
中文文档
入门指南
下载
安装包列表
Composer 中国镜像
Gson使用四(TypeAdapter)
eksliang
json gson Gson自定义转换器 gsonTypeAdapter
转载请出自出处:http://eksliang.iteye.com/blog/2175595 一.概述
Gson的TypeAapter可以理解成自定义序列化和返序列化 二、应用场景举例
例如我们通常去注册时(那些外国网站),会让我们输入firstName,lastName,但是转到我们都
JQM控件之Navbar和Tabs
gundumw100
html xml css
在JQM中使用导航栏Navbar是简单的。
只需要将data-role="navbar"赋给div即可:
<div data-role="navbar">
<ul>
<li><a href="#" class="ui-btn-active&qu
利用归并排序算法对大文件进行排序
iwindyforest
java 归并排序 大文件 分治法 Merge sort
归并排序算法介绍,请参照Wikipeida
zh.wikipedia.org/wiki/%E5%BD%92%E5%B9%B6%E6%8E%92%E5%BA%8F
基本思想:
大文件分割成行数相等的两个子文件,递归(归并排序)两个子文件,直到递归到分割成的子文件低于限制行数
低于限制行数的子文件直接排序
两个排序好的子文件归并到父文件
直到最后所有排序好的父文件归并到输入
iOS UIWebView URL拦截
啸笑天
UIWebView
本文译者:candeladiao,原文:URL filtering for UIWebView on the iPhone说明:译者在做app开发时,因为页面的javascript文件比较大导致加载速度很慢,所以想把javascript文件打包在app里,当UIWebView需要加载该脚本时就从app本地读取,但UIWebView并不支持加载本地资源。最后从下文中找到了解决方法,第一次翻译,难免有
索引的碎片整理SQL语句
macroli
sql
SET NOCOUNT ON
DECLARE @tablename VARCHAR (128)
DECLARE @execstr VARCHAR (255)
DECLARE @objectid INT
DECLARE @indexid INT
DECLARE @frag DECIMAL
DECLARE @maxfrag DECIMAL
--设置最大允许的碎片数量,超过则对索引进行碎片
Angularjs同步操作http请求with $promise
qiaolevip
每天进步一点点 学习永无止境 AngularJS 纵观千象
// Define a factory
app.factory('profilePromise', ['$q', 'AccountService', function($q, AccountService) {
var deferred = $q.defer();
AccountService.getProfile().then(function(res) {
hibernate联合查询问题
sxj19881213
sql Hibernate HQL 联合查询
最近在用hibernate做项目,遇到了联合查询的问题,以及联合查询中的N+1问题。
针对无外键关联的联合查询,我做了HQL和SQL的实验,希望能帮助到大家。(我使用的版本是hibernate3.3.2)
1 几个常识:
(1)hql中的几种join查询,只有在外键关联、并且作了相应配置时才能使用。
(2)hql的默认查询策略,在进行联合查询时,会产
struts2.xml
wuai
struts
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache