Thymeleaf API渲染模板

使用Thymeleaf API渲染模板生成静态页面

标签(空格分隔): Thymeleaf 静态页面


Thymeleaf 是新一代的Java模板引擎,它的语法对前端开发者友好可直接打开编辑,Spring Boot也建议使用它作为你的模板引擎,本文将演示如何使用它提供的API来渲染模板生成静态页面。

一、引入maven依赖

spring boot中引用:

1
2
3
4
5
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>3.0.9.RELEASE</version>
</dependency>

或者:

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

二、Java后台转换代码

  • 1、准备静态模板 templates/example.html
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Title</title>
    </head>
    <body>
    <h1 th:text="${name}">列表名称</h1>
    <ul>
    <li th:each="item: ${array}" th:text="${item}">条目</li>
    </ul>
    </body>
    </html>
  • 2、获取静态资源 转换后 输出静态资源

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    //构造模板引擎
    ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
    //模板所在目录,相对于当前classloader的classpath。模板的路径
    resolver.setPrefix("templates/");
    //模板文件后缀
    resolver.setSuffix(".html");
    TemplateEngine templateEngine = new TemplateEngine();
    templateEngine.setTemplateResolver(resolver);

    //构造上下文(Model)
    Context context = new Context();
    context.setVariable("name", "蔬菜列表");
    context.setVariable("array", new String[]{"土豆", "番茄", "白菜", "芹菜"});

    //渲染模板 输出静态资源的位置
    FileWriter write = new FileWriter("result.html");

    //进行解析组装数据
    templateEngine.process("example", context, write);
  • 3、结果

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Title</title>
    </head>
    <body>
    <h1>蔬菜列表</h1>
    <ul>
    <li>土豆</li>
    <li>番茄</li>
    <li>白菜</li>
    <li>芹菜</li>
    </ul>
    </body>
    </html>

三、直接返回属性值给前台页面,不需要后台转换

  • 1、准备静态页面 index.html

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Title</title>
    </head>
    <body>
    <h1 th:text="${name}">列表名称</h1>
    <ul>
    <li th:each="item: ${array}" th:text="${item}">条目</li>
    </ul>
    </body>
    </html>
  • 2、后台控制器返回数据

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;

    import java.util.ArrayList;
    import java.util.List;
    @Controller
    @SpringBootApplication
    public class ThymeleafTestApplication {
    @RequestMapping("/")
    public String index(Model model){
    model.addAttribute("name","蔬菜列表");
    model.addAttribute("array",new String[]{"土豆", "番茄", "白菜", "芹菜"});
    return "index";
    }
    public static void main(String[] args) {
    SpringApplication.run(ThymeleafTestApplication.class, args);
    }
    }
  • 3、结果

四、错误解析

如果报以下错误,是以为缺少 ognl.jar 包,使得解析器在处理html中的表达式时失败。

  • 1、异常信息

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    java.lang.NoClassDefFoundError: ognl/PropertyAccessor

    at org.thymeleaf.standard.StandardDialect.getVariableExpressionEvaluator(StandardDialect.java:179)
    at org.thymeleaf.standard.StandardDialect.getExecutionAttributes(StandardDialect.java:393)
    at org.thymeleaf.DialectSetConfiguration.build(DialectSetConfiguration.java:263)
    at org.thymeleaf.EngineConfiguration.<init>(EngineConfiguration.java:123)
    at org.thymeleaf.TemplateEngine.initialize(TemplateEngine.java:336)
    at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1079)
    at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1067)
    at com.thunisoft.dzjz.conver.handle.impl.AbstractBuildCoverImpl.buildCover(AbstractBuildCoverImpl.java:92)
    at com.thunisoft.dzjz.conver.handle.IBuildCoverHandleTest.buildCover_volume(IBuildCoverHandleTest.java:73)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
    Caused by: java.lang.ClassNotFoundException: ognl.PropertyAccessor
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 38 more
  • 2、解决方法 pom 中引入 ognl.jar 即可。

    1
    2
    3
    4
    5
    <dependency>
    <groupId>ognl</groupId>
    <artifactId>ognl</artifactId>
    <version>3.2.4</version>
    </dependency>