今天公司线上出了一个bug,看看是怎么解决的

今天公司线上出了一个bug,发送短信的内容中,点位符替换错误,原因就是字符串的replace方法

 

  • 短信模板类似:

  •  

{$var}您好:您办理的{$var}业务已到期,请处理!

 

  • 模板中变量{$var}用参数替数组换掉,比如{"张三","人人有功练"}

 

看下原代码处理

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

@Testpublic void testReplace() {String context = "{$var}您好:您办理的{$var}业务已到期,请处理!";String[] param = {"周星星", "人人有功练"};int i = 0;while(context.contains(PRE_BRACES)){int index  =  context.indexOf(PRE_BRACES);String argName = context.substring(index , context.indexOf(SUF_BRACES) + 1);context = context.replace(argName ,String.valueOf( param[i]));i++;}System.out.println(context);}

 

看下输出结果:

 

周星星您好:您办理的周星星业务已到期,请处理!

 

很遗憾,不是我们想要,而这就是因为对replace理解错误导致(原以为只会替换第一个

 

那我们看看replace正确的用法及相关的replaceAll

 

看看api解释

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

replacepublic String replace(char oldChar,                      char newChar)返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的<strong><span style="color:#ff0000;">所有 oldChar</span></strong> 得到的。如果 oldChar 在此 String 对象表示的字符序列中没有出现,则返回对此 String 对象的引用。否则,创建一个新的 String 对象,它所表示的字符序列除了所有的 oldChar 都被替换为 newChar 之外,与此 String 对象表示的字符序列相同。
示例:
"mesquite in your cellar".replace('e', 'o')         returns "mosquito in your collar" "the war of baronets".replace('r', 'y')         returns "the way of bayonets" "sparring with a purple porpoise".replace('p', 't')         returns "starring with a turtle tortoise" "JonL".replace('q', 'x') returns "JonL" (no change) 参数:oldChar - 原字符。newChar - 新字符。返回:一个从此字符串派生的字符串,它将此字符串中的所有 oldChar 替代为 newChar。ss

 

再看看replaceAll

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

replaceAllpublic String replaceAll(String regex,                         String replacement)使用给定的 replacement 替换此字符串所有匹配给定的 <strong><span style="color:#ff0000;">正则表达式</span></strong>的子字符串。调用此方法的 str.replaceAll(regex, repl) 形式与以下表达式产生的结果完全相同:
Pattern.compile( regex ).matcher( str ).replaceAll( repl )注意,在替代字符串中使用反斜杠 (\) 和美元符号 ($) 与将其视为字面值替代字符串所得的结果可能不同;请参阅 Matcher.replaceAll。如有需要,可使用 Matcher.quoteReplacement(java.lang.String) 取消这些字符的特殊含义。
参数:regex - 用来匹配此字符串的正则表达式replacement - 用来替换每个匹配项的字符串返回:所得 String

 

发现2个方法实现的效果是一样的,但是replaceAll可以用正则表达式,而replace只是普通的字符

 

通过实例比较一下

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

String str1 = "{$var}您好:您办理的{$var}业务已到期,请处理!";String str2 = "{$var}您好:您办理的{$var}业务已到期,请处理!";
​
// 普通文本str1 = str1.replace("{$var}", "周星星");// 必须是正则表达式,否则编译器会报错str2 = str2.replaceAll("\\{\\$var\\}", "周星星");
​
System.out.println(str1);System.out.println(str2);

 

转出结果:

 

周星星您好:您办理的周星星业务已到期,请处理!

 

周星星您好:您办理的周星星业务已到期,请处理!

 

再看一下正则替换的例子:

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

String str3 = "aaabbbcccddd111222";String str4 = "aaabbbcccddd111222";
​
// 将所有的"d"替换为"f"str3 = str3.replace("d", "f");// 将所有的数字替换为"f"str4 = str4.replaceAll("\\d", "f");
​
System.out.println(str3);System.out.println(str4);

 

输出结果:

 

aaabbbcccfff111222

 

aaabbbcccdddffffff,相信区别一目了然了!

 

最后再提供一下,刚才问题的一个解决方法(非最优方法)

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

  •  

/**     * 根据指定的字符参数替换变量     *     * @param context   源字符     * @param params    参数     * @param preBraces 分割符     * @param subBraces 分割符     * @return     */public static String replaceAll(String context, Object[] params, String preBraces, String subBraces) {
​
StringBuilder sb = new StringBuilder();int i = 0;String lastContext = StringUtils.EMPTY;
​
while (context.contains(preBraces)) {
​
String subContext = context.substring(NumberConstantEnum.ZERO.getIntValue(), context.indexOf(preBraces));context = context.substring(context.indexOf(subBraces) + 1, context.length());lastContext = context;
​
sb.append(subContext);sb.append(params[i]);
​
i++;}sb.append(lastContext);
​
return sb.toString();}

来源:https://blog.csdn.net/weigeshikebi/article/details/80602228

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值