自定义模板引擎 java,【四 Twirl模板引擎】 4. 自定义模板格式

本文档介绍了如何为Play框架的模板引擎添加自定义格式支持,包括实现`play.twirl.api.Format[A]`,关联文件扩展名,以及配置将模板结果转化为HTTP响应。通过创建自定义的文本处理类和定义`Writeable`实例,可以确保模板能够正确渲染并防止XSS攻击。
摘要由CSDN通过智能技术生成

为模板引擎添加对自定义格式的支持

内置的模板引擎支持常见的格式(HTML、XML等)。但是你也可以轻松地按需添加自己的格式。

模板处理流程概述

template会向输出的结果中添加静态及动态的内容。如下面这样一个简单模板:

foo @bar baz

里边包含了两个静态的部分(foo 和 baz),它们环绕了一个动态部分(bar)。模板引擎组合它们然后输出结果。事实上,为了防止XSS跨站攻击,bar需要在组合之前进行转义。如在HTML中 需要将 "

模板怎么知道每个模板引擎要关联的格式呢?它会根据后缀名查找:如一个以 .scala.html 结尾的模板将关联到HTML格式。

最后,你通常希望你的模板会输出为HTTP响应体,因此你必须定义如何用模板来渲染Play的result。

总而言之,为了支持自定义格式,必须做到下面这些步骤:

为自定义格式实现文本集成

为此格式关联文件扩展名

告诉Play,要如何用 模板来渲染HTTP响应。

实现自定义格式

实现 play.twirl.api.Format[A] trait中的 raw(text: String): A 及 escape(text: String): A 方法。Play将用它们来组合动态及静态内容。

泛型A表示模板渲染的result类型,如 HTML模板对应着Html。A必须是play.twirl.api.Appendable[A] 特质的子类,这里边具体的定义了如何将各部分组合在一起。

简单起见,Play提供了 play.twirl.api.BufferedContent[A] 抽象来来实现 play.twirl.api.Appendable[A],它里边使用了一个StringBuilder 来构建result。同时它还实现了 play.twirl.api.Content 特质,因此Play知道如何来将它序列化为HTTP response body(见本章最后一段)。

简单来说,你需要写两个类:一个定义result(实现 play.twirl.api.Appendable[A]),另一个定义文本处理(实现 play.twirl.api.Format[A])。下边是源码中HTML的例子:

// The `Html` result type. We extend `BufferedContent[Html]` rather than just `Appendable[Html]` so

// Play knows how to make an HTTP result from a `Html` value

class Html(buffer: StringBuilder) extends BufferedContent[Html](buffer) {

val contentType = MimeTypes.HTML

}

object HtmlFormat extends Format[Html] {

def raw(text: String): Html = …

def escape(text: String): Html = …

}

关联自定义格式的文件扩展名

在build过程中,整个项目编译之前,模板都会先被编译为 .scala 文件。sbt设置中的 TwirlKeys.templateFormats(Map[String, String]) 定义了文件扩展名和模板格式之间的关系。例如,如果Play没有内置支持HTML,你需要在TwirlKeys.templateFormats 做如下配置:

TwirlKeys.templateFormats += ("html" -> "my.HtmlFormat.instance")

注意箭头符号右边的类型必须是play.twirl.api.Format[_]。

从模板result到HTTP result

只要域中存在play.api.http.Writeable[A]类型的隐式变量,Play就可以直接将类型A转换为HTTP response。因此你需要做的就是为你的自定义类型来定义这样一个变量。下面还是以HTTP为例:

implicit def writableHttp(implicit codec: Codec): Writeable[Http] =

Writeable[Http](result => codec.encode(result.body), Some(ContentTypes.HTTP))

注意:如果你的模板result类型是 play.twirl.api.BufferedContent 的子类,你只需要定义一个隐式的 play.api.http.ContentTypeOf 值:

implicit def contentTypeHttp(implicit codec: Codec): ContentTypeOf[Http] =

ContentTypeOf[Http](Some(ContentTypes.HTTP))

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值