性能排名第一的模板引擎 JTE 在 Spring Boot 中的应用

文摘   2024-11-29 08:01   新疆  

Spring Boot 3实战案例合集》现已囊括超过50篇精选实战文章,并且此合集承诺将永久持续更新,为您带来最前沿的技术资讯与实践经验。欢迎积极订阅,享受不断升级的知识盛宴!订阅用户将特别获赠合集内所有文章的最终版MD文档(详尽学习笔记),以及完整的项目源码,助您在学习道路上畅通无阻。

环境:SpringBoot3.2.5



1. 简介

模板引擎是为了解决用户界面(显示)与业务数据(内容)分离而产生的,它可以生成特定格式的文档,如HTML、XML等。常见的模板引擎有FreeMarker和Thymeleaf等。

FreeMarker通过特定的语法,如${参数},将数据注入模板中,实现动态内容的生成。它适用于生成复杂格式的Excel文件、PDF文档等。

Thymeleaf则提供标准和Spring标准两种方言,可以直接套用模板实现JSTL、OGNL表达式效果。它特别适用于与SpringMVC集成的项目。

JTE(Java Template Engine)是一个轻量级的模板引擎,专为Java应用设计。它采用了独特的DSL(领域特定语言)来简化模板编写过程,使得模板更加简洁易读。JTE支持强大的继承和组合机制,这不仅有助于构建复杂的页面结构,还能有效减少重复代码。此外,JTE还提供了良好的错误报告功能,帮助开发者快速定位和解决问题,提高了开发效率。总之,无论是小型网站还是大型企业级应用,JTE都能提供灵活且高效的解决方案,是值得尝试的一款模板引擎。

JTE性能

按设计,jte 提供了非常快的输出速度。这是一个包含了 jte 的 mbosecke/template-benchmark 的分支版本,在 AMD Ryzen 5950X(单线程)上运行。

mbosecke/template-benchmark github地址如下:

https://github.com/casid/template-benchmark/

高并发

这是与上面相同的基准测试,但线程数被设置为@Threads(16),以充分利用所有核心。jte几乎没有序列化瓶颈,并且在具有多个CPU核心的服务器上能够非常高效地并发运行:

2. 实战案例

2.1 快速入门

定义数据模型

public class Page {  private String title ;  private String description ;  // getters, setters}

定义jte模板

@import com.pack.jte.test.Page@param Page page<html>  <head>    <meta charset="UTF-8">      @if(page.getDescription() != null)          <meta name="description" content="${page.getDescription()}">      @endif      <title>${page.getTitle()}</title>  </head>  <body>      <h1>${page.getTitle()}</h1>      <p>欢迎使用JTE模板引擎</p>  </body></html>
  • @import 直接转换为 Java 或 Kotlin 的导入语句,在这种情况下,使得 com.pack.jte.test.Page 被模板识别。

  • @param Page page 是需要传递给此模板的参数。

  • @if / @endif 构成了一个条件块。括号内的内容 (page.getDescription() != null) 是标准的 Java 代码。

  • ${} 将内容写入底层模板输出,类似于其他多种模板引擎中的用法。

渲染模板

CodeResolver codeResolver = new DirectoryCodeResolver(Path.of("target/classes/templates/jte")) ;TemplateEngine templateEngine = TemplateEngine.create(codeResolver, ContentType.Html) ;StringOutput so = new StringOutput();templateEngine.render("test.jte", new Page("xxxooo", "这里是馍馍社交"), so) ;System.err.println(so.toString()) ;

控制台输出结果

上面代码中的TemplateEngine实现有很多,你可根据不同的场景选择合适的输出模板。

2.2 模板语法

数据显示

要在模板中显示数据,请用 ${} 将其包裹起来:

@import my.Model@param Model model
Hello ${model.name}!

而对应的模型Model则如下:

package my ;public class Model {  public String name = "Pack" ;}

上述模板的输出将是 Hello Pack!

${} 可用来输出以下类型:

  • String

  • Enum

  • boolean,byte,short,int,long,float,double,char

