Java安全无泄漏地替换字符串
我需要一个专家建议以下情况。我有一个字符串模板(假设电子邮件模板),如下所示Java安全无泄漏地替换字符串,java,string,replace,Java,String,Replace,我需要一个专家建议以下情况。我有一个字符串模板(假设电子邮件模板),如下所示 Dear {PERSON_NAME}, We would like to thank you on behalf of {CEO_NAME}, {COMPANY_NAME}. You have been selected for the position of {POSITION_NAME} in {DEPARTMENT_NAME} etc etc 这是更换代码 String body = getTemplateBo
Dear {PERSON_NAME},
We would like to thank you on behalf of {CEO_NAME}, {COMPANY_NAME}. You have been selected
for the position of {POSITION_NAME} in {DEPARTMENT_NAME}
etc etc
这是更换代码
String body = getTemplateBody(tempalteId);
sendMail(
body.replace("{PERSON_NAME}", personName )
.replace("{CEO_NAME}", ceoName),
.replace("{COMPANY_NAME}", companyName),
.replace("{POSITION_NAME}", positionName),
.replace("{DEPARTMENT_NAME}", deptName),
.replace("{X}", someVar1),
.replace("{Y}", someVar2),
.replace("{Z}", someVar3),
.replace("{ETC_ETC}", "etc")
);
我们拥有的:
{PERSON\u NAME}
先存储再处理的效率如何
上述代码中是否存在内存泄漏
或任何问题
?
请注意以上代码只是一个简单的示例,用于解释我的需求,可能不会检查变量名或方法名编码标准。这是怎么回事
使用HashMap
,key作为变量(即“{PERSON\u NAME}”),值作为该键的相应getter(即getPersonName()
)。显然,这个getter必须是一个接口
我想这是一个很好的方法
更有经验的人会怎么想?方法的
String::substring
实现如下:
return Pattern.compile(target.toString(), Pattern.LITERAL)
.matcher(this)
.replaceAll(Matcher.quoteReplacement(replacement.toString()));
使用上述代码,您可以创建9个模式
s和18个intermediateString
s。由于每次调用都会将替换的值内联,因此不会发生内存泄漏,所有引用都会立即被释放,尽管最后的字符串是
但是,通过解析{
-}
封闭值的输入,并使用StringBuilder
组合最终的字符串,可以更有效地实现这一点。这应该是您更关心的问题。这不是一个好的选择吗?如果使用FreeMarker,则可以在单独的模板文件中提供模板,并通过将模板与数据模型(bean或映射
)合并来构建输出
//设置配置
Configuration cfg=新配置(Configuration.VERSION_2_3_21);
setDirectoryForTemplateLoading(新文件(“/where/you/store/templates”);
设置默认编码(“UTF-8”);
//创建数据模型-例如bean或映射
最终映射根=新HashMap();
root.put(“人名”、“乔”);
root.put(“CEO_姓名”、“安妮”);
//获取模板
Template temp=cfg.getTemplate(“myTemplate.ftl”);
//将模板与数据模型合并
Writer out=新的OutputStreamWriter(System.out);
温度过程(根,输出);
如果使用HashMap
作为替换支架,则此解决方案具有线性运行时间。
这个解决方案没有什么特别之处,只是简单的旧java;)
公共静态字符串格式(字符序列文本,最终地图数据)
{
if(text==null)
{
返回“”;
}
final int len=text.length();
if(len<1)
{
返回“”;
}
最终StringBuilder textSB=新StringBuilder();
最终StringBuilder键B=新StringBuilder();
int pos=0;
布尔inKey=false;
char ch;
字符串值;
while(pos
相关(但没有基准或任何东西):这似乎是一种简单的替代方法,但可能不是一种有效的方法。在我的例子中,有20个固定变量需要替换。一个模板在一小时内被新值替换10000次。如果您能知道这次否决的原因,我们将不胜感激。。。只是想从中吸取教训……如果你能负担得起另一种依赖,那就是解决方案。
// Setup config
Configuration cfg = new Configuration(Configuration.VERSION_2_3_21);
cfg.setDirectoryForTemplateLoading(new File("/where/you/store/templates"));
cfg.setDefaultEncoding("UTF-8");
// Create the data model - e.g. a bean or a map
final Map<String, String> root = new HashMap<>();
root.put("PERSON_NAME", "Joe");
root.put("CEO_NAME", "Anne");
// Get the template
Template temp = cfg.getTemplate("myTemplate.ftl");
// Merge the template with the data model
Writer out = new OutputStreamWriter(System.out);
temp.process(root, out);
public static String format(CharSequence text, final Map<String, String> data)
{
if (text == null)
{
return "";
}
final int len = text.length();
if (len < 1)
{
return "";
}
final StringBuilder textSB = new StringBuilder();
final StringBuilder keySB = new StringBuilder();
int pos = 0;
boolean inKey = false;
char ch;
String value;
while (pos < len)
{
ch = text.charAt(pos);
if (ch == '{')
{
if (inKey)
{
throw new IllegalArgumentException("Invalid open key char at " + pos + 1);
}
inKey = true;
keySB.setLength(0);
}
else if (ch == '}')
{
if (!inKey)
{
throw new IllegalArgumentException("Invalid close key char at " + pos + 1);
}
inKey = false;
value = data.get(keySB.toString());
if (value == null)
{
throw new IllegalArgumentException("No value found for key " + keySB);
}
textSB.append(value);
}
else
{
if (inKey)
{
keySB.append(ch);
}
else
{
textSB.append(ch);
}
}
pos++;
}
if (inKey)
{
throw new IllegalArgumentException("None determined key detected.");
}
return textSB.toString();
}