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")
        );
我们拥有的:

  • 用{}括起来的20个变量,如
    {PERSON\u NAME}
  • 这些变量在单个模板字符串中固定不变
  • 这些变量是唯一的,在同一模板中不会重复任何变量
  • 每个模板的10000个实例在一小时内使用。每天的do为(10000*24)
  • 问题:替换模板字符串中的变量以获得实际结果字符串的有效(不优雅)方法是什么
    先存储再处理的效率如何

    上述代码中是否存在
    内存泄漏
    任何问题

    请注意以上代码只是一个简单的示例,用于解释我的需求,可能不会检查变量名或方法名编码标准。

    这是怎么回事

    使用
    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个
    intermediate
    String
    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();
    }