我是靠谱客的博主 体贴夏天,最近开发中收集的这篇文章主要介绍JAVA中使用freemark生成自定义文(json、excel、yaml、txt)2016-05-27 新增:,觉得挺不错的,现在分享给大家,希望可以做个参考。
概述
场景:在我们工作中,有时需要生成一些文件,可能它不是一种标准的格式,比如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)2016-05-27 新增:的全部内容,希望文章能够帮你解决JAVA中使用freemark生成自定义文(json、excel、yaml、txt)2016-05-27 新增:所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复