博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JAVA中使用freemark生成自定义文件(json、excel、yaml、txt)
阅读量:7041 次
发布时间:2019-06-28

本文共 11645 字,大约阅读时间需要 38 分钟。

原文:http://blog.csdn.net/jinzhencs/article/details/51461776

 

场景:在我们工作中,有时需要生成一些文件,可能它不是一种标准的格式,比如JSON。

目的:配置一个模板,根据前端传入的值动态生成配置文件,并且支持循环判断


项目路径:

这里写图片描述 

请无视YamlTest.和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
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
podMap = new HashMap
(); 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
> portList = new ArrayList<>(); Map
portMap1 = new HashMap
(); portMap1.put("containerPort", 8080); Map
portMap2 = new HashMap
(); 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>,
] } ] }}

最终效果:

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>,

还是很给力.

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>,
], "resources": { "limits":{ "cpu": "${containerInfo.cpu}", "memory": "${containerInfo.memory}" } } }
] } } }}

 

测试代码:

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>,
} }, "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>,
} }, "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>,
], "env": [ <#list containerInfo.envList as envInfo>{ "name": "${envInfo.name}", "value": "${envInfo.value}" } <#if envInfo_has_next>,
], "volumeMounts": [ { "mountPath": "${containerInfo.logPath}", "name": "flumelog" } ], "resources": { "limits":{ <#if containerInfo.cpu??> "cpu": "${containerInfo.cpu}"
<#if containerInfo.memory??> ,"memory": "${containerInfo.memory}"
} } }<#if containerInfo_has_next>,
] <#if nodeSelector??> //这里是判断是否为null , "nodeSelector": { <#list nodeSelector as nodeSelector> "${nodeSelector.key}": "${nodeSelector.value}" <#if nodeSelector_has_next>,
}
} } }}

 

你可能感兴趣的文章
nginx的upstream目前支持5种方式的分配
查看>>
kill命令详解
查看>>
python基础
查看>>
手机端问题
查看>>
cat
查看>>
iOS修改工程名
查看>>
The RPC Server is unavailable
查看>>
java基础(二)面向对象
查看>>
07(maven+SSH)网上商城项目实战之springmvc乱码问题
查看>>
HelpDesk/ServiceDesk
查看>>
信息化,让ERP回到自己的势力范围去!
查看>>
网络故障排除精解十例(一)
查看>>
/bin/postconf:error while loading shared libraries:libmysqlclient.so.15
查看>>
ECS Linux 服务器中文乱码如何解决?
查看>>
JQuery事件——鼠标事件
查看>>
CISCO路由器DHCP 配置
查看>>
linux-practice(23-24)
查看>>
zeppelin-0.6.2-bin-all/conf/shiro.ini配置详情
查看>>
Lucene
查看>>
python面向对象——属性
查看>>