引入依赖
<!-- 新增模板引擎freemarker -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
使用
- 对象需要转换成map对象
- 字符串变量需要用${变量} 来替换 此变量就是对象里面的属性 也就是key
- 如果属性值可能为空,可以通过${变量!} el表达式来处理npe的情况
- FreemarkerUtil 为模板字符串替换工具类
@Test
public void mapToString() throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
//可以自己定义实体类,我这个是项目中引入的
SmmsTSuggestDemandAttachDoris build = SmmsTSuggestDemandAttachDoris
.builder().storeStock(new BigDecimal(1)).build();
//需要把对象转成map 利用apache包转换
Map<String,Object> describe = BeanUtils.describe(build);
//定义变量
String msg = "";
StringBuffer calProcessNotes = new StringBuffer("门店:%s 款:%s 码:%s,wos计算:\\n");
try{
calProcessNotes.append("计算库存:实物库存:${storeStock} 在单库存:%s 在途库存:%s 可用库存:%s(=实物库存(%sstoreStock) - 在单库存(%s),如果为负数则设置为0),预计库存:%s(=实物库存(%s)- 在单库存(%s) + 在途库存(%s) ,如果为负数则设置为0); \\n");
calProcessNotes.append("历史周期还原销量:%s 如果为负数则设置为0;\\n");
calProcessNotes.append("计算时间:计划离店日期:%s 需求开始日期:%s(=当前日期) 需求结束日期:%s(=min(当前日期(%s)+round(需求覆盖周数(%s)*7-1),计划离店日期(%s)) 如果:计划离店日期为空当前日期(%s)+round(【需求覆盖周数(%s)】*7)-1) ,需求开始日期或者结束日期为空开始日期大于结束日期就不算了直接结束;\\n");
calProcessNotes.append("计算离店日期: 离店日期:%s 计划离店开始日期:%s(=计划离店日期(%s)-round(离店前减少补货周数(%s)*7+1));\\n");
calProcessNotes.append("计算调出保护: 调出保护:%s 上市日期:%s 上市调出保护周数:%s 上市调出保护:%s (如果需求开始日期(%s)小于【上市日期(%s)】+【需求计算参数详情】中的【上市调出保护周数(%s)】*7,则取【需求计算参数详情】中的【上市调出保护(%s)】,否则取【需求计算参数详情】中的【调出保护(%s)】);\\n");
calProcessNotes.append("计算库存及天数: 常规天数:%s 活动天数:%s 离店天数:%s 活动目标库存:%s 常规目标库存:%s(=周均销(%s)*常规天数(%s)/7) 离店目标库存:%s(=离店前补调倍率(%s)*周均销(%s)*离店天数(%s)/7);\\n");
calProcessNotes.append("计算需求和资源: 原始目标库存:%s(=常规目标库存(%s)+活动目标库存(%s)+离店目标库存(%s)) 需求:%s(=round(max(min(max(原始目标库存(%s),核心码量(%s),安全库存(%s)),最大目标深度(%s))-预计库存(%s),0),0)) 可调出量:%s(= round(max(可用库存(%s)-min(max(原始目标库存(%s),调出保护(%s),核心码补量(%s),安全库存(%s)),最大目标深度(%s)),0)));");
//模板引擎替换
System.out.println(FreemarkerUtil.parseContent(calProcessNotes.toString(),describe));
}catch (Exception e) {
calProcessNotes.append("wos计算异常,异常信息:").append(e.getMessage());
msg = calProcessNotes.toString();
}
}
工具类
package cn.lifecycle.btb.aitransfers2.distribute2.utils;
import freemarker.cache.StringTemplateLoader;
import freemarker.template.Configuration;
import java.io.StringReader;
import java.io.StringWriter;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Map;
/**
* @author ws
* @Description: 模板引擎替换字符串变量 ${变量} 遵循el表达式
* @date 2024-03-07 17:43
*/
public class FreemarkerUtil {
/**
* 解析模板
* @param content 内容
* @param dataMap 参数
* @return 字符串转换之后的文本
*/
public static String parseContent(String content, Map<String, Object> dataMap) {
try {
String tempname = hashKeyForDisk(content);
Configuration configuration = new Configuration();
configuration.setNumberFormat("#");
StringTemplateLoader stringLoader = new StringTemplateLoader();
stringLoader.putTemplate(tempname, content);
freemarker.template.Template template = new freemarker.template.Template(tempname, new StringReader(content));
StringWriter stringWriter = new StringWriter();
template.process(dataMap, stringWriter);
configuration.setTemplateLoader(stringLoader);
content = stringWriter.toString();
}catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("Template parsing failed");
}
return content;
}
/**
* A hashing method that changes a string (like a URL) into a hash suitable
* for using as a disk filename.
*/
public static String hashKeyForDisk(String key) {
String cacheKey;
try {
final MessageDigest mDigest = MessageDigest.getInstance("MD5");
mDigest.update(key.getBytes());
cacheKey = bytesToHexString(mDigest.digest());
} catch (NoSuchAlgorithmException e) {
cacheKey = String.valueOf(key.hashCode());
}
return cacheKey;
}
private static String bytesToHexString(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < bytes.length; i++) {
String hex = Integer.toHexString(0xFF & bytes[i]);
if (hex.length() == 1) {
sb.append('0');
}
sb.append(hex);
}
return sb.toString();
}
}