目录:
-
- [1. Thymeleaf "标准表达式" :](#1. Thymeleaf "标准表达式" :)
-
-
- [{ } : 变量表达式 ( 从 "上下文" 中获取 "变量值")](#{ } : 变量表达式 ( 从 "上下文" 中获取 "变量值"))
- [*{ } : 选择变量表达式 ( 从 "被选定对象" 中获取 "变量值")](#*{ } : 选择变量表达式 ( 从 "被选定对象" 中获取 "变量值"))
- [#{ } : 消息表达式 ( 主要用于 "国际化内容" 的 "替换和展示" )](#{ } : 消息表达式 ( 主要用于 "国际化内容" 的 "替换和展示" ))
- [@{ } : 链接表达式 ( 使用该表达式会生成一个 "URL字符串" )](#@{ } : 链接表达式 ( 使用该表达式会生成一个 "URL字符串" ))
- [~{ } : 片段表达式 ( 引入页面中的 "模板片段" )](#~{ } : 片段表达式 ( 引入页面中的 "模板片段" ))
-
- [2. Thymeleaf "内置对象"](#2. Thymeleaf "内置对象")
- [3. Thymeleaf "基本使用"](#3. Thymeleaf "基本使用")
-
- [Thymeleaf 模板 的 "基本配置"](#Thymeleaf 模板 的 "基本配置")
- [静态资源 的 "访问"](#静态资源 的 "访问")
- [4. Spring Boot 与 Thymeleaf模板引擎 的 "整合使用"](#4. Spring Boot 与 Thymeleaf模板引擎 的 "整合使用")
-
- [① 创建项目](#① 创建项目)
- [② 编写配置文件](#② 编写配置文件)
- [③ 创建 Web 控制类](#③ 创建 Web 控制类)
- [④ 创建 "模板页面" 并引入 "静态资源文件"](#④ 创建 "模板页面" 并引入 "静态资源文件")
- [⑤ 效果测试](#⑤ 效果测试)
- [5. 使用 Thymeleaf "配置国际化页面" ( Spring Boot 国际化功能实现 )](#5. 使用 Thymeleaf "配置国际化页面" ( Spring Boot 国际化功能实现 ))
-
- [① 创建项目](#① 创建项目)
- [② 创建 Web 控制类](#② 创建 Web 控制类)
- [③ 编写 "多语言国际化文件"](#③ 编写 "多语言国际化文件")
- [④ 编写 "全局配置文件" ( 指定 自定义的 "语言配置文件" 来 替代 "默认的语言配置文件" )](#④ 编写 "全局配置文件" ( 指定 自定义的 "语言配置文件" 来 替代 "默认的语言配置文件" ))
- [⑤ 定制 "区域信息解析器"](#⑤ 定制 "区域信息解析器")
- [⑥ 定制 "国际化" "视图页面"](#⑥ 定制 "国际化" "视图页面")
- [⑦ 整合效果测试](#⑦ 整合效果测试)

作者简介 :一只大皮卡丘,计算机专业学生,正在努力学习、努力敲代码中! 让我们一起继续努力学习!
该文章参考学习教材 为:
《Spring Boot企业级开发教程》 黑马程序员 / 编著文章以课本知识点 + 代码为主线,结合自己看书学习过程中的理解和感悟 ,最终成就了该文章
文章用于本人学习使用 , 同时希望能帮助大家。
欢迎大家点赞👍 收藏⭐ 关注💖哦!!!
(侵权可联系我,进行删除,如果雷同,纯属巧合)
1. Thymeleaf "标准表达式" :
Thymeleaf 模板引擎 提供了 多种标准表达式语法 ,具体语法内容如下 :
表达式语法 说明 ${...} 变量表达式 ,表示 从 后端 传递 到 前端的 模型 ( 也称 "** 上下文** " ) 获取 的 "指定名称"的 变量 的 值。 *{...} 选择变量表达式 ,一般用于从 "被选定对象" 中 获取 "变量值 " ( 而不是从 "上下文" 中获取 变量值 ) ,如果没有选定对象 ,则 和变量表达式一样。 #{...} 消息表达式,#{...}表达式 用于从 消息源 (message sources )中 检索本地化的** 消息** 。 #{...}表达式 通常用于 替换静态文本 ,这些消息 可以存储在 外部的属性文件 ( 如 .properties文件 )中,并由 Thymeleaf 在 渲染时 动态解析和 插入 。** ps** : ① 主要用于 "国际化内容 " 的 "替换和展示 ", 其 一般是结合 "国际化配置 "的相关知识点 一起使用 的。 ② 通过 "消息表达式 " 来从 消息源 ( 如 : .properties文件 ) 中获得 "属性值"。 @{...} 链接表达式,该表达式 用于 构建 URL。使用该表达式 将会 生成一个 URL字符串,可以是一个** 绝对 URL** ,也可以是一个 相对于当前上下文 的 URL。这个表达式 通常在 HTML 的 href 、src 、action等属性 中使用功能 ,通过该功能 来 动态生成链接 或 资源的 URL。 ~{...} 片段表达式 ,用于 引用页面中的** 一个模板片段** ( 到别 的页面中 ),该表达式 一般配合th:insert 或 th:replace 标签使用。 在上面表格中列举了 Thymeleaf 模板引擎 最常用的简单表达式语法,并对这些语法进行了功能说明。除此之外,Thymeleaf 还提供了 其他更多的语法支持 ,例如 文本表达式 、 算术表达式 、布尔表达式 、比较表达式 等。
${ } : 变量表达式 ( 从 "上下文" 中获取 "变量值")
${...} : 表达式 ,表示 从 后端 传递 到 前端的 模型 ( 称为 "** 上下文** " ) 中获取 的 "指定名称"的 变量 的 值 。( 从"上下文 " 中 获取 "变量值" ), 例子代码如 :
html<!DOCTYPE html> <!-- 配置开启"Thymeleaf模板引擎页面开发 "--> <!-- xmlns:th="http://www/thymeleaf.org" 表示引入"Thymeleaf模板引擎" --> <html lang="en" xmlns:th="http://www/thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Thymeleaf中的的 ${...} 变量表达式</title> </head> <body> <!-- ${title} : Thymeleaf变量表达式,表示从后端传递到前端的模型 (也称:上下文)中获取"指定名称"的变量的值 th:text : Thymeleaf标签,表示"动态显示/动态修改"该标签中的值 ( 会进行HTML"转义",确保为"纯文本内容") th:text="${title}" : 如果"上下文"中有title变量的值,则动态修改标签中的值;没有没有该变量值,则p标签显示的值还是"默认文本内容" --> <p th:text="${title}"> 默认标题 </p> </body> </html>
上述代码示例 使用了Thymeleaf模板 的 变量表达式 : ${...} 用来 动态设置 / 动态修改 p标签 的 值 ,如果 ① 当前程序未启动 或 ② 上下文中不存在 title变量 ,则 p标签 显示的值 为 "默认标题 " ( 显示默认文本值 )。
如果当前上下文中 存在title变量并且程序已经启动 ,当前p标签中的 默认文本内容 将会被 title 变量 的 值所 "替换" ,从而达到在 Thymeleaf模板引擎页面 中 "动态修改/替换 " 文本的效果。
*{ } : 选择变量表达式 ( 从 "被选定对象" 中获取 "变量值")
选择变量表达式和 变量表达式 "用法类似 ",一般用于从"被选定对象" 中 获取 "** 属性值** "/ "变量值 " ( 而不是从 "上下文" 中获取属性值 ) ,如果没有选定对象 ,则 和变量表达式一样,示例代码如下 :
two.html :
html<!DOCTYPE html> <!-- 配置开启"Thymeleaf模板引擎页面开发 "--> <!-- xmlns:th="http://www/thymeleaf.org" 表示引入"Thymeleaf模板引擎" --> <html lang="en" xmlns:th="http://www/thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Thymeleaf中的的 *{...} 选择变量表达式</title> </head> <body> <!-- th:object : 模板片段设置一个"中心对象",使得你可以在模板中方便地 "访问"该对象的属性,而"无需每次"都写出完整的表达式。 th:text : 动态修改标签文本内容 ${} : 变量表达式,表示从"上下文"中获取"变量值" *{} : 选择变量表达式,从"被选定的对象"中获得"变量值"/"属性值" ${#object.firstName} : 使用Thymeleaf的内置对象object获取当前上下文对象中的firstName属性值 user为存储在session中的对象 --> <div th:object="${session.user}"> <p>Name: <span th:text="${#object.firstName}">姓</span></p> <p>Surname: <span th:text="*{lastName}">名</span></p> <p>Nationnality: <span th:text="*{nationality}">国籍</span></p> </div> </body> </html>
ThymeleafController.java :
java@Controller public class ThymeleafController { @GetMapping("/toTwo") public String toTwo(HttpSession session) { //存储一个对象在Session中,前端获得该对象的数据信息 User user = new User(); user.setFirstName("张"); user.setLastName("三"); user.setNationality("中国"); session.setAttribute("user",user); return "two"; //返回值为: String类型,返回一个视图页面给前端 } }
html<!-- @{ } : 链接表达式,该表达式最后会生成一个URL字符串 th:href : 为href属性赋值 --> <a href="details.html" th:href="@{/order/details(orderId=${orderId})}">view</a>
上述代码中 ,链接表达式@{ } 分别编写 了 绝对链接地址 和 相对链接地址 。在 有参表达式 中,需要按照 :
@{ 路径 (参数名称=参数值 , 参数名称=参数值 ...) } 的 形式编写 ,同时该 参数的值可以使用** 变量表达式来传递动态参数值**。
#{ } : 消息表达式 ( 主要用于 "国际化内容" 的 "替换和展示" )
消息表达式 : 主要用于 Thymeleaf 模板页面 国际化内容的** 动态"替换" 和 "展示"** 。使用消息表达式 #{...} 进行 国际化设置时, 还** 需要提供一些国际化配置文件**。
通过 "消息表达式 " 来从 消息源 ( 如 : .properties文件 ) 中获得 "属性值 " ,其 一般是结合 "国际化配置 "的相关知识点 一起使用 的。例子可参考下面的具体案例。
@{ } : 链接表达式 ( 使用该表达式会生成一个 "URL字符串" )
链接表达式,用于 构建 URL。一般用于 "页面跳转"或者 " 资源的引入 " , 使用该表达式 将会 生成一个 URL字符串,可以是一个** 绝对 URL** ,也可以是一个 相对于当前上下文 的 URL。这个表达式 通常在 HTML 的 href 、src 、action等属性 中使用功能 ,通过该功能 来 动态生成链接或 资源的 URL。同时** 链接表达式在Web开发中占据着非常重要的地位** 。示范代码如下 :
four.html :
html<!DOCTYPE html> <!-- 配置开启"Thymeleaf模板引擎页面开发 "--> <!-- xmlns:th="http://www/thymeleaf.org" 表示引入"Thymeleaf模板引擎" --> <html lang="en" xmlns:th="http://www/thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Thymeleaf中的的 @{...} 链接表达式</title> </head> <body> <!-- @{} : 链接表达式,使用该表达式会生成一个URL字符串 ${} : 变量表达式,从上下文中获得"变量值" th:href : 动态设置href属性的值 --> <a th:href="@{ ${url} }">view</a> </body> </html>
ThymeleafController.java :
java@Controller public class ThymeleafController { @GetMapping("/toFour") public String toFour(Model model) { //存储一个对象在Session中,前端获得该对象的数据信息 model.addAttribute("url", "/toDetails"); return "biaodashi/four"; //返回值为: String类型,返回一个视图页面给前端 } @GetMapping("/toDetails") public String toDetails() { return "biaodashi/Details"; //返回值为: String类型,返回一个视图页面给前端 } }
Details.html :
html<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Details.html</title> </head> <body> 123 </body> </html>
~{ } : 片段表达式 ( 引入页面中的 "模板片段" )
片段表达式 ,用于 引用页面中的** 一个模板片段** ( 到别 的页面中 ),该表达式 一般配合 th:fragment标签 、th:insert标签 或 th:replace 标签使用 。
代码例子如下 :footer.html :
html<!DOCTYPE html> <!--配置开启Thymeleaf模板引擎页面开发--> <html lang="en" xmlns:th="http://www/thymeleaf.org"> <head> <meta charset="UTF-8"> <title>footer.html</title> </head> <body> <footer th:fragment="footer"> <p>这是一个公共的footer部分。</p> </footer> </body> </html>
index.html :
html<!DOCTYPE html> <!--配置开启Thymeleaf模板引擎页面开发--> <html lang="en" xmlns:th="http://www/thymeleaf.org"> <head> <meta charset="UTF-8"> <title>主页面</title> <h1>欢迎来到主页面</h1> </head> <body> <!-- 使用 ~{} :片段表达式引入 "footer模板 " --> <!-- ~{footer :: footer} : 获得footer.html中的 footer片段 --> <div th:insert="~{footer :: footer}"></div> <p>这是主页面的内容。</p> </body> </html>
上述代码中 ,使用 th:insert 属性将 footer片段模板引用到该** <div>标签中。第一个footer** 为 模板名称 ( 视图页面 的名称 ),第二个footer 为模版片段 的名称。
2. Thymeleaf "内置对象"
Thymeleaf 为 变量所在域 提供了一些 内置对象 。
Thymeleaf 的"内置对象 "指的是在 Thymeleaf 模板引擎中 预定义的 一组对象 ( 不用什么配置,就已经存在的、** 可直接使用的对象** ),这些 对象 可以 直接在模板中使用 ,而 无需通过后端代码显式地 传递给模板。
Thymeleaf内置对象提供了对** 常用功能的访问** ,如 ① 访问上下文数据 、② 执行常见的字符串 、③ 数值操作 、④ 格式化日期和时间 、⑤ 国际化等。
Thymeleaf内置对象的作用主要是** 简化模板的 开发过程,可以在模板** 中直接使用这些内置的功能 ,而 不需要编写额外的后端代码 。通过内置对象 ,开发者可以更高效地在模板中处理数据 、控制流程 、显示消息等。
常见 的 Thymeleaf "内置对象" 有 :
Thymeleaf 内置对象 描述 #ctx 或 #context 上下文"对象" #vars 上下文"变量" #locale 上下文区域设置 / 本地化"对象" #dates 日期工具 对象 #calendars 日历工具 对象 #numbers 数字工具 对象 #strings 字符串工具 对象 #arrays 数组工具 #lists 列表工具
Thymeleaf 内置对象 描述 #sets 集合工具 #maps 映射工具 #request 或 #httpServletRequest ( 仅限Web Context ) HTTP "请求" 对象 #response 或 #httpServletResponse ( 仅限Web Context ) HTTP "响应" 对象 #session ( 仅限Web Context ) HttpSession对象 #ServletContext ( 仅限Web Context ) ServletContext对象 结合上述内置对象的说明 ,假设要在 Thymeleaf模板引擎页面中 动态获取 "当前国家信息" ,可以使用** #locale 内置对象** ,示例代码如下 :
html<!DOCTYPE html> <!-- 配置开启"Thymeleaf模板引擎页面开发 "--> <!-- xmlns:th="http://www/thymeleaf.org" 表示引入"Thymeleaf模板引擎" --> <html lang="en" xmlns:th="http://www/thymeleaf.org"> <head> <meta charset="UTF-8"> <title>#locale内置对象的使用</title> </head> <body> The locale country is : <span th:text="${#locale.country}">US</span> </body> </html>
上述代码中,使用 ${#locale.country} :动态获取当前用户所在国家信息 ,其中 <span>标签内 默认内容为 : US(美国) ,程序启动后 通过浏览器查看当前页面时 ,Thymeleaf会通过浏览器语言设置来 识别当前用户所在国家信息,从而实现** 动态替换**。
3. Thymeleaf "基本使用"
Thymeleaf 模板 的 "基本配置"
在 Spring Boot 项目 中使用 Thyneleaf模板 ,首先必须保证 引入Thymeleaf依赖 ,示例代码如下:
html<!-- thymeleaf模板引擎 的 依赖启动器 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
其次 ,在 全局配置文件中 配置 Thymeleaf 模板的一些** 参数** 。一般 Web 项目都** 会使用下列配置** :
properties#开启Thymeleaf模版缓存,默认为true (启用模版缓存),开发中通常会关闭,保证"项目调试过程中"数据能够及时响应,上线稳定后应保持为true spring.thymeleaf.cache = true #设置模版编码 spring.thymeleaf.encoding=UTF-8 #应用于模版的模版模式 spring.thymeleaf.mode=HTML5 #指定模版页面存储路径 ( 默认为:classpath:/templates/ ) spring.thymeleaf.prefix=classpath:/resources/templates/ #指定模版页面名称的后缀 ( 默认为: .html ) spring.thymeleaf.suffix=.html
静态资源 的 "访问"
开发 Web 应用 时,难免需要 使用静态资源 。Spring Boot默认设置 了 静态资源的 访问路径默认将** /**所有访问** 映射到** 以下目录**:
(1) classpath:/META-INF/resources/ :
项目类路径 下的 META-INF 文件夹 下的 resources 文件夹下 的 所有文件。
(2) classpath:/resources/ :
项目类路径 的 resources 文件夹下 的 所有文件。
(3) classpath:/static/ : 项目类路径下 的 static 文件夹 下的 所有文件。
(4) classpath:/public/ : 项目类路径下 的 public 文件夹下 的 所有文件。
使用 Spring Initializr 方式创建的 SprinBoot 项目会** 默认生成一个 resources 目录,在resources 目录** 中 新建 public 、resources 、static 3个子目录 ,Spring Boot默认会依次 从 public 、resources 、static 里面 查找静态资源。
4. Spring Boot 与 Thymeleaf模板引擎 的 "整合使用"
① 创建项目
关于 静态资源的** 项目结构** :
② 编写配置文件
properties#开启Thymeleaf模版缓存,默认为true (启用模版缓存),开发中通常会关闭,保证"项目调试过程中"数据能够及时响应,上线稳定后应保持为true spring.thymeleaf.cache=false
③ 创建 Web 控制类
在 项目中创建** controller 层包** ,并在该包 下创建一个用于前端模板页面 动态数据替换 效果测试的 访问实体类 : LoginController ,代码文件如下所示 :
LoginController.java :
javaimport org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import java.util.Calendar; @Controller //加入到IOC容器中 public class LoginController { /** * 获取并封装当前年份,跳转到登录页 login.html */ @GetMapping("/toLoginPage") public String toLoginPage(Model model) { //通过Model来向前端传递数据 model.addAttribute("currentYear", Calendar.getInstance().get(Calendar.YEAR)); return "login"; //返回值为String类型,可用于返回一个"视图页面" } }
④ 创建 "模板页面" 并引入 "静态资源文件"
在 resources 的 templates 目录 下创建一个 用户登录 的 模板页面 : login.html ,代码如下所示 :
login.html :
html<!DOCTYPE html> <!-- 配置开启Thymeleaf模板引擎页面开发 --> <html lang="en" xmlns:th="http://www/thymeleaf.org"> <head> <meta charset="UTF-8"> <!-- th:href : 设置href属性的值 @{} : 链接表达式,该表达式得到一个URL字符串,赋值给href属性 --> <link th:href="@{/login/css/bootstrap.min.css}" rel="stylesheet"> <link th:href="@{/login/css/signin.css}" rel="stylesheet"> <title>用户登录页面</title> </head> <body class="text-center"> <!-- 用户登录form表单--> <form class="form-signin"> <!-- th:src : 设置src属性的值 @{} : 链接表达式,该表达式得到一个URL字符串,赋值给src属性 --> <img class="mb-4" th:src="@{/login/img/login.jpg}" width="72" height="72"> <h1 class="h3 mb-3 font-weight-normal" >请登录</h1> <input type="text" class="form-control" placeholder="用户名" required="" autofocus=""> <input type="password" class="form-control" placeholder="密码" required=""> <div class="checkbox mb-3"> <label> <input type="checkbox" value="remember-me"/>记住我</label> </div> <button class="btn btn-lg btn-primary btn-block" type="submit" >登录</button> <!-- th:text : 动态修改标签中的值 ${} : 从"上下文"中获得指定变量的值 th:text="${currentYear}" : 用后端传来的currentYear变量的值来动态替换2018 --> <p class="mt-5 mb-3 text-muted">@<span th:text="${currentYear}">2018</span>-<span th:text="${currentYear}+1">2019</span></p> </form> </body> </html>
⑤ 效果测试
项目启动成功后 ,浏览器上访问 : http://localhost:8080/toLoginPage 进入登录页面 ,效果如下图所示 :
5. 使用 Thymeleaf "配置国际化页面" ( Spring Boot 国际化功能实现 )
① 创建项目
关于 静态资源的** 项目结构** :
② 创建 Web 控制类
在 项目中创建** controller 层包** ,并在该包 下创建一个用于前端模板页面 动态数据替换 效果测试的 访问实体类 : LoginController ,代码文件如下所示 :
LoginController.java :
javaimport org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import java.util.Calendar; @Controller //加入到IOC容器中 public class LoginController { /** * 获取并封装当前年份,跳转到登录页 login.html */ @GetMapping("/toLoginPage") public String toLoginPage(Model model) { //通过Model来向前端传递数据 model.addAttribute("currentYear", Calendar.getInstance().get(Calendar.YEAR)); return "login"; //返回值为String类型,可用于返回一个"视图页面" } }
③ 编写 "多语言国际化文件"
在项目的类路径 resources 下创建名称为 i18n 的 文件夹 ,并在该文件夹中 根据需要编写对应的多语言国际化文件 : login.properties 、login_zh_CN.properties 和 login_en_US.properties 文件,代码文件如下所示 :
( 注意点 :
其他语言国际化文件 的 名称必须** 严格按照** : " 文件前缀名_语言代码_国家代码.properties " 的 形式命名"。)login.properties :
propertieslogin.tip=请登录 login.username=用户名 login.password=密码 login.rememberme=记住我 login.button=登录
login_zh_CN.properties : ( 文件前缀名_语言代码_国家代码.properties )
propertieslogin.tip=请登录 login.username=用户名 login.password=密码 login.rememberme=记住我 login.button=登录
login_en_US.properties :( 文件前缀名_语言代码_国家代码.properties )
propertieslogin.tip=please sign in login.username=Username login.password=Password login.rememberme=Remember me login.button=Login
login.properties 为自定义默认语言配置文件 ,login_zh_CN.properties为** 自定义中文国际化文件** 和 login_en_US.properties 为自定义英文国际化文件。
需要说明的是 ,Spring Boot 默认识别 的 语言配置文件 为 : 类路径 resources 下 的 messages.properties , 其他语言国际化文件的 名称必须** 严格按照** : " 文件前缀名_语言代码_国家代码.properties " 的 形式命名 "。
---( 默认的语言配置文件为 :messages.properties , 此时** 全局配置文件** 中的 "** 国际化文件基础名** " 为 : messages , 当然此时这个配置信息可忽略不配置也可以的 )注意点 :
可通过 全局配置文件 来 修改 默认的语言配置文件 ( 指定自定义的语言配置文件 为 "默认使用 的 语言配置文件")。
④ 编写 "全局配置文件" ( 指定 自定义的 "语言配置文件" 来 替代 "默认的语言配置文件" )
properties# 开启Thymeleaf模版缓存,默认为true (启用模版缓存),开发中通常会关闭,保证"项目调试过程中"数据能够及时响应,上线稳定后应保持为true spring.thymeleaf.cache=false # 配置国际化文件基础名 / 修改"默认的语言配置文件" # 默认的语言配置文件为 : 类路径resources下的 messages.properties文件,现在将其修改为为 类路径resources下 i18n文件夹下的 login.properties ,所以有此时的 "国际化文件基础名"为 login spring.messages.basename=i18n.login
需要说明的是 ,Spring Boot 默认识别 的 语言配置文件 为 : 类路径 resources 下 的 messages.properties , 其他语言国际化文件 的 名称必须** 严格按照** : " 文件前缀名_语言代码_国家代码.properties " 的 形式命名"。
-------( 默认的语言配置文件为 :messages.properties , 此时的** 国际文件基础名为 : messages ,是 可以不用在"全局配置文件"中 配置的 。如果 默认的 语言配置文件修改为 : login.properties** , 那么此时的 "** 国际文件基础名** " 为 : login , 其的** 其他语言国家化文件** 要 "上面要求 " 创建,如 : login_ zh_CN.properties )
上面的 全局配置文件 中,通过 spring.messages.basename = i18n.login ,指定 国际化文件基础名 为 i18文件夹下的 login ( 此时对应的** 默认的 " 语言配置文件** " 为 : login.properties ) , 此时 login表示 多语言文件 的"** 前缀名**"。
如果 开发者完全** 按照** Spring Boot 默认识别机制 ,在项目类路径resources 下 编写 messages.properties等国际化文件, 可以省略国际化文件基础名的配置 。
---( 如果按默认识别机制 在 resources 目录 下 编写 messages.properties等国际化文件 ,就可以 省略 "全局配置文件" 中的配置 )。
⑤ 定制 "区域信息解析器"
在完成上一步 中 多语言国际化文件的 编写和配置后,就可以正式在** 前端页面中 结合Thymeleaf模板相关属性 进行 国际化语言设置** 和 展示 了。
不过这种实现方式默认是 使用** 请求头中的 语言信息** ( 浏览器语言信息 ) 自动 进行 语言切换的,** 有些项目还 会提供手动语言切换的功能** ,这就需要 定制 "区域解析器" 了。
在项目中 创建名 config的包 ,并在该包下创建个 用于定制 "国际化功能区域信息解析器"的自定义配置类 : MyLocalResovel ,代码文件如下所示 :
MyLocaleResolver.java :
javaimport jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.apache.catalina.util.StringUtil; import org.springframework.cglib.core.Local; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.LocaleResolver; import org.thymeleaf.util.StringUtils; import java.util.Locale; @Configuration //标记为配置类 public class MyLocaleResolver implements LocaleResolver { //该配置类用于定制 "国际化功能区域信息解析器" /** * 自定义区域解析方式 : * ① 通过"手动切换"的形式来进行"语言环境"的修改 * ② 如果没有"手动切换",则按照请求头中的 "Accept-Language的语言参数" 信息来进行"语言环境"的修改 * ---不管哪种方式,最后都是将 相关的"语言信息" "作为参数" 来创建 Locale对象,并将该对象作为"返回值" */ @Override public Locale resolveLocale(HttpServletRequest request) { //获取 "页面手动切换" "传递的参数:language" ---手动切换 //language参数的形式为: zh_CN 或 en_US String language = request.getParameter("language"); //获取"请求头"自动传递的语言参数Accept-Language ---根据浏览器信息"自动切换" //Accept-Language的语言参数形式为: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7 String header = request.getHeader("Accept-Language"); Locale locale = null; //如果"手动切换参数"不为空,则根据手动参数进行切换,否则默认根据"请求头"信息切换 if (!StringUtils.isEmpty(language)) { //手动参数不为空,则用"手动参数"来进行"语言设置" // .split() : 根据给定"字符"/"正则表达式"的匹配 "拆分此字符串" String[] split = language.split("_"); //以 _ 来进行拆分,因为language参数的形式为: zh_CN 或 en_US locale = new Locale(split[0], split[1]); } else { //用浏览器中的请求头信息中的language参数来进行"语言设置" //Accept-Language的语言参数形式为: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7 String[] splits = header.split(","); String[] split = splits[0].split("-"); locale = new Locale(split[0], split[1]); } return locale; } @Override public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) { } /** * 将自定义的MyLocaleResolver类 "重新注册"为一个类型为 : LocaleResolver 的 Bean组件 */ @Bean //将方法的返回值对象加入到IOC容器中 public LocaleResolver localeResolver() { return new MyLocaleResolver(); } }
上面的文件代码中 , MyLocalResovel配置类实现了 LocaleResovel接口 , 并重写了 LocaleResove接口 的 resolveLocale( )方法来 解析自定义语言 。使用 @Bean 注解 将 当前配置类 注册成 Spring 容器中** 一个 Bean 组件**。这样就** 可以覆盖默认的 LocaleResolver 组件。在重写的 resoiveLocale( )方法中,可以根据不同的需求切换语言信息** 从而获取请求的参数 ,只有请求参数不为空 时,才可以进行语言的切换。
需要注意的是,在** 请求参数 : language的 语言手动切换组装时,使用的是 下划线这是由 多语言配置文件的 格式决定的 ( 例如 language = 'zh_CN' ) ; 而在 请求头参数Accept-Language** 的 语言自动切换组装时,使用的是** 短横线"_"进行的切割** ,这是由浏览器发送 的 请求头信息 样式决定的 ( 例如 Accept-Language : en-US,en;q=0.9,zh-CN;q=0.8,zh;9=0.7 )。
⑥ 定制 "国际化" "视图页面"
打开项目 templates 模板文件夹 中的用户登录页面 login.html ,结合 Thymeleaf 模板引擎实现国际化功能 ,代码文件如下所示 :
login.html :
html<!DOCTYPE html> <!-- 配置开启Thymeleaf模板引擎页面开发 --> <html lang="en" xmlns:th="http://www/thymeleaf.org"> <head> <meta charset="UTF-8"> <!-- th:href : 设置href属性的值 @{} : 链接表达式,该表达式得到一个URL字符串,赋值给href属性 --> <link th:href="@{/login/css/bootstrap.min.css}" rel="stylesheet"> <link th:href="@{/login/css/signin.css}" rel="stylesheet"> <title>用户登录页面</title> </head> <body class="text-center"> <!-- 用户登录form表单--> <form class="form-signin"> <!-- th:src : 设置src属性的值 @{} : 链接表达式,该表达式得到一个URL字符串,赋值给src属性 --> <img class="mb-4" th:src="@{/login/img/login.jpg}" width="72" height="72"> <!-- #{} : 消息表达式 ,通过该表达式来从"消息源" (如: .properties文件)中获取"属性值",其一般结合"国际化"的相关知识点一起使用 --> <h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}">请登录</h1> <input type="text" class="form-control" th:placeholder="#{login.username}" required="" autofocus=""> <input type="password" class="form-control" th:placeholder="#{login.password}" required=""> <div class="checkbox mb-3"> <!-- [[#{login.rememberme}]] : 使用行内表达式来动态获取国际化文件中的 login.rememberme信息 --> <label> <input type="checkbox" value="remember-me"/>[[#{login.rememberme}]]</label> </div> <button class="btn btn-lg btn-primary btn-block" type="submit" th:text="#{login.button}">登录</button> <!-- th:text : 动态修改标签中的值 ${} : 从"上下文"中获得指定变量的值 th:text="${currentYear}" : 用后端传来的currentYear变量的值来动态替换2018 --> <p class="mt-5 mb-3 text-muted">@<span th:text="${currentYear}">2018</span>-<span th:text="${currentYear}+1">2019</span></p> <a class="btn btn-sm" th:href="@{/toLoginPage(language='zh_CN')}">中文</a> <a class="btn btn-sm" th:href="@{/toLoginPage(language='en_US')}">English</a> </form> </body> </html>
⑦ 整合效果测试
项目启动成功后 ,浏览器上访问 : http://localhost:8080/toLoginPage 进入登录页面 ,效果如下图所示 :
( 如有乱码问题 ,可对 IDEA开发工具 中的 Properties文件编码格式进行** 设置 / 或其他原因导致的乱码**,可自行解决 )