thymeleaf模板
https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html
thymeleaf模板引擎入门==>https://www.cnblogs.com/ai-developers/p/7395588.html
1、引入thymeleaf依赖
<!-- 切换thymeleaf版本 --> <properties> <thymeleaf.version>3.0.9.RELEASE</thymeleaf.version> <!-- 布局功能的支持程序 thymeleaf3适配layout2以上版本 , thymeleaf2 适配 layout1版本 --> <thymeleaf-layout-dialect.version>2.2.2</thymeleaf-layout-dialect.version> </properties> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
2、Thymeleaf使用
配置属性类
@ConfigurationProperties(prefix = "spring.thymeleaf") public class ThymeleafProperties { private static final Charset DEFAULT_ENCODING = Charset.forName("UTF-8"); private static final MimeType DEFAULT_CONTENT_TYPE = MimeType.valueOf("text/html"); public static final String DEFAULT_PREFIX = "classpath:/templates/"; public static final String DEFAULT_SUFFIX = ".html"; ...
使用thymeleaf
1、把HTML页面放在classpath:/templates/,thymeleaf就能自动渲染;
2、导入thymeleaf的名称空间 <html lang="en" xmlns:th="http://www.thymeleaf.org">
3、使用thymeleaf语法;
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>成功!</h1> <!--th:text 将div里面的文本内容设置为 --> <div th:text="${person.name}">姓名</div> <div> [[${person.name}]] </div> </body> </html>
thymeleaf语法规则
基本元素
Order优先级从高到低 | Feature | Attributes | 中文说明 |
---|---|---|---|
1 | Fragment inclusion | th:insert th:replace |
片段包含: jsp:include |
2 | Fragment iteration | th:each |
遍历: c:forEach |
3 | Conditional evaluation | th:if th:unless th:switch th:case |
条件判断: c:if |
4 | Local variable definition | th:object th:with |
声明变量: c:set |
5 | General attribute modification | th:attr th:attrprepend th:attrappend |
任意属性修改 支持prepend, append |
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 |
表达式
Simple expressions:(表达式语法)
Variable Expressions: ${...}:
获取变量值;OGNL;
1)、获取对象的属性、调用方法
2)、使用内置的基本对象:
#ctx : the context object.
#vars: the context variables.
#locale : the context locale.
#request : (only in Web Contexts) the HttpServletRequest object.
#response : (only in Web Contexts) the HttpServletResponse object.
#session : (only in Web Contexts) the HttpSession object.
#servletContext : (only in Web Contexts) the ServletContext object.
${session.foo}
3)、内置的一些工具对象:
#execInfo : information about the template being processed.
#messages : methods for obtaining externalized messages inside variables expressions, in the same way as they would be obtained using #{…} syntax.
#uris : methods for escaping parts of URLs/URIs
#conversions : methods for executing the configured conversion service (if any).
#dates : methods for java.util.Date objects: formatting, component extraction, etc.
#calendars : analogous to #dates , but for java.util.Calendar objects.
#numbers : methods for formatting numeric objects.
#strings : methods for String objects: contains, startsWith, prepending/appending, etc.
#objects : methods for objects in general.
#bools : methods for boolean evaluation.
#arrays : methods for arrays.
#lists : methods for lists.
#sets : methods for sets.
#maps : methods for maps.
#aggregates : methods for creating aggregates on arrays or collections.
#ids : methods for dealing with id attributes that might be repeated (for example, as a result of an iteration).
Selection Variable Expressions
*{...}:选择表达式:和${}在功能上是一样;
补充:配合 th:object="${session.user}:
<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>
Message Expressions: #{...}:获取国际化内容
Link URL Expressions: @{...}:定义URL;
@{/order/process(execId=${execId},execType='FAST')}
Fragment Expressions: ~{...}:片段引用表达式
<div th:insert="~{commons :: main}">...</div>
Literals(字面量)
Text literals: 'one text' , 'Another one!' ,…
Number literals: 0 , 34 , 3.0 , 12.3 ,…
Boolean literals: true , false
Null literal: null
Literal tokens: one , sometext , main ,…
Text operations:(文本操作)
String concatenation: +
Literal substitutions: |The name is ${name}|
Arithmetic operations:(数学运算)
Binary operators: + , - , * , / , %
Minus sign (unary operator): -
Boolean operations:(布尔运算)
Binary operators: and , or
Boolean negation (unary operator): ! , not
Comparisons and equality:(比较运算)
Comparators: > , < , >= , <= ( gt , lt , ge , le )
Equality operators: == , != ( eq , ne )
Conditional operators:条件运算(三元运算符)
If-then: (if) ? (then)
If-then-else: (if) ? (then) : (else)
Default: (value) ?: (defaultvalue)
Special tokens:
No-Operation: _
thymeleaf片断fragment
基本片断(被引用)
myfragment.html
具体位置: resources/templates/commons/myfragment.html (不一定要位于commons,但一定要在templates下)
<body> <!-- 无参片断 --> <nav th:fragment="topBar"> <p> fragment no arg </p> </nav> <!-- 有参片断 --> <nav th:fragment="sideBar(fragmentArg1,fragmentArg2)"> <p> fragment has arg </p> <a href="#" th:class="${fragmentArg1 =='main'?'nav-link active':'nav-link'}"> 超链接 </a> </nav> </body>
无参引用方式
引用片断方式 | 说明 | 无参样例 | 效果 |
th:insert: | 将公共片段整个插入到声明引入的元素中 |
<div th:insert="commons/myfragment :: topBar"></div> |
<div> <nav th:fragment="topBar"> <p> fragment no arg </p> </nav> </div> |
th:replace | 将声明引入的元素替换为公共片段 |
<div th:replace="commons/myfragment :: topBar"></div> |
|
th:include | 将被引入的片段的内容包含进这个标签中 |
<div th:include="commons/myfragment :: topBar"></div> |
<div> <p> fragment no arg </p> </div> |
有参引用方式
仅以th:replace为例
引用片断方式 | 说明 | 有参样例,见小括号中两个参数 | 效果 |
th:insert: | 将公共片段整个插入到声明引入的元素中 |
<nav th:replace="~{commons/myfragment :: sideBar(fragmentArg1='main',fragmentArg2='none')}"></nav> |
<nav th:fragment="sideBar(fragmentArg1,fragmentArg2)"> <p> fragment has arg </p> <a href="#" th:class="${fragmentArg1 =='main'?'nav-link active':'nav-link'}"> 超链接 </a> </nav> |
thymeleaf获取上下文路径
关键字: springboot获取上下文路径 , thymeleaf获取上下文路径
https时会遇到跨域问题
<script type="text/javascript" th:inline="javascript"> basePath = [[${#httpServletRequest.getScheme() + '://' + #httpServletRequest.getServerName() + ':' + #request.getServerPort() + #request.getContextPath()}]] console.log("basePath="+basePath); </script>
console 打印: basePath=https://localhost:80/managerSys/
以上带https头之后 , 当有反向代理nginx时, 获取的端口可能会不匹配, 此时最好把 ':' + #request.getServerPort() 去掉
https正常
<script type="text/javascript" th:inline="javascript"> var basePath = [[${ '//' + #httpServletRequest.getServerName() + #request.getContextPath()}]]; // var basePath = window.location.origin+"/managerSys" console.log("basePath=" + basePath); </script>
console 打印: basePath=//localhost/managerSys
以上不带schema头的基本路径(即不带http , https)等,此时浏览器会自动判断schema头,并在请求时自动追加 , 但有个缺点是只能暴露80或443端口 ,不能用其它端口, 不然默认跳到80或443中去导致找不到请求.
https正常
<script type="text/javascript" th:inline="javascript"> var basePath = window.location.origin+"/managerSys" console.log("basePath=" + basePath); </script>
console 打印: basePath=http://localhost/managerSys
thymeleaf模板重定向和转发
在controller中使用"redirect:/xxx" 或 "forward:/yyy"即可
return "redirect:/emps";//新增成功后,返回到列表页面
因为在ThymeleafViewResolver.java的createView(...)中, 针对redirect: 和 forward: 有做特殊处理
@Override protected View createView(final String viewName, final Locale locale) throws Exception { // First possible call to check "viewNames": before processing redirects and forwards if (!this.alwaysProcessRedirectAndForward && !canHandle(viewName, locale)) { vrlogger.trace("[THYMELEAF] View "{}" cannot be handled by ThymeleafViewResolver. Passing on to the next resolver in the chain.", viewName); return null; } // Process redirects (HTTP redirects) if (viewName.startsWith(REDIRECT_URL_PREFIX)) { vrlogger.trace("[THYMELEAF] View "{}" is a redirect, and will not be handled directly by ThymeleafViewResolver.", viewName); final String redirectUrl = viewName.substring(REDIRECT_URL_PREFIX.length(), viewName.length()); final RedirectView view = new RedirectView(redirectUrl, isRedirectContextRelative(), isRedirectHttp10Compatible()); return (View) getApplicationContext().getAutowireCapableBeanFactory().initializeBean(view, viewName); } // Process forwards (to JSP resources) if (viewName.startsWith(FORWARD_URL_PREFIX)) { // The "forward:" prefix will actually create a Servlet/JSP view, and that's precisely its aim per the Spring // documentation. See http://docs.spring.io/spring-framework/docs/4.2.4.RELEASE/spring-framework-reference/html/mvc.html#mvc-redirecting-forward-prefix vrlogger.trace("[THYMELEAF] View "{}" is a forward, and will not be handled directly by ThymeleafViewResolver.", viewName); final String forwardUrl = viewName.substring(FORWARD_URL_PREFIX.length(), viewName.length()); return new InternalResourceView(forwardUrl); } // Second possible call to check "viewNames": after processing redirects and forwards if (this.alwaysProcessRedirectAndForward && !canHandle(viewName, locale)) { vrlogger.trace("[THYMELEAF] View "{}" cannot be handled by ThymeleafViewResolver. Passing on to the next resolver in the chain.", viewName); return null; } vrlogger.trace("[THYMELEAF] View {} will be handled by ThymeleafViewResolver and a " + "{} instance will be created for it", viewName, this.viewClass.getSimpleName()); return loadView(viewName, locale); }
何为RESTFUL
URI: /资源名称/资源标识 HTTP请求方式区分对资源CRUD操作
普通CRUD(uri来区分操作) | RestfulCRUD | |
---|---|---|
查询 | getEmp | emp---GET |
添加 | addEmp?name=bobo&age=28 | emp---POST |
修改 | updateEmp?id=29&name=bobo | emp/{id}---PUT |
删除 | deleteEmp?id=2 | emp/{id}---DELETE |
2)、实验的请求架构;
实验功能 | RestfulCRUD 请求URI | 请求方式 | |
---|---|---|---|
查询所有员工 | emps | GET |
//用于列表界面 @GetMapping(value = "/emps") public String queryAll(ModelMap model, HttpSession session) { |
查询某个员工(详情查看页) | emp/2 | GET | |
来到添加页面 | emp | GET |
//用于新增前 @GetMapping(value = "/emp") public String gotoAddPage( ModelMap model, HttpSession session) { |
添加员工 | emp | POST |
<form th:action="@{/emp}" method="post"> <input type="hidden" name="_method" th:value="${emp} != null ? 'put':''"/> <input type="hidden" name="id" th:value="${emp} != null ? ${emp.id}:''"/> <button type="submit" class="btn btn-default btn-danger">删除</button> </form> |
来到修改页面(查出员工进行信息回显) | emp/2 | GET |
//用于更新前 @GetMapping(value = "/emp/{id}") public String gotoUpdatePage(@PathVariable("id") Integer id, ModelMap model, HttpSession session) { |
修改员工 | emp | PUT |
<form th:action="@{/emp}" method="post"> <input type="hidden" name="_method" th:value="${emp} != null ? 'put':''"/> <input type="hidden" name="id" th:value="${emp} != null ? ${emp.id}:''"/> <button type="submit" class="btn btn-default btn-danger">删除</button> </form> |
删除员工 | emp/2 | DELETE |
<form th:action="@{/emp/}+${emp.id}" method="post"> <input type="hidden" name="_method" value="delete"/> <button type="submit" class="btn btn-default btn-danger">删除</button> </form> |
判断是否存在 | emp/2 | HEAD |
存在就返回200,不存在返回400 (ElasticSearch 就是这么做的) |
thymeleaf之独立使用模板引擎*****
$$$$$hymeleaf模板引擎入门==>https://www.cnblogs.com/ai-developers/p/7395588.html
public void exportExcel(HttpServletRequest request, HttpServletResponse response, @RequestBody(required = false) Map<String, Object> parameters, @RequestParam(value = "from", required = false) Integer from, @RequestParam(value = "limit", required = false) Integer limit, @RequestParam(value = "sorting", required = false) String sorting) { TemplateEngine templateEngine; //ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(request.getServletContext());//zcpd; ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver(); try { templateEngine = new TemplateEngine(); templateResolver = new ClassLoaderTemplateResolver(); templateResolver.setPrefix("templates/"); //模板位置 templateResolver.setSuffix(".html"); //模板扩展名 templateResolver.setTemplateMode("TEXT");//'HTML', 'XML', 'TEXT', 'JAVASCRIPT', 'CSS', 'RAW' templateResolver.setCharacterEncoding("UTF-8"); templateResolver.setOrder(1); templateResolver.setCacheable(false); templateEngine.setTemplateResolver(templateResolver); //Context context = new Context(); WebContext context = new WebContext(request, response, request.getServletContext()); context.setVariable("results", request); //添加变量message到context context.setVariable("message", "hello thymeleaf"); StringWriter stringWriter = new StringWriter(); //解析模板并显示到浏览器 templateEngine.process("bobo", context, stringWriter); //logger.info("stringWriter = " + stringWriter); response.getWriter().write(stringWriter.toString()); Document document = DocumentHelper.parseText(stringWriter.toString()); String xmlData = document.asXML(); logger.info(xmlData); } catch (Exception e) { e.printStackTrace(); } }
thymeleaf方言dialect
Thymeleaf本身提供了StandardDialect
,以及结合了Spring之后提供的SpringStandardDialect
。Thymeleaf默认的语法 th:if
等,就是定义在了StandardDialect
中,th
为方言的前缀,if
为方言的处理器名称。
Thymeleaf3自定义方言Dialect与处理器==>https://blog.csdn.net/edzhou00/article/details/83276672
th:block
<th:block></th:block>是Thymeleaf提供的唯一的一个Thymeleaf块级元素,其特殊性在于Thymeleaf模板引擎在处理<th:block>的时候会删掉它本身,标签本身不显示,而保留其内容,应用场景主要有如下两个:
1、同时控制相连两个标签是否显示
如下代码:
<div id="div1" th:if="..."> </div> <div id="div2" th:if="..."> </div>
div1和div2中两个if条件一样时,可以改成如下写法:
<th:block th:if="..."> <div id="div1"> </div> <div id="div2"> </div> </th:block>
2、循环同级标签
比如在表格中需要使用th:each循环两个tr,在不知道th:block标签时,可能会用th:each配合th:if使用,但是使用th:block就简单了,如下:
<table> <th:block th:each="..."> <tr>...</tr> <tr>...</tr> </th:block> </table>
转自: thymeleaf块标签(空标签)th:block,标签本身不显示==>http://www.yyjjssnn.cn/articles/849.html
其它笔记
其它待研究知识点
thymeleaf中的内联[ [ ] ]==>https://www.cnblogs.com/suncj/p/4031486.html
参考
thymeleaf的使用及配置==>https://www.cnblogs.com/gqymy/p/9216686.html
关于thymeleaf+layout布局的使用方式【纯转】==>https://www.cnblogs.com/whatlonelytear/p/11308836.html