JAVA中使用freemark生成自定義文(json、excel、yaml、txt)
場景:在我們工作中,有時需要生成一些檔案,可能它不是一種標準的格式,比如JSON。
目的:配置一個模板,根據前端傳入的值動態生成配置檔案,並且支援迴圈判斷
專案路徑:
請無視YamlTest.java和YamlTemplate.ftl
JAVA程式碼:
package com.ming.freemark.demo;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
public class YamlTestList {
//模板配置物件
private Configuration cfg;
//Yaml目錄
private static String yamlPath = "resources\\yaml";
/**
* 初始化配置
*/
public void init() {
cfg = new Configuration();
File yamlFile = null;
try {
yamlFile = new File(yamlPath);
cfg.setDirectoryForTemplateLoading(yamlFile);
} catch (IOException e) {
e.printStackTrace();
}
}
public void process(Map<String, Object> map){
try {
Template template = cfg.getTemplate("YamlTemplate2.ftl");
template.process(map, new FileWriter(new File(yamlPath + "\\test.yaml")));
} catch (IOException | TemplateException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
YamlTestList test = new YamlTestList();
test.init();
//生成一個pod的yaml檔案
Map<String,Object> podMap = new HashMap<String,Object>();
podMap.put("kind", "Pod");
podMap.put("apiVersion", "v1");
podMap.put("metadataName", "test-pod");
podMap.put("lablesName", "test-pod");
podMap.put("lablesVersion", "1.0");
//此處是一個迴圈 一個pod包含多個微服務元件
podMap.put("containerName", "tomcat");
podMap.put("imageName", "tomcatImage");
//組裝一個container裡面的port列表
//一個docker container裡面可能有多個元件,比如一個container部署了兩個tomcat,則此處是port的列表
List<Map<String,Object>> portList = new ArrayList<>();
Map<String,Object> portMap1 = new HashMap<String,Object>();
portMap1.put("containerPort", 8080);
Map<String,Object> portMap2 = new HashMap<String,Object>();
portMap2.put("containerPort", 8081);
portList.add(portMap1);
portList.add(portMap2);
podMap.put("portList", portList);
test.process(podMap);
// myMap[key]?default(""),這裡是判斷值是否為null,如果為null,設定預設值為空,freemarker不支援null,如果值為null,會丟擲異常報錯。
}
}
ftl模板檔案:
{
"kind": "${kind}",
"apiVersion": "${apiVersion}",
"metadata": {
"name": "${metadataName}",
"labels": {
"name": "${lablesName}",
"version": "${lablesVersion}"
}
},
"spec": {
"containers": [
{
"name": "${containerName}",
"image": "${imageName}",
"ports":[
<#list portList as portInfo>
{
"containerPort":${portInfo.containerPort?c}
}<#if portInfo_has_next>,</#if>
</#list>
]
}
]
}
}
最終效果:
test.yaml
之前是空白的,執行程式後自動生成一份檔案(k8s的編排檔案)
說明:此處其實生成的是.json檔案。打錯字了。其實無所謂,自己把ftl裡面的改為yaml格式即可。
遇到的問題
花了2小時把這個玩意大體搞定了。
遇到的坑:
1.如何遍歷list
之前我按自己想的寫的是<#list ${portList} as portInfo>,一直報錯,後來修修改改發現原來不需要,直接portList即可。
2.加入判斷 list.hasNext來決定是否加逗號。
之前直接每個後面加逗號,然後就成這樣了
"ports":[
{
"containerPort":8080
},
{
"containerPort":8081
},
]
所以需要加上一個判斷。不過freemark直接支援
<#if portInfo_has_next>,</#if>
還是很給力.
2016-05-27 新增:
經過完整的測試部署之後的一份ftl及Demo示例,解決了list迴圈巢狀且list的是map的問題
ftl:
{
"kind": "ReplicationController",
"apiVersion": "v1",
"metadata": {
"name": "${appName}-rc",
"labels": {
"name": "${appName}-rc",
"version": "v1"
}
},
"spec": {
"replicas": ${replicas},
"selector": {
"name": "${appName}-pod"
},
"template": {
"metadata": {
"name": "${appName}-pod",
"labels": {
"name": "${appName}-pod",
"version": "v1"
}
},
"spec": {
"containers": [
<#list containerList as containerInfo>{
"name": "${containerInfo.microServiceName}",
"image": "${containerInfo.imageUrl}",
"ports": [
<#list containerInfo.portList as portInfo>{
"containerPort": ${portInfo.port?c}
}<#if portInfo_has_next>,</#if>
</#list>
],
"resources": {
"limits":{
"cpu": "${containerInfo.cpu}",
"memory": "${containerInfo.memory}"
}
}
}
</#list>]
}
}
}
}
測試程式碼:
public static String layoutData(String name,int exposePort){
// 編排基本資訊
JSONObject layoutInfoJSON = new JSONObject();
layoutInfoJSON.put("name", name + "layout");
layoutInfoJSON.put("version", "v1.0");
layoutInfoJSON.put("dmsAppName", name);
layoutInfoJSON.put("dmsAppId", "0a2f9r8t7y6j7hg9"); //dms的應用Id
layoutInfoJSON.put("replicas", 2); //副本數
layoutInfoJSON.put("masterId", "beijing1"); //北京一區
layoutInfoJSON.put("basicCpuScale", 1); //pod基礎設定:6核cpu
layoutInfoJSON.put("basicMemScale", 2); //pod基礎設定:12G記憶體
//構建微服務資訊list
//微服務1
JSONArray msArray = new JSONArray();
JSONObject msJsonObjectOne = new JSONObject();
msJsonObjectOne.put("name", "tomcat");
msJsonObjectOne.put("version", "1.0");
msJsonObjectOne.put("type", 1); //微服務型別:1:service、2:job
msJsonObjectOne.put("domain", "www.test.com");
msJsonObjectOne.put("imageUrl", "tomcat-1");
msJsonObjectOne.put("memRatio", 1);
msJsonObjectOne.put("cpuRatio", 1);
//微服務1中的ports 埠列表
JSONArray portArray = new JSONArray();
JSONObject portJsonObjectOne = new JSONObject();
portJsonObjectOne.put("port", 8080); //容器本身的埠
portJsonObjectOne.put("protocol", "tcp"); //埠協議型別
portJsonObjectOne.put("exposePort", exposePort); //容器埠 - 外網暴露埠 注意端口占用
portArray.add(portJsonObjectOne);
msJsonObjectOne.put("ports", portArray);
//微服務1中的evns 環境變數列表
JSONArray evnArray = new JSONArray();
JSONObject evnJsonObjectOne = new JSONObject();
evnJsonObjectOne.put("key", "evn_key1");
evnJsonObjectOne.put("value", "evn_value1");
evnJsonObjectOne.put("option", "evn_option1");
evnArray.add(evnJsonObjectOne);
msJsonObjectOne.put("evns", evnArray);
msArray.add(msJsonObjectOne);
//把微服務放入編排資訊中
layoutInfoJSON.put("microServiceInfoList", msArray);
return JSONObject.toJSONString(layoutInfoJSON);
}
結果:
{
"kind": "ReplicationController",
"apiVersion": "v1",
"metadata": {
"name": "k8stest6-rc",
"labels": {
"name": "k8stest6-rc",
"version": "v1"
}
},
"spec": {
"replicas": 2,
"template": {
"metadata": {
"name": "k8stest6-pod",
"labels": {
"name": "k8stest6-pod",
"version": "v1"
}
},
"spec": {
"containers": [
{
"name": "tomcat",
"image": "tomcat-1",
"ports": [
{
"containerPort": 8080
}
],
"resources": {
"limits":{
"cpu": "1",
"memory": "2.0Gi"
}
}
}
]
}
}
}
}
注意:要使用這個json最好
.trim().replaceAll(" ", "");
並且要注意不要有縮排,會被坑
持續更新ing…..
2016-07-06:
{
"kind": "ReplicationController",
"apiVersion": "v1",
"metadata": {
"name": "${stackName}",
"labels": {
"appName": "${appName}",
"stackName": "${stackName}",
<#list containerList as containerInfo>
"${containerInfo.microServiceName}-major": "${containerInfo.major}",
"${containerInfo.microServiceName}-version": "${containerInfo.version}"
<#if containerInfo_has_next>,</#if></#list>
}
},
"spec": {
"replicas": ${replicas},
"template": {
"metadata": {
"name": "${stackName}",
"labels": {
"appName": "${appName}",
"stackName": "${stackName}",
<#list containerList as containerInfo>
"${containerInfo.microServiceName}-major": "${containerInfo.major}",
"${containerInfo.microServiceName}-version": "${containerInfo.version}"
<#if containerInfo_has_next>,</#if></#list>
}
},
"spec": {
"volumes":
[{
"name": "flumelog",
"hostPath":
{
"path": "/var/logs/ulog/${appName}-${stackName}"
}
}],
"containers": [
<#list containerList as containerInfo>{
"name": "${containerInfo.microServiceName}",
"image": "${containerInfo.imageUrl}",
"ports": [
<#list containerInfo.portList as portInfo>{
"containerPort": ${portInfo.targetPort?c}
}
<#if portInfo_has_next>,</#if>
</#list>
],
"env": [
<#list containerInfo.envList as envInfo>{
"name": "${envInfo.name}",
"value": "${envInfo.value}"
}
<#if envInfo_has_next>,</#if>
</#list>
],
"volumeMounts": [
{
"mountPath": "${containerInfo.logPath}",
"name": "flumelog"
}
],
"resources": {
"limits":{
<#if containerInfo.cpu??>
"cpu": "${containerInfo.cpu}"
</#if>
<#if containerInfo.memory??>
,"memory": "${containerInfo.memory}"
</#if>
}
}
}<#if containerInfo_has_next>,</#if></#list>
]
<#if nodeSelector??> //這裡是判斷是否為null
,
"nodeSelector": {
<#list nodeSelector as nodeSelector>
"${nodeSelector.key}": "${nodeSelector.value}"
<#if nodeSelector_has_next>,</#if>
</#list>
}
</#if>
}
}
}
}
相關推薦
JAVA中使用freemark生成自定義文(json、excel、yaml、txt)
場景:在我們工作中,有時需要生成一些檔案,可能它不是一種標準的格式,比如JSON。 目的:配置一個模板,根據前端傳入的值動態生成配置檔案,並且支援迴圈判斷 專案路徑: 請無視YamlTest.java和YamlTemplate.ftl
Java中Arrays.sort()自定義陣列的升序和降序排序
Java學習中會遇到對陣列進行升序或者降序排序的問題 Java語言提供給我們Array.sort(int [] arr)對陣列進行升序排列 import java.util.Arrays; public class Test1 { public stat
java中Collections對自定義物件進行sort()
基礎學生類 package itcast02; public class Student implements Comparable<Student> { // 學生姓名
java中import匯入自定義包
java 中利用import 匯入自定義包 必須在java 的同一個專案下,可以跨包匯入 需要的 包中的類 例如: 你的java project 下有 a b c 三個包 a包中有aa類 b包中
【奔跑的菜鳥】Java中TreeSet的自定義排列順序
在Java程式設計中有時會用到TreeSet這個類,這個類會對裡面的key進行自動的排序。一般是進行自然序列排序,但是自然序列排序,一般都沒什麼用。我們大多數情況下需要它按照我們自己要求的方式進行排序。下面這個例子就是把一個類的引用放到TreeSet中,然後按照
java中自定義封裝json以及和物件的轉換
首先建立服務端返回的資料型別物件: package com.studio.pojo.util; import org.codehaus.jackson.map.ObjectMapper; publ
Java中動態生成當前日期的文件
java;文件名自動生成;1.Java中動態生成當前日期的文件名稱並且將控制臺的輸出信息輸入到文件中 public static void SaveClonseToFile() throws IOException, FileNotFoundException { File f =
android打包生成apk時自定義文件名版本號。自定義項目字段等等
field col each deb 自定義 文件名 all != null 早期的AS2.0版本左右中這樣配置: app---->build.gradle中設置 applicationVariants.all { variant ->
利用Java 動態代理,自定義註解 讀取配置檔案中的屬性值
Java動態代理在一些中介軟體中經常用到,或者一些大型專案中都會用到。 這裡順帶使用一下自定義註解方式,基於java 反射機制讀取.properties格式檔案。 demo的大致內容包含以下: 1.配置檔案:config.properties url=http://www.
java生成自定義的表ID
需生成如下ID: 56d7ade1-87d1-4f54-8dc8-13611c8c2545 27181ad4-4214-4e12-af3a-911a0103a12f 24cafdfb-eac3-4567-80c0-70d21d096b19 c92046a0-3d94-4d7
iview中使用render屬性生成自定義的標籤
Table表格 關於生成自定義列的表格,效果如下: 程式碼如下: <template> <Table border :columns="columns7" :data="data6"></Table> </templat
淺談 SQL 中的鎖(七)如何生成自定義的自增 ID
在 SQL 表設計中,自增 ID 的使用很廣泛。因為有些資料的屬性並不具有唯一性,所以要給它加上一個生成的主鍵。生成主鍵最方便的方式,就是採用 SQL 產品提供的自增 ID 功能。可能自增 ID 的使用太過方便了,現在大有氾濫的趨勢,甚至有資深的工程師說:所有的表都應該有一個
java對ArrayList中的元素自定義排序
任何類只要實現了Comparable介面就可以呼叫java提供的Array.sort()函式或是是Collections.sort()函式對一個物件列表排序,在重寫Comparable中的函式是我們可以自定義對列表的排序方式,比如要對一個學生列表先按年齡排序
3.自定義返回json格式的數據給前臺(自定義Controller類中的Json方法)
mes eth lose rtu http 容易出錯 結果 execute hide 在mvc的項目中,我們前臺做一些操作時,後臺要返回一些結果給前臺,這個時候我們就需要有一個狀態來標識到底是什麽類型的錯誤, 例如: 執行刪除的時候,如果操作成功(1行受影響
在java中隨機生成一個無序且長度不大於10的字符串
image ack con 技術 exti pen collect tint span package xiangmu; import java.util.ArrayList; import java.util.Collections; import java.ut
C++ MFC中添加自定義消息映射宏及添加消息響應函數
c++ mfc sindsun 反射消息映射宏 下面是我自己在學習C++過程中遇到的問題及解決過程,我把這個共享出來,希望能幫到遇到同樣問題的同胞! 一、添加消息響應函數 afx_msg void OnOwnerDraw(NMHDR * pNotifyStruct, LRESULT* pRes
angularJS中如何寫自定義指令
module ren gif 發送郵件 www amp 提前 ras instance 指令定義 (轉自http://www.cnblogs.com/huangshikun/p/7060787.html) 對於指令,可以把它簡單的理解成在特定DOM元素上運行的函數,指令
Lambda語句中創建自定義類型時,也可指定某種特定類型,方法是在new與{}之間寫上類型名稱
特定 pan sel lambda語句 lam {} where distinct select 如: var fc =...ChildFath = fc.Select(c => new Child_Father { child = c.child, father =
JavaScript中的trim自定義
代碼 原型 div console 字符串 class 位或 color bstr 先直接貼代碼 1 String.prototype.trimfy=function (val){ 2 var demo=String(this); 3
linux中添加自定義命令
系統配置 永久 c中 取消 bsp /etc/ 註意 指令 詳解 centos下設置alias別名,比較簡單,例如: vim /root/.bashrc addalias rm=‘rm -i‘ Linux alias設置指令的別名命令詳解 功能說明:設置指令的別名。語