• springboot thymeleaf【转】【补】


    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优先级从高到低FeatureAttributes中文说明
    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>
     
        

    <nav th:fragment="topBar"> <p> fragment no arg </p> </nav>

    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

    https://www.programcreek.com/java-api-examples/?class=org.thymeleaf.templateresolver.TemplateResolver&method=setPrefix

        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

    其它笔记

    * th:action    <form id="login" th:action="@{/login}">......</form>    定义后台控制器的路径
    * th:each        循环List集合: <tr th:each="user,iterStat : ${list}"> <td th:text="${user.userName}">Onions</td> </tr> iterStat:下标
                          循环Map集合: <div th:each="mapS:${map}"> <div th:text="${mapS}"></div> </div>
                          循环数组:        <div th:each="arrayS:${arrays}"> <div th:text="${arrayS}"></div> </div>
    * th:field        
    * th:href        定义超链接,类似<a>标签的href 属性。value形式为@{/login}
    * th:id            类似html标签中的id属性。    <div class="user" th:id = "(${index})"></div>
    * th:if            <span th:if="${Sex} == 1" > <input type="redio" name="se" th:value="男" /> </span> 
                         <span th:if="${Sex} == 2"> <input type="redio" name="se" th:value="女" /> </span>
    * th:include
    * th:fragment
    * th:object
    * th:src            外部资源引入    <script th:src="@{/static/js/jquery-2.4.min.js}"></script>
    * th:replace
    * th:text           <input th:text=${param} />
    * th:value        <input th:value=${param} />
     
    条件判断可以这样写:<input th:text="(${user.isAdmin}?'管理员':'普通用户')"></input>
     
     
    Hello, [[${user.name}]]! //[[]]写法会html转义
    Hello, [(${user.name})]! //[()]写法不会html转义
     
    thymeleaf的配置文件说明 
    #spring.thymeleaf.cache = true #启用模板缓存。 
    #spring.thymeleaf.check-template = true #在呈现模板之前检查模板是否存在。
    #spring.thymeleaf.check-template-location = true #检查模板位置是否存在。
    #spring.thymeleaf.content-type = text / html #Content-Type值。 
    #spring.thymeleaf.enabled = true #启用MVC Thymeleaf视图分辨率。 
    #spring.thymeleaf.encoding = UTF-8 #模板编码。 
    #spring.thymeleaf.excluded-view-names = #应该从解决方案中排除的视图名称的逗号分隔列表。 
    #spring.thymeleaf.mode = HTML5 #应用于模板的模板模式。另请参见StandardTemplateModeHandlers。 
    #spring.thymeleaf.prefix = classpath:/ templates / #在构建URL时预先查看名称的前缀。 
    #spring.thymeleaf.suffix = .html #构建URL时附加到查看名称的后缀。 
    #spring.thymeleaf.template-resolver-order = #链中模板解析器的顺序。 
    #spring.thymeleaf.view-names = #可以解析的视图名称的逗号分隔列表。/ templates / #在构建URL时先查看名称的前缀。 
    #spring.thymeleaf.suffix = .html #构建URL时附加到查看名称的后缀。 
    #spring.thymeleaf.template-resolver-order = #链中模板解析器的顺序。 
    #spring.thymeleaf.view-names = #可以解析的视图名称的逗号分隔列表。/ templates / #在构建URL时先查看名称的前缀。 
    #spring.thymeleaf.suffix = .html #构建URL时附加到查看名称的后缀。 
    #spring.thymeleaf.template-resolver-order = #链中模板解析器的顺序。 
    #spring.thymeleaf.view-names = #可以解析的视图名称的逗号分隔列表。

     

     

    其它待研究知识点

    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

  • 相关阅读:
    软件工程第一次作业--IT女的进化
    软件工程第五次作业
    软件工程第四次作业
    软件工程第三次作业
    软件工程第二次作业
    v0.1beta
    第二次结对作业
    软件工程结对作业
    软件工程第三次作业
    软件工程第二次作业
  • 原文地址:https://www.cnblogs.com/whatlonelytear/p/9023089.html
Copyright © 2020-2023  润新知