JAVA中使用freemark生成自定义文(json、excel、yaml、txt)

来源:互联网 发布:p2p返利的理财源码 编辑:程序博客网 时间:2024/05/22 06:12

场景:在我们工作中,有时需要生成一些文件,可能它不是一种标准的格式,比如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>            }        }    }}
0 0
原创粉丝点击