Freemarker 自定義指令/函數(shù) 踩坑

需求:

  • 使用模版引擎講待處理的模版中的變量替換為最終值
  • 模版中需要使用到 list 循環(huán)。需要根據(jù)數(shù)據(jù)列表生成數(shù)量不定的結(jié)果
  • 模版中需要使用到 base64 編碼蓄愁,且需要支持嵌套。base64 編碼中需要支持變量替換

base64( base64( "data1": ${data1 } ): base64( "data2": ${data2} ) )

開發(fā)環(huán)境

  • Springboot Maven Kotlin k8s

需求調(diào)研

  • 搜索了常用的模版引擎,嘗試使用了 jinjava糊治、Freemarker, 由于 jinjava 沒有找到足夠的功能來支持需求侧漓,最終選擇更為常用的 Freemarker.

需求實(shí)現(xiàn)

  • 添加依賴
<!-- freemarker -->
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.30</version>
        </dependency>
  • 新建一個自定義(實(shí)現(xiàn)base64編碼)方法類
class Base64Method : TemplateMethodModelEx {
    override fun exec(data: MutableList<Any?>): Any {
        return String(Base64.getEncoder().encode(data[0].toString().toByteArray(Charsets.UTF_8).clone()))
    }
}
  • 模版操作
@Test
    @Transactional
    fun tempalteTest() {
        val stringLoader = StringTemplateLoader()
        val templateValue: String = "<#list data1 as dataType1>\n" +
                "'type1://\${base64(\"\${data1.userName}:\${data1.password}\")}'\n" +
                "</#list>\n" +
                "<#list data2 as dataType2>\n" +
                "'type2://\${base64\"{\"userName\":\"\${data2.nodeName}\",\"password\":\"\${data2.password}\"}\")}'\n" +
                "</#list>\n" +
                "<#list data3 as dataType2>\n" +
                "'type3://\${base64(\"\${data3.userName}@\${data3.password}\")}'\n" +
                "</#list>"
        stringLoader.putTemplate("myTemplate", templateValue)
        val configuration = Configuration(Configuration.getVersion())
        configuration.defaultEncoding = "utf-8"
        configuration.setSharedVariable("base64", Base64Method());
//        configuration.setSharedVariable("base66", Base64Directive()); // 不滿足需求,遺棄
        configuration.templateLoader = stringLoader

        val template = configuration.getTemplate("myTemplate", "utf-8")

        //向數(shù)據(jù)集中添加數(shù)據(jù)
        val dataModel: MutableMap<String, MutableList<Map<String, String>>> = mutableMapOf()
        val type1: MutableList<Map<String, String>> = mutableListOf()
        val type2: MutableList<Map<String, String>> = mutableListOf()
        val type3: MutableList<Map<String, String>> = mutableListOf()

        val apList = HttpUtil.get("https://xxx.xxx") // 獲取后端數(shù)據(jù)

        // 根據(jù)后端結(jié)果apList 初始化數(shù)據(jù)
        // type1 初始化
        // type2 初始化
        // type3 初始化

        dataModel["type1"] = type1
        dataModel["type2"] = type2
        dataModel["type3"] = type3

        val out: Writer = StringWriter()
        // 第七步:調(diào)用模板對象的process方法輸出文件蛀醉。
        template.process(dataModel, out)
        // 第八步:關(guān)閉流悬襟。
        var test2 = out.toString()
        out.flush()
        out.close()
    }

未能實(shí)現(xiàn)部分

  • 嵌套實(shí)現(xiàn)

踩的坑

  • 剛開始使用 TemplateDirectiveModel 自定義指令的方式,如果待編碼的內(nèi)容中出現(xiàn)變量拯刁,就會出現(xiàn) base64 編碼的是一段一段的脊岳,也就是先每一小段編碼,在拼接成完成的垛玻。但我需要的效果是先拼接成完整的再進(jìn)行base64割捅。即便是這樣,我也想如果能拿到待編碼 list 的長度帚桩,那等拼接到最后一個再編碼也行亿驾,但并不能拿到這個 list,放棄账嚎。
  • 在使用 TemplateMethodModelEx 時莫瞬,如果待編碼內(nèi)容中有使用雙引號這類字符,需要使用 \ 來轉(zhuǎn)義郭蕉,否則會出現(xiàn)數(shù)據(jù)丟失問題乏悄。
  • 在測試嵌套時,方法內(nèi)無法使用 <#list> 循環(huán)恳不,故最后的解決方案是:再結(jié)果的基礎(chǔ)上自行 base64檩小。

如有錯誤,請大佬指定烟勋,這是一種不完整的解決方式规求,正在尋求更好的解決方案~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市卵惦,隨后出現(xiàn)的幾起案子阻肿,更是在濱河造成了極大的恐慌,老刑警劉巖沮尿,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件丛塌,死亡現(xiàn)場離奇詭異较解,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)赴邻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進(jìn)店門印衔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人姥敛,你說我怎么就攤上這事奸焙。” “怎么了彤敛?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵与帆,是天一觀的道長。 經(jīng)常有香客問我墨榄,道長玄糟,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任袄秩,我火速辦了婚禮茶凳,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘播揪。我一直安慰自己贮喧,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布猪狈。 她就那樣靜靜地躺著箱沦,像睡著了一般。 火紅的嫁衣襯著肌膚如雪雇庙。 梳的紋絲不亂的頭發(fā)上谓形,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天,我揣著相機(jī)與錄音疆前,去河邊找鬼寒跳。 笑死,一個胖子當(dāng)著我的面吹牛竹椒,可吹牛的內(nèi)容都是我干的童太。 我是一名探鬼主播,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼胸完,長吁一口氣:“原來是場噩夢啊……” “哼书释!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起赊窥,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤爆惧,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后锨能,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體扯再,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡芍耘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了熄阻。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片斋竞。...
    茶點(diǎn)故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖饺律,靈堂內(nèi)的尸體忽然破棺而出窃页,到底是詐尸還是另有隱情跺株,我是刑警寧澤复濒,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站乒省,受9級特大地震影響巧颈,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜袖扛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一砸泛、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蛆封,春花似錦唇礁、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至砸讳,卻和暖如春琢融,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背簿寂。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工漾抬, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人常遂。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓纳令,卻偏偏與公主長得像,于是被迫代替她去往敵國和親克胳。 傳聞我的和親對象是個殘疾皇子泊碑,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評論 2 348