MessageFormat是text包中的一个常用类,有一次遇到了个问题,发现原来是单引号引起的,遂找了API,并整理一下。
用途:MessageFormat常用将读取到的配置文件、国际化文件中标注的占位符解析,把参数对应的放入占位符的位置上,从而实现引用参数化。
例子:
读取到配置文件中的一条项目:sqlpattern = select * from user where user_type = {0} ,那么调用String sql = MessageFormat.format(sqlpattern, "admin"),得到的字符串sql为
select * from user where user_type = admin。
问题:如果你在mysql的workbench等工具上执行这条语句,是可行的,因为admin会自动被加上'admin',但是在应用程序中,必须加'',从而user_type = '{0}',那么原来的语句变成:select * from user where user_type = '{0}',如果user_type不是参数而是给定的内容,如:
select * from user where user_type = 'manager',当使用MessageFormat读取到的字符串中,单引号会被移除,从而造成sql语法错误。
解析:查看了api,MessageFormat这个类还是蛮复杂的,主要是字符串格式多变化。对于上述例子,其中的sql被MessageFormat定义为pattern(规则),admin被定义为arguments(参数),对于pattern部分的字符串,有如下模式:
String:
StringPartopt
String StringPart
StringPart:
''
' QuotedString '
UnquotedString
也就是说分为引用和非引用字符,引用即是{0}这种占位符,非引用也就是='admin',内容是给定的这种。
对于引用,会去除周围所有符号,但是会保留 ' ',这也是我们正常所见的情况,如:where name='{0}',那么可以得到where name='tom'。而对于非引用,就需要注意了,会移除周围的单引号和左边的花括号,例如 ’admin',那么你只能获得admin,如果是{admin则会报错,但是对于其他符号或者admin}则是没有问题的。
解决:
如果遇到存在单引号又不得不使用的情况下,需要使用双单引号,如' 'admin' '即可,在使用成对的花括号的情况,如' '{admin}' '即可,如果只是使用{,则需要三个单引号,如:'''{'''。不管怎样,双单引号仅代表一对单引号,对于多出的不起作用的单引号(如三个以上单引号)是会被移除的。
还有一种是使用子规则的情况,在处理本地化的时候会遇到,例如:
String pattern = "hello:{0},your last login at{1,time,short} {1,date,short}";其中的{1,time,short} {1,date,short}就是子规则,当使用locale对象的时候常用来匹配其字段输出格式,如:MessageFormat mf = new MessageFormat(pattern,locale);这个时候如果子规则中存在引用的'',是无效的但不会去移除,因为这通常是作用于locale一方的,而非引用的是不允许单引号但是花括号是允许的并且是成对的。