感谢王牌海盗的投稿!本文首发于:http://cosbor.web-144.com/?p=52
=======================================================================================
在上一篇中,我们讲了如何利用并改造Dojo的FilteringSelect组件实现一个拼音检索功能的下拉菜单。本篇文章准备讲讲服务端如何为FilteringSelect更好的提供具有拼音简码的store及实现自动新增实体bean时,将相应name字段转为拼音简码后存储。服务端的例子使用了spring+hibernate。大致过程是编写一个java注解,在model实体类中标注需要进行汉字转拼音的属性字段,利用spring的AOP功能,编写一个统一切面,在dao层对保存实体的save方法进行拦截,将标注的name字段转为拼音简码后注入bean的拼音简码字段,这样使业务编码人员无需再关注对实体name字段进行拼音简码的转换工作。
首先,我们需要准备一个将汉字转换成拼音的工具类CnToSpell,可以从网上下一个叫pinyin4j的jar包,该jar包提供了一套拼音转换的API,使用其编写我们的转换工具类CnToSpell,提供一个静态方法方便的将一个汉字字符串转成拼音字符串。
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
|
public
class
CnToSpell
{
/**
* 将汉字转换为全拼
*
* @param src
* @return String
*/
public
static
String getPinYin( String src )
{
char
[] t1 =
null
;
t1 = src.toCharArray();
// System.out.println(t1.length);
String[] t2 =
new
String[t1.length];
// System.out.println(t2.length);
// 设置汉字拼音输出的格式
HanyuPinyinOutputFormat t3 =
new
HanyuPinyinOutputFormat();
t3.setCaseType( HanyuPinyinCaseType.LOWERCASE );
t3.setToneType( HanyuPinyinToneType.WITHOUT_TONE );
t3.setVCharType( HanyuPinyinVCharType.WITH_V );
String t4 =
""
;
int
t0 = t1.length;
try
{
for
(
int
i =
0
; i < t0 ; i++ )
{
// 判断是否为汉字字符
// System.out.println(t1[i]);
if
( Character.toString( t1[i] ).matches(
"[\\u4E00-\\u9FA5]+"
) )
{
t2 = PinyinHelper.toHanyuPinyinStringArray( t1[i] , t3 );
// 将汉字的几种全拼都存到t2数组中
t4 += t2[
0
];
// 取出该汉字全拼的第一种读音并连接到字符串t4后
}
else
{
// 如果不是汉字字符,直接取出字符并连接到字符串t4后
t4 += Character.toString( t1[i] );
}
}
}
catch
( Exception e )
{
// TODO Auto-generated catch block
e.printStackTrace();
}
return
t4;
}
/**
* 提取每个汉字的首字母
* @param str
* @return String
*/
public
static
String getPinYinHeadChar( String str )
{
HanyuPinyinOutputFormat t3 =
new
HanyuPinyinOutputFormat();
t3.setCaseType( HanyuPinyinCaseType.LOWERCASE );
t3.setToneType( HanyuPinyinToneType.WITHOUT_TONE );
t3.setVCharType( HanyuPinyinVCharType.WITH_V );
String convert =
""
;
for
(
int
j =
0
; j < str.length() ; j++ )
{
char
word = str.charAt( j );
//提取汉字的首字母
String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray( word , t3 );
if
( pinyinArray !=
null
)
{
convert += pinyinArray[
0
].charAt(
0
);
}
else
{
convert += word;
}
}
return
convert;
}
/**
* 将字符串转换成ASCII码
* @param cnStr
* @return String
*/
public
static
String getCnASCII( String cnStr )
{
StringBuffer strBuf =
new
StringBuffer();
//将字符串转换成字节序列
byte
[] bGBK = cnStr.getBytes();
for
(
int
i =
0
; i < bGBK.length ; i++ )
{
// System.out.println(Integer.toHexString(bGBK[i] & 0xff));
//将每个字符转换成ASCII码
strBuf.append( Integer.toHexString( bGBK[i] &
0xff
) );
}
return
strBuf.toString();
}
public
static
void
main( String[] args )
{
String cnStr =
"三国人物"
;
System.out.println( getPinYin( cnStr ) );
System.out.println( getPinYinHeadChar( cnStr ) );
System.out.println( getCnASCII( cnStr ) );
}
}
|
接下来,我们定义一个自定义注解ToPy,用来在实体bean中标注需要进行拼音转换的字段。
1
2
3
4
5
6
7
|
@Retention
(RetentionPolicy.RUNTIME)
@Target
(ElementType.TYPE)
public
@interface
ToPy
{
String nameField();
String pyField();
}
|
三国人物名称的实体SanGuo
01
02
03
04
05
06
07
08
09
10
11
12
|
@Entity
@Table
(name =
"test_sanguo"
)
@ToPy
(nameField=
"name"
,pyField=
"py"
)
//通过自定义的注解标识实体中需要进行中文名称转拼音的字段
public
class
SanGuo
{
private
Long id;
private
String name;
private
String py;
private
String note;
//省略seter、geter方法
}
|
接下来,我们编写一个spring的Advior,利用AOP技术,在保存实体前进行拦截增强,将拼音转换工作统一在切面中完成。代码如下:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
@Aspect
@Component
public
class
ToPyAdvior
{
//定义切点,对dao层的insert的方法调用前进行增强
@Before
( value=
"execution(* com.test..*Dao.insert*(..))"
)
public
void
doAccessCheck(JoinPoint joinPoint)
{
//取得新增实体方法insert*的参数对象
Object obj = joinPoint.getArgs()[
0
];
Class clazz = obj.getClass();
//通过反射获取实体上的自定义注解ToPy
ToPy as = (ToPy)clazz.getAnnotation( ToPy.
class
);
Field sourceField;
Field targetField;
try
{
//根据注解中的定义获取需要转换的中文字段内容
sourceField = clazz.getDeclaredField( as.nameField() );
targetField = clazz.getDeclaredField( as.pyField() );
sourceField.setAccessible(
true
);
targetField.setAccessible(
true
);
String title = sourceField.get( obj ).toString();
//将转化后的拼音简码set到实体类的py字段
targetField.set( obj , CnToSpell.getPinYinHeadChar( title ) );
}
catch
( Exception e )
{
e.printStackTrace();
}
}
}
|
这样一来,业务编码人员只需要在实体类中针对需要拼音转码的字段进行注解即可,而不需要在每个实体的dao层中单独处理字段拼音的编码转换工作了。