  • 任意实现了gg.jte.Content的类

注意:出于安全考虑,不会自动进行 .toString() 转换。不支持的类型会产生编译错误。

if语句块

可以使用关键字 @if@elseif@else@endif 来构造 if 语句。这些关键字可直接转换为 Java 对应的关键字:

@if(model.entries.isEmpty())  I have no entries!@elseif(model.entries.size() == 1)  I have one entry!@else  I have ${model.entries.size()} entries!@endif

自 Java 14+ 起,还可以对 instanceof 使用模式匹配:

@if (model instanceof SubModel subModel)  ${subModel.getSpecial()}@endif

就像写Java代码一样。

循环

除了 if 语句,jte 还提供了 @for@endfor 关键字,用于循环遍历可迭代数据。同样,@for 可以直接转换为 Java 或 Kotlin 的对应关键字:

@for(Entry entry : model.entries)  <li>${entry.title}</li>@endfor
@for(var entry : model.entries)  <li>${entry.title}</li>@endfor
@for(int i = 0; i < 10; ++i)  <li>i is ${i}</li>@endfor

循环时,你可以使用 gg.jte.support.ForSupport 类获取有关循环的信息,例如你是在循环的第一次迭代还是最后一次迭代。

@import gg.jte.support.ForSupport@for(var entryLoop : ForSupport.of(model.entries))<tr class="${(entryLoop.getIndex() + 1) % 2 == 0 ? "even" : "odd"}">  ${entryLoop.get()}</tr>@endfor

自 jte 3.0 起,可以在 @endfor 之前使用 @else。如果循环中没有遍历任何元素,@else 内容就会渲染。这对显示空列表状态非常有用,无需额外的 @if。例如

@for(var item : datas)  <tr>    <td>${item.getName()}</td>    <td>${item.getQuantity()}</td>  </tr>@else  <tr>    <td colspan="2">本月销售总数</td>  </tr>@endfor

这功能不错误

注释

jte 允许你在模板中定义注释。

<%-- 这里是注释信息 --%>

注意:模板输出中不包含 jte 注释。

模板调用

要在模板之间共享共同功能,可以调用其他模板。所有模板都必须位于 jte 根目录下。

通用模板定义templates/jte/common.jte

@import com.pack.jte.test.Entry@param Entry entry@param boolean verbose
<h2>${entry.getTitle()}</h2>@if(verbose) <h3>xxxooo</h3>@endif

在其它模板中调用该模板

@template.common(page.getEntry(), false)

这里@template后面是你要调用模板的完整路径。类似方法调用,该模板中需要什么数据,直接在这里传入。

模板渲染示例:

CodeResolver codeResolver = new DirectoryCodeResolver(Path.of("target/classes/templates/jte")) ;TemplateEngine templateEngine = TemplateEngine.create(codeResolver, ContentType.Html) ;TemplateOutput so = new StringOutput();Page page = new Page("xxxooo", "这里是馍馍社交");page.setEntry(new Entry("你好中国")) ;

以上我们介绍了常用的一些语法,还有其它如需要了解可以查看官网。

2.3 在Spring Boot中的应用

我们只需要引入以下的依赖即可,根据你使用Spring Boot的版本,支持2.x、3.x

<dependency>  <groupId>gg.jte</groupId>  <artifactId>jte</artifactId>  <version>3.1.12</version></dependency><dependency>  <groupId>gg.jte</groupId>  <artifactId>jte-spring-boot-starter-3</artifactId>  <version>3.1.12</version></dependency>

配置文件如下配置

gg:  jte:    developmentMode: true    # 生产环境设置,与上面的不能同时设置    usePrecompiledTemplates: false    # 注意这里的路径,如果你打成的jar运行,则你应该在你当前jar所在目录同级建立对应的目录    templateLocation: target/classes/templates/jte    templateSuffix: .jte

设置了模板文件的路径及文件的后缀。同时设置了当前为开发模式。

我们这里以上面的test.jte为例演示

@Controller@RequestMapping("/jte")public class TestController {
@GetMapping("") public String view(Model model, HttpServletResponse response) { Page page = new Page("xxxooo", "这里是馍馍社交"); page.setEntry(new Entry("你好中国")) ; model.addAttribute("page", page); return "test"; }}

页面展示

除了要注意模板路径问题外,其它就像以前一样该怎么写就怎么写,模板数据模型的使用方式都一样的。

以上是本篇文章的全部内容,如对你有帮助帮忙点赞+转发+收藏

推荐文章

新选择!基于Spring Boot监听MySQL日志Binlog实现数据实时同步

强大!Spring Boot全新模块化管理方式

高级开发!自定义@Value实时刷新最新配置

项目亮点!Spring Boot 多线程事务一致性方案,支持JDBC,MyBatis,JPA

Spring Boot + 事务钩子,完美解决事务并发问题

自己动手实现Agent统计API接口调用耗时

Jackson在Spring Boot高级应用技巧【Long精度丢失, @JsonValue, 数据脱敏】

考察你对 Spring 基本功掌握能力

Tika 与 Spring Boot 的完美结合:支持任意文档解析的神器

性能提升!@Async与CompletableFuture优雅应用

自定义注解+SpEL实现强大的权限管理

Spring AOP高级知识你知道多少?

借一古老技术考察你对SpringBoot掌握程度

Spring全家桶实战案例源码
spring, springboot, springcloud 案例开发详解
 最新文章