锘??xml version="1.0" encoding="utf-8" standalone="yes"?>
]]>
鐪嬬湅Hibernate Validator 鏄庝箞鍋氱殑鍚?涓瑙佸埌濂?鐩鎬俊浣犲氨浼?xì)璇? Oh God, 榪欏氨鏄垜闇瑕佺殑.
浠諱綍鑾峰緱Matrix鎺堟潈鐨勭綉绔欙紝杞澆璇蜂繚鐣欎互涓嬩綔鑰呬俊鎭拰閾炬帴錛?/span>
浣滆咃細(xì)icess(浣滆呯殑blog:http://blog.matrix.org.cn/page/icess)
鍏抽敭瀛楋細(xì)Hibernate Validator
鐢ˋnnotations 緇欑被鎴栬呯被鐨勫睘鎬у姞涓婄害鏉?constraint),鍦ㄨ繍琛屾湡媯(gè)鏌ュ睘鎬у兼槸寰堜紭闆呯殑.Hibernate Validator灝辨槸榪欐牱鐨勪竴涓鏋?璇ユ鏋舵槸鍗佸垎瀹規(guī)槗鐨?灝卞儚鍙傝冩枃妗d腑瀹gО鐨勯偅鏍?,鍑犱箮娌℃湁浠涔堝涔?fàn)鏇簿U?Validator 鏄竴涓獙璇佹鏋?涓嶉渶瑕佸拰Hibernate鐨勫叾浠栭儴鍒嗙粦瀹氬氨鍙互浣跨敤,鍙鍦ㄤ綘鐨勯」鐩腑娣誨姞Hibernate-annotations.jar搴撳氨鍙互浜?閭d箞涓嬮潰灝辮鎴戜滑鐪嬬湅鎬庝箞浣跨敤鍚?
Person.java 綾?/font>
/*
聽(tīng)
*聽(tīng)Created聽(tīng)on聽(tīng)2006-1-12 Person.java
聽(tīng)
*聽(tīng)@author聽(tīng)
聽(tīng)
*/
package聽(tīng)
test.annotation.validator;
import聽(tīng)
org.hibernate.validator.Length;
import聽(tīng)
org.hibernate.validator.Min;
import聽(tīng)
org.hibernate.validator.Valid;
銆
//@Serializability聽(tīng) //嫻嬭瘯鑷畾涔夌害鏉?/font>
public聽(tīng)class聽(tīng)
Person聽(tīng){
聽(tīng)聽(tīng)
private聽(tīng)
String聽(tīng)name;
聽(tīng)聽(tīng)
private聽(tīng)int聽(tīng)
age;
聽(tīng)聽(tīng)
private聽(tīng)
Address聽(tīng)address;
聽(tīng)聽(tīng)
聽(tīng)聽(tīng)
public聽(tīng)
Person()聽(tīng){}
聽(tīng)聽(tīng)
聽(tīng)聽(tīng)
@Valid //娉ㄦ剰姝ゅ
聽(tīng)聽(tīng)
public聽(tīng)
Address聽(tīng)getAddress()聽(tīng){
聽(tīng)聽(tīng)聽(tīng)聽(tīng)
return聽(tīng)
address;
聽(tīng)聽(tīng)
}
聽(tīng)聽(tīng)
public聽(tīng)void聽(tīng)
setAddress(Address聽(tīng)address)聽(tīng){
聽(tīng)聽(tīng)聽(tīng)聽(tīng)
this
.address聽(tīng)=聽(tīng)address;
聽(tīng)聽(tīng)
}
聽(tīng)聽(tīng)
聽(tīng)聽(tīng)
@Min(value聽(tīng)=聽(tīng)
1
)
聽(tīng)聽(tīng)
public聽(tīng)int聽(tīng)
getAge()聽(tīng){
聽(tīng)聽(tīng)聽(tīng)聽(tīng)
return聽(tīng)
age;
聽(tīng)聽(tīng)
}
聽(tīng)聽(tīng)
public聽(tīng)void聽(tīng)
setAge(
int聽(tīng)
age)聽(tīng){
聽(tīng)聽(tīng)聽(tīng)聽(tīng)
this
.age聽(tīng)=聽(tīng)age;
聽(tīng)聽(tīng)
}
聽(tīng)聽(tīng)
聽(tīng)聽(tīng)
@Length(min聽(tīng)=聽(tīng)
4
)
聽(tīng)聽(tīng)
public聽(tīng)
String聽(tīng)getName()聽(tīng){
聽(tīng)聽(tīng)聽(tīng)聽(tīng)
return聽(tīng)
name;
聽(tīng)聽(tīng)
}
聽(tīng)聽(tīng)
public聽(tīng)void聽(tīng)
setName(String聽(tīng)name)聽(tīng){
聽(tīng)聽(tīng)聽(tīng)聽(tīng)
this
.name聽(tīng)=聽(tīng)name;
聽(tīng)聽(tīng)
}
}
銆
Address.java 綾?/font>
/*
聽(tīng)
*聽(tīng)Created聽(tīng)on聽(tīng)2006-1-12 Address.java
聽(tīng)
*聽(tīng)@author聽(tīng)
聽(tīng)
*/
package聽(tīng)
test.annotation.validator;
import聽(tīng)
org.hibernate.validator.Length;
import聽(tīng)
org.hibernate.validator.Max;
import聽(tīng)
org.hibernate.validator.Min;
public聽(tīng)class聽(tīng)
Address聽(tīng){
聽(tīng)聽(tīng)
private聽(tīng)
String聽(tīng)street;
聽(tīng)聽(tīng)
private聽(tīng)int聽(tīng)
num;
聽(tīng)聽(tīng)
聽(tīng)聽(tīng)
public聽(tīng)
Address()聽(tīng){}
聽(tīng)聽(tīng)
聽(tīng)聽(tīng)
@Min(value聽(tīng)=聽(tīng)
1
)
聽(tīng)聽(tīng)
@Max(value聽(tīng)=聽(tīng)
100
)
聽(tīng)聽(tīng)
public聽(tīng)int聽(tīng)
getNum()聽(tīng){
聽(tīng)聽(tīng)聽(tīng)聽(tīng)
return聽(tīng)
num;
聽(tīng)聽(tīng)
}
聽(tīng)聽(tīng)
public聽(tīng)void聽(tīng)
setNum(
int聽(tīng)
num)聽(tīng){
聽(tīng)聽(tīng)聽(tīng)聽(tīng)
this
.num聽(tīng)=聽(tīng)num;
聽(tīng)聽(tīng)
}
聽(tīng)聽(tīng)
聽(tīng)聽(tīng)
@Length(min聽(tīng)=聽(tīng)
3
,max聽(tīng)=聽(tīng)
8
)
聽(tīng)聽(tīng)
public聽(tīng)
String聽(tīng)getStreet()聽(tīng){
聽(tīng)聽(tīng)聽(tīng)聽(tīng)
return聽(tīng)
street;
聽(tīng)聽(tīng)
}
聽(tīng)聽(tīng)
public聽(tīng)void聽(tīng)
setStreet(String聽(tīng)street)聽(tīng){
聽(tīng)聽(tīng)聽(tīng)聽(tīng)
this
.street聽(tīng)=聽(tīng)street;
聽(tīng)聽(tīng)
}
}
涓婇潰鏄袱涓敤 Validator Annotations 娉ㄩ噴鐨?綾? 姣忎釜灞炴ч兘鐢?綰︽潫闄愬埗浜?聽(tīng) 涓嬮潰鐪嬬湅嫻嬭瘯鐨勭被鍚?
TestValidator.java 綾?/code>
/*
聽(tīng)
*聽(tīng)Created聽(tīng)on聽(tīng)2006-1-12
聽(tīng)
*聽(tīng)@author聽(tīng)icerain
聽(tīng)
*/
package聽(tīng)
test.annotation.validator;
import聽(tīng)
org.hibernate.validator.ClassValidator;
import聽(tīng)
org.hibernate.validator.InvalidValue;
public聽(tīng)class聽(tīng)
TestValidator聽(tīng){
聽(tīng)聽(tīng)
public聽(tīng)void聽(tīng)
test()聽(tīng){
聽(tīng)聽(tīng)聽(tīng)聽(tīng)
Address聽(tīng)add聽(tīng)=聽(tīng)
new聽(tīng)
Address();
聽(tīng)聽(tīng)聽(tīng)聽(tīng)
add.setNum(
0
);
聽(tīng)聽(tīng)聽(tīng)聽(tīng)
add.setStreet(
"1"
);
聽(tīng)聽(tīng)聽(tīng)聽(tīng)
聽(tīng)聽(tīng)聽(tīng)聽(tīng)
Person聽(tīng)p聽(tīng)=聽(tīng)
new聽(tīng)
Person();
聽(tīng)聽(tīng)聽(tīng)聽(tīng)
p.setAddress(add);
聽(tīng)聽(tīng)聽(tīng)聽(tīng)
p.setAge(
0
);
聽(tīng)聽(tīng)聽(tīng)聽(tīng)
p.setName(
"ice"
);
聽(tīng)聽(tīng)聽(tīng)聽(tīng)
聽(tīng)聽(tīng)聽(tīng)聽(tīng)
/******************Test聽(tīng)validator聽(tīng)********/
聽(tīng)聽(tīng)聽(tīng)
// 娉ㄦ剰璇ュ鍙獙璇佷簡(jiǎn)Person 涓轟簡(jiǎn)璇存槑 @Valid 娉ㄩ噴鐨勪嬌鐢?/font>
聽(tīng)聽(tīng)聽(tīng)聽(tīng)
ClassValidator<Person>聽(tīng)classValidator聽(tīng)=聽(tīng)
new聽(tīng)
ClassValidator<Person>聽(tīng)(Person.
class
);
聽(tīng)聽(tīng)聽(tīng)聽(tīng)
InvalidValue[]聽(tīng)validMessages聽(tīng)=聽(tīng)classValidator.getInvalidValues(p);
聽(tīng)聽(tīng)聽(tīng)聽(tīng)
for聽(tīng)
(InvalidValue聽(tīng)value聽(tīng):聽(tīng)validMessages)聽(tīng){
聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)
聽(tīng)聽(tīng)聽(tīng)聽(tīng)
System.out.println(
"InvalidValue聽(tīng)鐨勯暱搴︽槸:"聽(tīng)
+聽(tīng)validMessages.length
聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)
+
"聽(tīng).聽(tīng)楠岃瘉娑堟伅鏄?聽(tīng)"聽(tīng)
+聽(tīng)value.getMessage()聽(tīng)
聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)
+聽(tīng)
"聽(tīng).聽(tīng)PropertyPath聽(tīng)鏄?"聽(tīng)
+聽(tīng)value.getPropertyPath()
聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)
+
"聽(tīng).\n\t聽(tīng)PropertyName聽(tīng)鏄?聽(tīng)"聽(tīng)
+value.getPropertyName()
聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)
+聽(tīng)
"Value聽(tīng)鏄?聽(tīng)"聽(tīng)
+聽(tīng)value.getValue()
聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)
+
"聽(tīng)Bean聽(tīng)鏄?聽(tīng)"
+聽(tīng)value.getBean()
聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)
+
"\n\t聽(tīng)BeanClass聽(tīng)鏄?"聽(tīng)
+聽(tīng)value.getBeanClass());
聽(tīng)聽(tīng)聽(tīng)聽(tīng)
}
聽(tīng)聽(tīng)
}
聽(tīng)聽(tīng)
聽(tīng)聽(tīng)
public聽(tīng)static聽(tīng)void聽(tīng)
main(String[]聽(tīng)args)聽(tīng){
聽(tīng)聽(tīng)聽(tīng)聽(tīng)
new聽(tīng)
TestValidator().test();
聽(tīng)聽(tīng)
}
}
銆
紼嬪簭鐨勮緭鍑哄涓? InvalidValue 鐨勯暱搴︽槸:4 . 楠岃瘉娑堟伅鏄? 蹇呴』澶т簬絳変簬 1 . PropertyPath 鏄?age . PropertyName 鏄? age. Value 鏄? 0 Bean 鏄? test.annotation.validator.Person@dd87b2 BeanClass 鏄?class test.annotation.validator.Person InvalidValue 鐨勯暱搴︽槸:4 . 楠岃瘉娑堟伅鏄? 闀垮害蹇呴』浠嬩簬 4 涓?2147483647 涔嬮棿 . PropertyPath 鏄?name . PropertyName 鏄? name. Value 鏄? ice Bean 鏄? test.annotation.validator.Person@dd87b2 BeanClass 鏄?class test.annotation.validator.Person InvalidValue 鐨勯暱搴︽槸:4 . 楠岃瘉娑堟伅鏄? 蹇呴』澶т簬絳変簬 1 . PropertyPath 鏄?address.num . PropertyName 鏄? num. Value 鏄? 0 Bean 鏄? test.annotation.validator.Address@197d257 BeanClass 鏄?class test.annotation.validator.Address InvalidValue 鐨勯暱搴︽槸:4 . 楠岃瘉娑堟伅鏄? 闀垮害蹇呴』浠嬩簬 3 涓?8 涔嬮棿 . PropertyPath 鏄?address.street . PropertyName 鏄? street. Value 鏄? 1 Bean 鏄? test.annotation.validator.Address@197d257 BeanClass 鏄?class test.annotation.validator.Address 鍙互鐪嬪嚭涓嶆弧瓚崇害鏉熺殑鍊奸兘琚寚鍑轟簡(jiǎn). 鍚屾椂璇ュ彞: 鎴戜滑鍙獙璇佷簡(jiǎn) Person. 鍦≒erson閲岄潰鐨凙ddress鐨勫睘鎬?鐢變簬鏈?code style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New',Courier">@Valid Annotations 鎵浠?Address鐨勭浉鍏沖睘鎬т篃琚満鑱旈獙璇佷簡(jiǎn) . InvalidValue 鐨勯暱搴︽槸:2 . 楠岃瘉娑堟伅鏄? 蹇呴』澶т簬絳変簬 1 . PropertyPath 鏄?age . PropertyName 鏄? age. Value 鏄? 0 Bean 鏄? test.annotation.validator.Person@18fef3d BeanClass 鏄?class test.annotation.validator.Person InvalidValue 鐨勯暱搴︽槸:2 . 楠岃瘉娑堟伅鏄? 闀垮害蹇呴』浠嬩簬 4 涓?2147483647 涔嬮棿 . PropertyPath 鏄?name . PropertyName 鏄? name. Value 鏄? ice Bean 鏄? test.annotation.validator.Person@18fef3d BeanClass 鏄?class test.annotation.validator.PersonClassValidator<Person>聽(tīng)classValidator聽(tīng)=聽(tīng)new聽(tīng)ClassValidator<Person>聽(tīng)(Person.class);
濡傛灉 鎶?/span>
@Valid Annotations 鍘繪帀,緇撴灉濡備笅:
鍙互鐪嬪嚭 娌℃湁楠岃瘉 Address.
褰撶劧浜?,浣犺繕鍙互鍙獙璇佷竴涓睘鎬?, 娌℃湁蹇呰楠岃瘉鏁翠釜綾?鍙渶瑕佸湪璋冪敤
classValidator.getInvalidValues(p,"age")鏂規(guī)硶鏃?鍔犱笂浣犺楠岃瘉鐨勫睘鎬у氨鍙互浜?濡傛垜浠彧鎯抽獙璇乤ge 灞炴?鎶婁唬鐮佹敼涓哄涓嬫墍紺?
InvalidValue[] validMessages = classValidator.getInvalidValues(p,"age"); /
/鍙獙璇乤ge 灞炴?/font>
榪愯緇撴灉濡備笅:
InvalidValue 鐨勯暱搴︽槸:1 . 楠岃瘉娑堟伅鏄? 蹇呴』澶т簬絳変簬 1 . PropertyPath 鏄?age .
PropertyName 鏄? age. Value 鏄? 0 Bean 鏄? test.annotation.validator.Person@1457cb
BeanClass 鏄?class test.annotation.validator.Person
鍙槸楠岃瘉浜?age 灞炴?
鎬庝箞鏍?,寰堢畝鍗曞惂. 鍏充簬 Hibernate Validator 鍐呭緩鐨勯獙璇丄nnotations 澶у鍙互鐪嬬湅 API 鎴栬?鍙傝冩枃妗?涓枃鐗堟垜姝e湪緲昏瘧涓?璇瘋闂垜鐨?Blog 鑾峰緱鏈鏂頒俊鎭?.
濡傛灉浣犺鍐欒嚜宸辯殑綰︽潫鍛?, 浣犱笉鐢ㄦ媴蹇?,榪欎篃鏄緢瀹規(guī)槗鐨?
浠諱綍綰︽潫鏈変袱閮ㄥ垎緇勬垚: [綰︽潫鎻忚堪絎?鍗蟲(chóng)敞閲奭the constraint descriptor (the annotation) 鍜孾綰︽潫validator 鍗?瀹炵幇綾籡 the constraint validator (the implementation class).涓嬮潰鎴戜滑鎵╁睍Hibernate Test suit 涓殑涓涓猅est 鏉ヨ瑙d竴涓?
棣栧厛: 瑕佸0鏄庝竴涓?/span>
constraint descriptor .濡備笅:
package聽(tīng)
test.annotation.validator;
import聽(tīng)
java.lang.annotation.Documented;
import聽(tīng)static聽(tīng)
java.lang.annotation.ElementType.TYPE;
import聽(tīng)static聽(tīng)
java.lang.annotation.ElementType.FIELD;
import聽(tīng)static聽(tīng)
java.lang.annotation.ElementType.METHOD;
import聽(tīng)
java.lang.annotation.Retention;
import聽(tīng)static聽(tīng)
java.lang.annotation.RetentionPolicy.RUNTIME;
import聽(tīng)
java.lang.annotation.Target;
import聽(tīng)
org.hibernate.validator.ValidatorClass;
/**
聽(tīng)
*聽(tīng)Dummy聽(tīng)sample聽(tīng)of聽(tīng)a聽(tīng)bean-level聽(tīng)validation聽(tīng)annotation
聽(tīng)
*
聽(tīng)
*聽(tīng)
@author聽(tīng)
Emmanuel聽(tīng)Bernard
聽(tīng)
*/
@ValidatorClass(SerializabilityValidator.
class
)
@Target({METHOD,FIELD,TYPE})
@Retention(RUNTIME)
@Documented
public聽(tīng)
@interface聽(tīng)Serializability聽(tīng){
聽(tīng)聽(tīng)
int聽(tīng)
num()聽(tīng)
default聽(tīng)
11
;
聽(tīng)聽(tīng)
String聽(tīng)message()聽(tīng)
default聽(tīng)
"bean聽(tīng)must聽(tīng)be聽(tīng)serialiable"
;
}
@ValidatorClass(SerializabilityValidator.
class
) 鎸囧嚭浜?
constraint validator 綾?
@Target({METHOD,FIELD,TYPE})
@Retention(RUNTIME)
@Documented聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)
榪欏嚑涓垜灝變笉鐢ㄨВ閲婁簡(jiǎn)鍚?
Serializability聽(tīng)閲岄潰澹版槑浜?jiǎn)涓涓?message 鏄劇ず綰︽潫鐨勬彁紺轟俊鎭? num 鍙槸涓轟簡(jiǎn)璇存槑涓涓柟闈?鍦ㄨ繖閲岄潰娌℃湁瀹為檯鐢ㄩ旂敤 .
鐒跺悗灝辨槸 瀹炵幇涓涓?/span>
constraint validator 綾?璇ョ被瑕佸疄鐜?/span>Validator<ConstraintAnnotation>.榪欓噷鏄?/span>SerializabilityValidator.java 濡備笅:
//$Id:聽(tīng)SerializabilityValidator.java,v聽(tīng)1.3聽(tīng)2005/11/17聽(tīng)18:12:11聽(tīng)epbernard聽(tīng)Exp聽(tīng)$
constraint descriptor 閲岄潰鐨勫睘鎬?濡備笂闈㈡垜浠0鏄庣殑 num
package聽(tīng)
test.annotation.validator;
import聽(tīng)
java.io.Serializable;
import聽(tīng)
org.hibernate.validator.Validator;
/**
聽(tīng)
*聽(tīng)Sample聽(tīng)of聽(tīng)a聽(tīng)bean-level聽(tīng)validator
聽(tīng)
*
聽(tīng)
*聽(tīng)
@author聽(tīng)
Emmanuel聽(tīng)Bernard
聽(tīng)
*/
public聽(tīng)class聽(tīng)
SerializabilityValidator聽(tīng)
implements聽(tīng)
Validator<Serializability>,聽(tīng)Serializable聽(tīng){
聽(tīng)聽(tīng)
public聽(tīng)boolean聽(tīng)
isValid(Object聽(tīng)value)聽(tīng){
聽(tīng)聽(tīng)聽(tīng)
//榪欓噷鍙槸Validator 閲岄潰鐨?瀹炵幇楠岃瘉瑙勫垯鐨?鏂規(guī)硶. value 鏄楠岃瘉鐨勫?
聽(tīng)聽(tīng)聽(tīng)聽(tīng)
System.out.println(
"IN聽(tīng)SerializabilityValidator聽(tīng)isValid:"
+value.getClass()+
":聽(tīng)"聽(tīng)
+value.toString());
聽(tīng)聽(tīng)聽(tīng)聽(tīng)
return聽(tīng)
value聽(tīng)instanceof聽(tīng)Serializable;
聽(tīng)聽(tīng)}
聽(tīng)聽(tīng)public聽(tīng)void聽(tīng)initialize(Serializability聽(tīng)parameters)聽(tīng){
聽(tīng)聽(tīng)聽(tīng)聽(tīng)//聽(tīng)鍦ㄨ繖閲屽彲浠?鍙栧緱
聽(tīng)聽(tīng)聽(tīng)聽(tīng)
System.out.println(
"IN聽(tīng)SerializabilityValidator:聽(tīng)parameters:"
+聽(tīng)parameters.num()聽(tīng));
聽(tīng)聽(tīng)
}
}
鐒跺悗鍦ㄤ綘鐨勭被涓簲鐢ˊSerializability聽(tīng) 灝卞彲浠ョ害鏉熶竴涓被瀹炵幇
Serializable 鎺ュ彛浜? 濡備笅:
鍦ㄦ垜浠殑Person.java綾?娣誨姞@Serializability聽(tīng) Annotations ,鎶奝erson.java 涓殑
//@Serializability //嫻嬭瘯鑷畾涔夌害鏉?娉ㄩ噴鍘繪帀灝眔k浜?
InvalidValue 鐨勯暱搴︽槸:3 . 楠岃瘉娑堟伅鏄?
bean must be serialiable
. PropertyPath 鏄?null .
PropertyName 鏄? null. Value 鏄? test.annotation.validator.Person@1a73d3c Bean 鏄? test.annotation.validator.Person@1a73d3c
BeanClass 鏄?class test.annotation.validator.Person
榪愯緇撴灉濡備笅:
鐜板湪鎶奝erson綾誨疄鐜?java.io.Serializable 鎺ュ彛 鍒欐病鏈夊嚭鐜?楠岃瘉閿欒娑堟伅.
娑堟伅鐨勫浗闄呭寲涔熸槸寰堢畝鍗曠殑,鎶?/span>
Serializability聽(tīng) 涓殑message 鏀逛負(fù)浠}鎵╀綇鐨?灞炴ф枃浠剁殑Key灝卞彲浠ヤ簡(jiǎn)
public聽(tīng)
@interface聽(tīng)Serializability聽(tīng){
聽(tīng)聽(tīng)
int聽(tīng)
num()聽(tīng)
default聽(tīng)
11
;
聽(tīng)聽(tīng)
String聽(tīng)message()聽(tīng)
default聽(tīng)
"{Serializable}";
//"bean聽(tīng)must聽(tīng)be聽(tīng)serialiable";
//娑堟伅鐨勫浗闄呭寲
}
鐒跺悗緙栬緫璧勬枡鏂囦歡. 娉ㄦ剰 璇ヨ祫婧愭枃浠朵腑瑕佸寘鎷?Hibernate Validator 鍐呭緩鐨勮祫婧? 鍙互鍦ㄨorg\hibernate\validator\resources 鍖呴噷闈㈢殑璧勬簮鏂囦歡鍩虹涓婁慨鏀?,鍦ㄦ墦鍖呴噷闈?榪欐牱灝卞彲浠ヤ簡(jiǎn). 鑷繁鎵撳寘鍙兘涓嶅お鏂逛究.浣犲彲浠ユ妸璇ュ寘閲岄潰鐨勬枃浠跺鍒跺嚭鏉?鐒跺悗鏀懼埌浣犺嚜宸辯殑欏圭洰鍖呬笅鍦ㄨ嚜宸辯紪杈? 璇ユ祴璇曚腑 鎴戞槸鏀懼湪 test\resources 鍖呬笅鐨?
鐒跺悗鍦?璧勬簮鏂囦歡涓坊鍔?
Serializable = '''''' 榪欎箞涓琛? 鏍蜂緥濡備笅:
#DefaultValidatorMessages.properties (DefaultValidatorMessages_zh.properties 涓嶅啀鍒楀嚭^_^)
銆
#涓嬮潰鏄?Hibernate Validator 鍐呭緩鐨勫浗闄呭寲娑堟伅
validator.assertFalse= assertion failed
validator.assertTrue= assertion failed
validator.future= must be a future date
validator.length= length must be between {min} and {max}
validator.max= must be less than or equal to {value}
validator.min= must be greater than or equal to {value}
validator.notNull= may not be null
validator.past= must be a past date
validator.pattern= must match "{regex}"
validator.range= must be between {min} and {max}
validator.size= size must be between {min} and {max}
#涓嬮潰鏄嚜瀹氫箟鐨勬秷鎭?/font>
Serializable= Bean not Serializable聽(tīng) //鍔犱笂鑷繁瀹氫箟鐨勫浗闄呭寲娑堟伅.
鍦ㄦ瀯閫?/span>
ClassValidator
鏃惰娣諱笂 璧勬簮鏂囦歡 濡備笅:(鍦ㄦ祴璇曠被涓?
ClassValidator<Person> classValidator = new ClassValidator<Person> (Person.class,ResourceBundle.getBundle("test.resources.DefaultValidatorMessages"));//鍔犺澆璧勬簮
榪欐牱灝卞彲浠ヤ簡(jiǎn) .聽(tīng) 褰撶劧 浣犺繕鍙互 鏇存敼 Hibernate Validator 鐨勬秷鎭?涓嶆槸鍦ㄤ笂闈㈢殑璧勬簮鏂囦歡涓洿鎺ヤ慨鏀?/font>
validator.length = ... 絳夌瓑
) , 榪樿寰?Validator 娉ㄩ噴涓湁涓?message 鍏冪礌鍚? 浣犱互鍓嶇敤鐨勯兘鏄粯璁ゅ?鐜板湪浣犲彲浠ヨ涓轟綘鑷繁瀹氫箟鐨勪簡(jiǎn).
濡?validator.length 鎴戞妸浠栨敼涓?"璇ュ瓧絎︿覆鐨勯暱搴︿笉絎﹀悎瑙勫畾鑼冨洿鑼冨洿". 鍦ㄨ祫婧愭枃浠朵腑娣誨姞涓琛岄敭鍊煎睘鎬у(key瀹氫箟涓?"myMsg")濡備笅:
myMsg=璇ュ瓧絎︿覆鐨勯暱搴︿笉絎﹀悎瑙勫畾鑼冨洿鑼冨洿
騫朵笖榪樿鍦?/font> @Length 娉ㄩ噴涓彁渚沵essage鐨勫紩鐢ㄧ殑key 濡備笅 @Length(min = 4,message = "{ myMsg }")
鍐嶄竴嬈¤繍琛屾祴璇?,鎴戜滑灝卞彲浠ョ湅鍒頒笂闈袱鏉¤嚜瀹氫箟緇戝畾鐨勬秷鎭簡(jiǎn) .濡備笅:
InvalidValue 鐨勯暱搴︽槸:3 . 楠岃瘉娑堟伅鏄?/font>: Bean 涓嶆槸 鍙?Serializable . PropertyPath 鏄?null .
PropertyName 鏄? null. Value 鏄? test.annotation.validator.Person@1bd4722 Bean 鏄? test.annotation.validator.Person@1bd4722
BeanClass 鏄?class test.annotation.validator.Person
InvalidValue 鐨勯暱搴︽槸:3 . 楠岃瘉娑堟伅鏄?/font>: 璇ュ瓧絎︿覆鐨勯暱搴︿笉絎﹀悎瑙勫畾鑼冨洿鑼冨洿 . PropertyPath 鏄?name .
PropertyName 鏄? name. Value 鏄? ice Bean 鏄? test.annotation.validator.Person@1bd4722
BeanClass 鏄?class test.annotation.validator.Person
鎬庝箞鏍?姣斾綘鎯寵薄鐨勭畝鍗曞惂.
OK 涓婇潰鎴戜滑璁ㄨ浜?
Hibernate Validator 鐨勪富瑕佺敤娉? 浣嗘槸 璇ユ鏋舵湁浠涔堢敤鍛? ^_^
鐪嬪埌榪欓噷鍏跺疄涓嶇敤鎴戝湪澶氳浜?澶у閮界煡閬撴庝箞鐢?浠涔堟椂鍊欑敤. 浣滀負(fù)涓綃囦粙緇嶆ф枃绔犳垜榪樻槸鍦ㄦ緇欏嚭涓涓渶甯哥敤鐨勪緥瀛愬惂,鏇村ソ鐨勪嬌鐢ㄦ柟寮忓ぇ瀹舵參鎱㈡寲鎺樺惂.
姣斿 : 浣犵幇鍦ㄥ湪寮鍙戜竴涓漢鍔涜祫婧?HR)緋葷粺 (鍏跺疄鏄垜浠珽RP璇劇▼鐨勪竴涓綔涓?^_^), 閲岄潰瑕佸鐞嗗ぇ閲忕殑鏁版嵁,灝ゅ叾鏄湪杈撳叆鍚勭璧勬枡鏃?濡?鐧昏鍛樺伐淇℃伅. 濡傛灉浣犲叕鍙哥殑鍛樺伐鐨勫勾榫勮姹傛槸18 -- 60 閭d箞浣犳墍杈撳叆鐨勫勾榫勫氨涓嶈兘瓚呭嚭榪欎釜鑼冨洿. 浣犲彲鑳戒細(xì)璇磋繖寰堝鏄撳晩 , 涓嶇敤Validator灝卞彲浠ヨВ鍐沖晩.榪欎繚鎸佹暟鎹墠楠岃瘉灝卞彲浠ュ暒 濡俰f ( e.getAge() > 60 || e.getAge() < 18 ) ........ 緇欏嚭閿欒淇℃伅 鐒跺悗鎻愮ず閲嶆柊杈撳叆涓嶅氨O(jiān)K鍟?鐢ㄥ緱鐫 鍏村笀鍔ㄤ紬鐨勬潵涓涓夋柟妗嗘灦鍚?
鏄晩 褰撳氨楠岃瘉榪欎竴涓睘鎬ф椂, 娌℃湁蹇呰鍟?! 浣嗘槸涓涓湡姝g殑HR 緋葷粺,浼?xì)鍙湁涓涓睘鎬ц楠岃瘉鍚? 鎭愭曡鏈塏澶氬惂
浣犺鏄瘡涓涓兘閭f牱 鍐欎竴孌甸獙璇佷唬鐮?鏄笉鏄緢鐑?chǔ)鍟?,鍐典笖涔熶笉鏂逛究浠g爜閲嶇敤. 鐜板湪鑰冭檻涓浜?Validator 鏄笉鏄洿楂樻晥鍟?鎷︽埅鍒?綰︽潫榪濅緥鐨?灞炴?灝卞彲浠ョ洿鎺ュ緱鍒?鍥介檯鍖栫殑娑堟伅 鍙互鎶婅娑堟伅鏄劇ず鍒頒竴涓脊鍑哄璇濇涓?鎻愮ず鏇存聽(tīng) !
Validator鐨勭敤澶勪笉鍙繖涓縐?,浣犲彲浠ユ兂鍒板浣曠敤鍛?! 嬈㈣繋鍙戣〃浣犵殑楂樿!!
OK 鍒版 鎴戜滑鐨?Hibernate Validator 涔嬫梾灝辮鍏堝憡涓孌佃惤浜?. 甯屾湜榪欐槸浠や綘蹇?jī)鏃芳湠鎬$殑涓嬈″瘨鍐箣鏃?
鎶婁綘瀛﹀埌鐨勫簲鐢ㄥ埌浣犵殑欏圭洰涓惂,涓瀹氫細(xì)鎻愰珮?shù)綘鐨勭敓漶旂巼鐨? 鐩鎬俊鎴?,娌¢敊鐨劼?^_^ !
浠諱綍鑾峰緱Matrix鎺堟潈鐨勭綉绔欙紝杞澆璇蜂繚鐣欎互涓嬩綔鑰呬俊鎭拰閾炬帴錛?/span>
浣滆咃細(xì)icess(浣滆呯殑blog:http://blog.matrix.org.cn/page/icess)
鍏抽敭瀛楋細(xì)Hibernate Validator
鎴戝湪鍓嶉潰涓綃囨枃绔?lt;Hibernate Annotations 瀹炴垬-- 浠?hbm.xml 鍒?Annotations>:
涓?鏈夊緢澶氬紑鍙戣呭湪璋堣涓彁鍒?鏈夋病鏈夊繀瑕佷粠 hbm.xml 寰 Annotations 涓婅漿縐? 閭d箞鍦ㄨ繖綃囨枃绔犱腑鎴戜滑灝辨潵璁ㄨ涓涓?hbm.xml 涓?Annotations鐨勪紭緙虹偣,鐪嬬湅閭g鎯呭喌鏈閫傚悎浣?
棣栧厛,璁ㄨ涓涓?xml 閰嶇疆鏂囦歡鐨勪紭鐐? 涓漢璁や負(fù)涓昏浼樼偣灝辨槸褰撲綘鏀瑰彉搴曞眰閰嶇疆鏃?涓嶉渶瑕佹敼鍙樺拰閲嶆柊緙栬瘧浠g爜,鍙渶瑕佸湪xml 涓洿鏀瑰氨鍙互浜?渚嬪 Hibernate.cfg.xml 褰撲綘瑕佹洿鏀瑰簳灞傛暟鎹簱鏃? 鍙鏇存敼閰嶇疆鏂囦歡灝卞彲浠ヤ簡(jiǎn).Hibernate浼?xì)湄?fù)浣犲仛濂藉埆鐨勪簨鎯?
閭d箞xml鐨勭己鐐瑰憿,涓漢璁や負(fù)鏈変互涓嬪嚑鐐?
鎻忚堪絎﹀錛屼笉瀹規(guī)槗璁板繂,鎺屾彙 瑕佹繁鍏ヤ簡(jiǎn)瑙h繕鏈夌湅DTD鏂囦歡
鏃犳硶鍋氳嚜鍔ㄦ牎楠岋紝闇瑕佷漢宸ユ煡鎵?
璇誨彇鍜岃В鏋恱ml閰嶇疆瑕佹秷鑰椾竴瀹氭椂闂達(dá)紝瀵艱嚧搴旂敤鍚姩鎱紝涓嶄究浜庢祴璇曞拰緇存姢
褰撶郴緇熷緢澶ф椂錛屽ぇ閲忕殑xml鏂囦歡闅句互綆$悊
榪愯涓繚瀛榵ml閰嶇疆闇瑕佹秷鑰楅澶栫殑鍐呭瓨
鍦∣/R Mapping鐨勬椂鍊欓渶瑕佸湪java鏂囦歡鍜寈ml閰嶇疆鏂囦歡涔嬮棿浜ゆ浛錛屽澶т簡(jiǎn)宸ヤ綔閲?
鍏朵腑絎竴 浜岀偣 鍊熷姪浜庡厛榪涚殑IDE 鍙兘涓嶆槸浠涔堥棶棰? 浣嗘槸瀵瑰垵瀛﹁呰繕鏄釜闂 ^_^.
涓嬮潰鎴戜滑鐪嬬湅 Annotations鐨?鐗規(guī)у惂! 鍙互瑙e喅xml閬囧埌鐨勯棶棰?鏈変互涓嬩紭鐐?/p>
鎻忚堪絎﹀噺灝戙備互鍓嶅湪xml閰嶇疆涓線寰闇瑕佹弿榪癹ava灞炴х殑綾誨瀷錛屽叧緋葷瓑絳夈傝屽厓鏁版嵁鏈韓灝辨槸java璇█錛屼粠鑰岀渷鐣ヤ簡(jiǎn)澶ч噺鐨勬弿榪扮
緙栬瘧鏈熸牎楠屻傞敊璇殑鎵規(guī)敞鍦ㄧ紪璇戞湡闂村氨浼?xì)鎶ラ敊銆?
鍏冩暟鎹壒娉ㄥ湪java浠g爜涓紝閬垮厤浜?jiǎn)棰濆鐨勬枃錃g緇存姢宸ヤ綔
鍏冩暟鎹緙栬瘧鎴恓ava bytecode錛屾秷鑰楃殑鍐呭瓨灝戯紝璇誨彇涔熷緢蹇紝鍒╀簬嫻嬭瘯鍜岀淮鎶?
鍏充簬 鏄犲皠鏂囦歡鏄嬌鐢?hbm.xml 鏂囦歡榪樻槸浣跨敤 Annotations 鎴戜滑鏉ョ湅鐪?鑰呯殑鎬ц兘鍚? 鍏堝0鏄庝竴涓?涓漢璁や負(fù)鏄犲皠鏂囦歡涓鏃﹂厤緗ソ灝變笉浼?xì)鍦ㄥ緢澶ЫE嬪害涓婃敼鍙樹(shù)簡(jiǎn).鎵浠ヤ嬌鐢▁ml鏂囦歡騫朵笉浼?xì)甯︽潵寰堝ぇ鐨勫ソ澶?濡傛灉浣犺涓?鏄犲皠鏂囦歡鍦ㄤ綘鐨勯」鐩腑涔熺粡甯稿彉鍖?姣斿涓鍒桽tring鏁版嵁 ,浠婂ぉ浣犱嬌鐢?length="16" 鏄庡ぉ浣犺涓?璇ユ暟鎹殑闀垮害搴旇鏇撮暱鎵嶈兘婊¤凍涓氬姟闇姹?浜庢槸鏀逛負(fù)length="128" 絳夌瓑綾諱技鐨勯棶棰?. 濡傛灉浣犵粡甯告湁榪欐柟闈㈢殑鍙樺姩鐨勮瘽,涓嬮潰鐨勬瘮杈冧綘鍙互涓嶇敤鐪嬩簡(jiǎn) , 浣犲簲璇ヤ嬌鐢?xml鏂囦歡 鍥犱負(fù)Annotations 鏃犳硶寰堝ソ鐨勬弧瓚充綘鐨勮姹?
鐜板湪璁╂垜浠氨鏉ョ湅鐪?鑰呯殑鎬ц兘姣旇緝鍚?
(璇存槑: 榪欓噷鍙槸姣旇緝鏌ユ壘 鎻掑叆 鐨勬椂闂村揩鎱?娌℃湁姣旇緝闄よ繍琛屾椂闂翠互澶栫殑鍏朵粬鎬ц兘,濡?鍐呭瓨鍗犵敤閲?絳夌瓑)
鍏堟潵鐪嬬湅嫻嬭瘯紼嬪簭鍜岄厤緗?
棣栧厛鍦?Hibernate.cfg.xml 鏂囦歡涓幓鎺変簡(jiǎn)
<property name="hibernate.hbm2ddl.auto">update</property>
榪欎竴琛? 鍥犱負(fù)鍦ㄥ墠闈㈢殑瀹為獙涓互鍙?qiáng)寰忕珛浜?jiǎn)鏁版嵁搴撹〃浜?涓嶅啀闇瑕佹洿鏂頒簡(jiǎn).濡傛灉浣犳槸絎竴嬈¤繍琛岃渚嬪瓙 榪樻槸瑕佽琛岀殑.
Test.java 濡備笅:
/*
聽(tīng)*聽(tīng)Created聽(tīng)on聽(tīng)2005
聽(tīng)*聽(tīng)@author聽(tīng)
聽(tīng)*/
package聽(tīng)test.hibernate.annotation;
import聽(tīng)org.hibernate.Session;
import聽(tīng)org.hibernate.Transaction;
public聽(tīng)class聽(tīng)Test聽(tīng){
聽(tīng)聽(tīng)
聽(tīng)聽(tīng)public聽(tīng)static聽(tīng)void聽(tīng)main(String聽(tīng)[]聽(tīng)args)聽(tīng){
聽(tīng)聽(tīng)聽(tīng)聽(tīng)long聽(tīng)start聽(tīng)=聽(tīng)0;
聽(tīng)聽(tīng)聽(tīng)聽(tīng)long聽(tīng)end聽(tīng)=聽(tīng)0;
聽(tīng)聽(tīng)聽(tīng)聽(tīng)start聽(tīng)=聽(tīng)System.currentTimeMillis();聽(tīng)聽(tīng)//紼嬪簭寮濮嬫椂闂?/font>
聽(tīng)聽(tīng)聽(tīng)聽(tīng)
聽(tīng)聽(tīng)聽(tīng)聽(tīng)Session聽(tīng)s聽(tīng)=聽(tīng)HibernateUtil.currentSession();
聽(tīng)聽(tīng)聽(tīng)聽(tīng)long聽(tīng)mid聽(tīng)=聽(tīng)聽(tīng)System.currentTimeMillis();聽(tīng)聽(tīng)//鍒濆鍖栧畬姣曠殑鏃墮棿 (鍙兘姝ゆ椂騫舵病鏈夊垵濮嬪寲瀹屾瘯^_^)
聽(tīng)聽(tīng)聽(tīng)聽(tīng)
聽(tīng)聽(tīng)聽(tīng)聽(tīng)Transaction聽(tīng)tx聽(tīng)=聽(tīng)s.beginTransaction();聽(tīng)聽(tīng)聽(tīng)聽(tīng)
聽(tīng)聽(tīng)聽(tīng)聽(tīng)/********************嫻嬭瘯璇誨彇鐨勪唬鐮?***********************/
聽(tīng)聽(tīng)聽(tīng)聽(tīng)Person聽(tīng)p聽(tīng)=聽(tīng)null;
聽(tīng)聽(tīng)聽(tīng)聽(tīng)for(int聽(tīng)i聽(tīng)=聽(tīng)1;聽(tīng)i聽(tīng)<=聽(tīng)100;聽(tīng)i聽(tīng)++)聽(tīng){
聽(tīng)聽(tīng)聽(tīng)聽(tīng)p聽(tīng)=聽(tīng)(Person)聽(tīng)s.get(Person.class,聽(tīng)i);
聽(tīng)聽(tīng)聽(tīng)聽(tīng)System.out.println(p.getName());
聽(tīng)聽(tīng)聽(tīng)聽(tīng)}
聽(tīng)聽(tīng)聽(tīng)聽(tīng)System.out.println(p.getName());
聽(tīng)聽(tīng)聽(tīng) /********************嫻嬭瘯璇誨彇1嬈$殑浠g爜************************/
聽(tīng)聽(tīng)聽(tīng)聽(tīng)Person聽(tīng)p聽(tīng)=聽(tīng)null;
聽(tīng)聽(tīng)聽(tīng)聽(tīng)p聽(tīng)=聽(tīng)(Person)聽(tīng)s.get(Person.class,聽(tīng)1);
聽(tīng)聽(tīng)聽(tīng)聽(tīng)System.out.println(p.getName());
聽(tīng)聽(tīng)聽(tīng)聽(tīng)/*********************嫻嬭瘯鎻掑叆鐨勪唬鐮?************************************/
聽(tīng)聽(tīng)聽(tīng)聽(tīng)/*
聽(tīng)聽(tīng)聽(tīng)聽(tīng)for聽(tīng)(int聽(tīng)i聽(tīng)=聽(tīng)0;聽(tīng)i聽(tīng)<聽(tīng)100;聽(tīng)i聽(tīng)++)聽(tīng){
聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)Person聽(tīng)p聽(tīng)=聽(tīng)new聽(tīng)Person();
聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)p.setAge(i+1);
聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)p.setName("icerain"+i);
聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)p.setSex("male"+i);
聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)s.save(p);
聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)聽(tīng)s.flush();
聽(tīng)聽(tīng)聽(tīng)聽(tīng)}
聽(tīng)聽(tīng)聽(tīng)聽(tīng)*/
聽(tīng)聽(tīng)聽(tīng)聽(tīng)tx.commit();
聽(tīng)聽(tīng)聽(tīng)聽(tīng)HibernateUtil.closeSession();
聽(tīng)聽(tīng)聽(tīng)聽(tīng)
聽(tīng)聽(tīng)聽(tīng)聽(tīng)end聽(tīng)=聽(tīng)System.currentTimeMillis();聽(tīng)//嫻嬭瘯緇撴潫鏃墮棿
聽(tīng)聽(tīng)聽(tīng)聽(tīng)System.out.println("String[]聽(tīng)-聽(tīng)start聽(tīng)time:聽(tīng)"聽(tīng)+聽(tīng)start);
聽(tīng)聽(tīng)聽(tīng)聽(tīng)System.out.println("String[]聽(tīng)-聽(tīng)end聽(tīng)time:聽(tīng)"聽(tīng)+聽(tīng)end);
聽(tīng)聽(tīng)聽(tīng)聽(tīng)System.out.println("Init聽(tīng)time聽(tīng):聽(tīng)"聽(tīng)+聽(tīng)(mid-start)); // 鎵撳嵃鍒濆鍖栫敤鐨勬椂闂?/font>
聽(tīng)聽(tīng)聽(tīng)聽(tīng)System.out.println("Last聽(tīng)time聽(tīng)is聽(tīng):"聽(tīng)+(end聽(tīng)-聽(tīng)mid)聽(tīng)); //鎵撳嵃 鏁版嵁鎿嶄綔鐨勬椂闂?/font>
聽(tīng)聽(tīng)聽(tīng)聽(tīng)System.out.println("Total聽(tīng)time聽(tīng):聽(tīng)"聽(tīng)+(end聽(tīng)-聽(tīng)start)); //鎵撳嵃鎬繪椂闂?br />聽(tīng)聽(tīng)}
}
Annotations 鍖呬腑鐨凱erson.java 濡備笅
package聽(tīng)test.hibernate.annotation;
import聽(tīng)java.util.LinkedList;
import聽(tīng)java.util.List;
import聽(tīng)javax.persistence.AccessType;
import聽(tīng)javax.persistence.Basic;
import聽(tīng)javax.persistence.Entity;
import聽(tīng)javax.persistence.GeneratorType;
import聽(tīng)javax.persistence.Id;
import聽(tīng)javax.persistence.Table;
import聽(tīng)javax.persistence.Transient;
/**
聽(tīng)*聽(tīng)Person聽(tīng)generated聽(tīng)by聽(tīng)hbm2java
聽(tīng)*/
@SuppressWarnings("serial")
@Entity(access聽(tīng)=聽(tīng)AccessType.PROPERTY)
@Table
public聽(tīng)class聽(tīng)Person聽(tīng)implements聽(tīng)java.io.Serializable聽(tīng){
聽(tīng)聽(tīng)private聽(tīng)Integer聽(tīng)id;
聽(tīng)聽(tīng)private聽(tīng)String聽(tīng)name;
聽(tīng)聽(tīng)private聽(tīng)String聽(tīng)sex;
聽(tīng)聽(tīng)private聽(tīng)Integer聽(tīng)age;
聽(tīng)聽(tīng)private聽(tīng)List聽(tīng)list聽(tīng)=聽(tīng)new聽(tīng)LinkedList();
聽(tīng)聽(tīng)//聽(tīng)Constructors
聽(tīng)聽(tīng)/**聽(tīng)default聽(tīng)constructor聽(tīng)*/
聽(tīng)聽(tīng)public聽(tīng)Person()聽(tīng){
聽(tīng)聽(tīng)}
聽(tīng)聽(tīng)/**聽(tīng)constructor聽(tīng)with聽(tīng)id聽(tīng)*/
聽(tīng)聽(tīng)public聽(tīng)Person(Integer聽(tīng)id)聽(tīng){
聽(tīng)聽(tīng)聽(tīng)聽(tīng)this.id聽(tīng)=聽(tīng)id;
聽(tīng)聽(tīng)}
聽(tīng)聽(tīng)//聽(tīng)Property聽(tīng)accessors
聽(tīng)聽(tīng)@Id(generate=GeneratorType.AUTO)
聽(tīng)聽(tīng)public聽(tīng)Integer聽(tīng)getId()聽(tīng){
聽(tīng)聽(tīng)聽(tīng)聽(tīng)return聽(tīng)this.id;
聽(tīng)聽(tīng)}
聽(tīng)聽(tīng)public聽(tīng)void聽(tīng)setId(Integer聽(tīng)id)聽(tīng){
聽(tīng)聽(tīng)聽(tīng)聽(tīng)this.id聽(tīng)=聽(tīng)id;
聽(tīng)聽(tīng)}
聽(tīng)聽(tīng)@Basic
聽(tīng)聽(tīng)public聽(tīng)String聽(tīng)getName()聽(tīng){
聽(tīng)聽(tīng)聽(tīng)聽(tīng)return聽(tīng)this.name;
聽(tīng)聽(tīng)}
聽(tīng)聽(tīng)public聽(tīng)void聽(tīng)setName(String聽(tīng)name)聽(tīng){
聽(tīng)聽(tīng)聽(tīng)聽(tīng)this.name聽(tīng)=聽(tīng)name;
聽(tīng)聽(tīng)}
聽(tīng)聽(tīng)@Basic
聽(tīng)聽(tīng)public聽(tīng)String聽(tīng)getSex()聽(tīng){
聽(tīng)聽(tīng)聽(tīng)聽(tīng)return聽(tīng)this.sex;
聽(tīng)聽(tīng)}
聽(tīng)聽(tīng)public聽(tīng)void聽(tīng)setSex(String聽(tīng)sex)聽(tīng){
聽(tīng)聽(tīng)聽(tīng)聽(tīng)this.sex聽(tīng)=聽(tīng)sex;
聽(tīng)聽(tīng)}
聽(tīng)聽(tīng)@Basic
聽(tīng)聽(tīng)public聽(tīng)Integer聽(tīng)getAge()聽(tīng){
聽(tīng)聽(tīng)聽(tīng)聽(tīng)return聽(tīng)this.age;
聽(tīng)聽(tīng)}
聽(tīng)聽(tīng)public聽(tīng)void聽(tīng)setAge(Integer聽(tīng)age)聽(tīng){
聽(tīng)聽(tīng)聽(tīng)聽(tīng)this.age聽(tīng)=聽(tīng)age;
聽(tīng)聽(tīng)}
聽(tīng)聽(tīng)@Transient
聽(tīng)聽(tīng)public聽(tīng)List聽(tīng)getList()聽(tīng){
聽(tīng)聽(tīng)聽(tīng)聽(tīng)return聽(tīng)list;
聽(tīng)聽(tīng)}
聽(tīng)聽(tīng)public聽(tīng)void聽(tīng)setList(List聽(tīng)list)聽(tīng){
聽(tīng)聽(tīng)聽(tīng)聽(tīng)this.list聽(tīng)=聽(tīng)list;
聽(tīng)聽(tīng)}
}
鍏朵粬鐨勪唬鐮佸嚑涔庢病鏈夋敼鍙?
涓嬮潰鐨勬瘡縐嶇被鍨嬬殑嫻嬭瘯閮芥祴璇曚簡(jiǎn)3嬈′互涓? 鍙栦腑闂寸殑嫻嬭瘯鏃墮棿.
嫻嬭瘯鏈哄櫒閰嶇疆:
CPU:聽(tīng) AMD Athlon (xp) 2000+
鍐呭瓨: 784880KB
紜洏: 涓夋槦 SP0812N
璇誨彇涓嬈÷?tīng)聽(tīng)鐨勬瘮杈?(鍗曚綅: 姣)
浣跨敤Annotations 鐨勬祴璇曟暟鎹?/td> | 浣跨敤Xml鏂囦歡鐨勬祴璇曟暟鎹?/td> | 綆瑕佽鏄?/td> | ||
Init time : | 2444 | Init time : | 2431 | 嫻嬭瘯鍓嶆垜璁や負(fù)璇ラ」緇撴灉xml搴旇姣旇緝澶?瑕佽鍙栨槧灝勬枃浠跺晩,瀹為檯鎯呭喌涓嶆槸榪欐牱,涓嶇煡閬撲負(fù)浠涔? |
Last time is : | 62 | Last time is : | 85 | 鐩稿樊姣旇緝澶т笉鐭ラ亾涓轟粈涔? |
Total time : | 2506 | Total time : | 2516 | xml鏂囦歡鎬諱綋涓婃參浜?jiǎn)涓鐐?/td> |
聽(tīng)聽(tīng) 璇誨彇100嬈$殑姣旇緝:
浣跨敤Annotations 鐨勬祴璇曟暟鎹?/td> | 浣跨敤Xml鏂囦歡鐨勬祴璇曟暟鎹?/td> | 綆瑕佽鏄?/td> | ||
Init time : | 2437 | Init time : | 2422 | 鍜屽墠闈㈠垵濮嬪寲宸笉澶?/td> |
Last time is : | 438 | Last time is : | 484 | 鏈夋椂闂村樊 |
Total time : | 2875 | Total time : | 2906 | 涔熸槸xml鏂囦歡鎬諱綋涓婃參浜?jiǎn)涓鐐?/td> |
鎻掑叆100嬈$殑姣旇緝:
浣跨敤Annotations 鐨勬祴璇曟暟鎹?/td> | 浣跨敤Xml鏂囦歡鐨勬祴璇曟暟鎹?/td> | 綆瑕佽鏄?/td> | ||
Init time : | 2453 | Init time : | 2469 | 鍜屽墠闈㈠垵濮嬪寲宸笉澶?/td> |
Last time is : | 469 | Last time is : | 656 | 鏈夋椂闂村樊 |
Total time : | 2922 | Total time : | 3125 | 涔熸槸xml鏂囦歡鎬諱綋涓婃參浜?jiǎn)涓鐐?/td> |
浠庝笂闈㈢殑涓夋瀵規(guī)瘮涓ぇ瀹跺彲浠ョ湅鍒?鍒濆鍖栫殑閮ㄥ垎鍑犱箮涓よ呮槸涓鏍風(fēng)殑, 鍦ㄦ暟鎹搷浣滀笂闈?浣跨敤xml鏂囦歡 鎬繪槸姣斾嬌鐢ˋnnotations 鎱竴鐐?鍦ㄦ垜浠彧鎿嶇旱涓涓彧鏈夊嚑涓睘鎬х殑灝忔寔涔呭寲綾葷殑鎿嶄綔涓氨鏈?鍑犲崄姣鐨勫樊璺? 鍑犲崄姣鍦ㄨ綆楁満涓畻涓嶇畻寰堝ぇ 澶у搴旇閮界煡閬?鎴戝氨涓嶅湪澶氳浜?
鎬葷粨: 緇忚繃 xml 鏂囦歡 鍜孉nnotations 鐨勪紭緙虹偣鍜?鎬ц兘涓婄殑瀵規(guī)瘮.鐜板湪浣跨敤閭d釜浣滀負(fù)浣犳寔涔呭寲鏄犲皠絳栫暐.鎴戠浉淇″ぇ瀹墮兘浼?xì)姝<嫯閫夋嫨鐨?
嫻嬭瘯鍚庤: 緇忚繃澶氭嫻嬭瘯 鎰熻鏈夋椂鍊欏緢涓嶇ǔ瀹?,鏈夌殑鏃跺欏緢紼沖畾涓嶇煡閬撴槸嫻嬭瘯鏈夐棶棰樿繕鏄埆鐨勯棶棰?澶у鍙互鑷繁嫻嬭瘯涓涓? 鏈変粈涔堟柊鐨勫彂鐜?璇峰ぇ瀹惰璁鴻璁?
CREATE TABLE user (瀵逛簬榪欎釜琛ㄦ牸錛屾?zhèn)ㄦ湁涓涓猆ser綾誨埆涓庝箣瀵瑰簲錛岃〃鏍間腑鐨勬瘡涓涓瓧孌靛皢瀵瑰簲鑷砋ser瀹炰緥涓婄殑Field鎴愬憳銆?br />
id INT(11) NOT NULL auto_increment PRIMARY KEY,
name VARCHAR(100) NOT NULL default'',
age INT
);
import java.io.Serializable;
import net.sf.hibernate.HibernateException;
import net.sf.hibernate.Session;
import net.sf.hibernate.SessionFactory;
import net.sf.hibernate.Transaction;
public class HibernateSessionUtil implements Serializable
{
publicstaticfinal ThreadLocal tLocalsess = new ThreadLocal();
publicstaticfinal ThreadLocal tLocaltx = new ThreadLocal();
/*
* getting the thread-safe session for using
*/
publicstatic Session currentSession(){
Session session = (Session) tLocalsess.get();
//open a new one, if none can be found.
try{
if (session == null){
session = openSession();
tLocalsess.set(session);
}
}catch (HibernateException e){
thrownew InfrastructureException(e);
}
return session;
}
/*
* closing the thread-safe session
*/
publicstatic void closeSession(){
Session session = (Session) tLocalsess.get();
tLocalsess.set(null);
try{
if (session != null && session.isOpen()){
session.close();
}
}catch (HibernateException e){
thrownew InfrastructureException(e);
}
}
/*
* begin the transaction
*/
publicstatic void beginTransaction(){
Transaction tx = (Transaction) tLocaltx.get();
try{
if (tx == null){
tx = currentSession().beginTransaction();
tLocaltx.set(tx);
}
}catch (HibernateException e){
thrownew InfrastructureException(e);
}
}
/*
* close the transaction
*/
publicstatic void commitTransaction(){
Transaction tx = (Transaction) tLocaltx.get();
try{
if (tx != null && !tx.wasCommitted() && !tx.wasRolledBack())
tx.commit();
tLocaltx.set(null);
}catch (HibernateException e){
thrownew InfrastructureException(e);
}
}
/*
* for rollbacking
*/
publicstatic void rollbackTransaction(){
Transaction tx = (Transaction) tLocaltx.get();
try{
tLocaltx.set(null);
if (tx != null && !tx.wasCommitted() && !tx.wasRolledBack()){
tx.rollback();
}
}catch (HibernateException e){
thrownew InfrastructureException(e);
}
}
privatestatic Session openSession() throws HibernateException{
return getSessionFactory().openSession();
}
privatestatic SessionFactory getSessionFactory() throws HibernateException{
return SingletonSessionFactory.getInstance();
}
}
銆filter涓殑紼嬪紡紕煎涓?/p>
public class HibernateSessionCloser implements Filter{
protected FilterConfig filterConfig = null;
public void init(FilterConfig filterConfig)throws ServletException{
this.filterConfig = filterConfig;
}
public void destroy(){
this.filterConfig = null;
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
try{
chain.doFilter(request, response);
}
finally{
try{
HibernateSessionUtil.commitTransaction();
}catch (InfrastructureException e){
HibernateSessionUtil.rollbackTransaction();
}finally{
HibernateSessionUtil.closeSession();
}
}
}
}
鐒跺緦鍦ㄦ搷浣滆硣鏂欏韓涔嬪墠鍔犱笂
HibernateSessionUtil.beginTransaction();
HibernateSessionUtil.currentSession();//鍙栧緱Session
榪欎釜渚嬪瓙浣跨敤浜?jiǎn)HSQL鍋氭暟鎹簱錛宻pring鐨凙OP浣滀負(fù)鍩虹錛屼嬌鐢ˋcegi鍋氬畨鍏ㄦ帶鍒剁粍浠躲?br />鑱旂郴浜虹鐞嗙殑web搴旂敤鍦ㄥ惎鍔ㄦ椂鍊欙紝浼?xì)鍋氫竴緋誨垪鍒濆鍖栧姩浣滐細(xì)
1. 璇誨彇web.xml鏂囦歡錛?/p>
2. 騫惰В鏋愭枃浠墮噷鐨勫唴瀹廣?br />a) context-param鍏冪礌銆?br />i. contextConfigLocation灞炴с傝繖涓睘鎬у畾涔変簡(jiǎn)spring鎵闇瑕佺殑3涓睘鎬ф枃浠躲傚畠浠垎鍒槸錛歛pplicationContext -acegi-security.xml銆乤pplicationContext-common-business.xml銆?applicationContext-common-authorization.xml
ii. log4jConfigLocation灞炴с傝繖涓睘鎬у畾涔変簡(jiǎn)log4j閰嶇疆鏂囦歡銆?/p>
b) filter鍏冪礌銆?br />榪欓噷瀹氫箟浜?jiǎn)acegi鐨勪竴涓繃婊ゅ櫒銆侫cegi鐨勫ぇ閮ㄥ垎榪囨護(hù)鍣ㄩ兘鏄繖鏍烽厤緗殑銆備嬌鐢‵ilterToBeanProxy緇勪歡錛岀粰瀹冧紶閫掍竴涓猼argetClass灞炴с傝繖涓猼argetClass蹇呴』瀹炵幇javax.servlet.Filter鎺ュ彛銆?br />榪欓噷閰嶇疆鐨勬槸FilterChainProxy銆傝繖涓狥ilterChainProxy姣旇緝濂界敤錛屽彲浠ヤ負(fù)瀹冨畾涔変竴涓瞗ilter灞炴с傝繖浜沠ilter灝嗕細(xì)鎸夌収瀹氫箟鐨勯『搴忚璋冪敤銆備緥濡傦紝
<bean id="filterChainProxy" class="net.sf.acegisecurity.util.FilterChainProxy">
<property name="filterInvocationDefinitionSource">
<value>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/**=httpSessionContextIntegrationFilter,authenticationProcessingFilter,basicProcessingFilter,rememberMeProcessingFilter,anonymousProcessingFilter,securityEnforcementFilter
</value>
</property>
</bean>
榪欎釜榪囨護(hù)鍣ㄧ殑mapping鏄?*鈥濄?br />c) listener鍏冪礌銆?br />i. ContextLoaderListener銆傝繖涓槸Spring浣跨敤鏉ュ姞杞芥牴applicationcontext銆傚茍鍒嗗埆瑙f瀽 applicationContext-acegi-security.xml銆乤pplicationContext-common- business.xml銆乤pplicationContext-common-authorization.xml絳夐厤緗枃浠訛紝鎶婄浉鍏崇殑瀵硅薄鍒濆鍖?br />iii. Log4jConfigListener銆傝繖涓槸spring鐢ㄦ潵鍒濆鍖杔og4j緇勪歡鐨刲istener銆?br />iv. HttpSessionEventPublisher銆傝繖涓粍浠跺皢鍙戝竷HttpSessionCreatedEvent鍜孒ttpSessionDestroyedEvent浜嬩歡緇檚pring鐨刟pplicationcontext銆?br />d) servlet鍏冪礌銆?br />i. contacts銆傝繖閲岄噰鐢ㄤ簡(jiǎn)spring鐨凪VC妗嗘灦錛?鎵浠ヨ繖涓猻ervlet鏄痵pring MVC鐨勪竴涓牳蹇?jī)鎺у埗鍣ㄥQ坥rg.springframework.web.servlet.DispatcherServlet錛夈傝繖涓猻ervlet 鍚姩鏃跺欙紝浼?xì)浠巆ontacts-servlet.xml閲岄潰璇誨彇淇℃伅錛屽茍鍋氱浉鍏崇殑鍒濆鍖栥?br />v. remoting銆備篃鏄痵pring MVC鐨勪竴涓牳蹇?jī)鎺у埗鍣ㄣ備笌contacts涓嶅悓錛岃繖涓猻ervlet涓昏鏄彁渚泈eb services鏈嶅姟銆傝繖涓猻ervlet鍚姩鏃跺欙紝 浼?xì)浠巖emoting-servlet.xml閲岄潰璇誨彇淇℃伅錛屽茍鍋氱浉鍏崇殑鍒濆鍖栥?br />e) taglib鍏冪礌銆傝繖閲屽畾涔変簡(jiǎn)spring鐨勬爣f) 絳懼簱銆?br />3. 瑙f瀽applicationContext-acegi-security.xml銆?br />a) 榪囨護(hù)鍣ㄩ摼銆傚畾涔変簡(jiǎn)涓涓狥ilterChainProxy錛宐) 騫舵寚c) 瀹氫簡(jiǎn)涓緋誨垪鐨勮繃婊ゅ櫒閾俱俬ttpSessionContextIntegrationFilter, authenticationProcessingFilter,basicProcessingFilter,rememberMeProcessingFilter,anonymousProcessingFilter,securityEnforcementFilter
d) 璁よ瘉綆$悊鍣ㄣ傝繖涓鐞嗗櫒鐢盿cegi鎻愪緵銆傝繖涓鐞嗗櫒闇瑕佷竴涓猵roviders鍙傛暟銆傝繖涓猵roviders鍙傛暟鍖呭惈浜?jiǎn)鎻愪緵绯痪l熻璇佺殑瀵硅薄銆?br />i. daoAuthenticationProvider銆備竴鑸敤鎴瘋璇併?br />ii. anonymousAuthenticationProvider銆傚尶鍚嶇敤鎴瘋璇併?br />iv. rememberMeAuthenticationProvider銆傝浣忔垜璁よ瘉銆?/p>
e) 瀵嗙爜鍔犲瘑銆傝繖閲屽畾涔変簡(jiǎn)涓涓猘cegi鐨凪d5綆楁硶鍔犲瘑瀵硅薄Md5PasswordEncoder銆?br />f) 瀹氫箟浜?jiǎn)涓涓猨dbcDao瀹炵幇綾匯傝繖涓被鐢盿cegi鎻愪緵鐨刵et.sf.acegisecurity.providers.dao.jdbc.JdbcDaoImpl銆傝繖涓璞¢渶瑕佷竴涓猟ataSource鐨勫弬鏁般?br />g) 瀹氫箟daoAuthenticationProvider銆傝繖涓璞$敱acegi鎻愪緵銆傚畠鏈?涓睘鎬э細(xì)
authenticationDao銆傝繖閲屾寚鍚戝墠闈㈠畾涔夌殑jdbcDao銆?br />userCache銆傝繖閲屾寚鍚戝悗闈㈠畾涔夌殑user緙撳瓨瀵硅薄銆?br />passwordEncoder銆傝繖閲屾寚鍚戝墠闈㈠畾涔夌殑瀵嗙爜鍔犲瘑瀵硅薄銆?br />h) 鐢ㄦ埛緙撳瓨綆$悊銆?br />涓轟簡(jiǎn)緙撳瓨user錛岃繖閲屼嬌鐢╯pring鐨別hcache鏉ョ紦瀛榰ser銆傜紦瀛樻満鍒訛細(xì)
i. 瀹氫箟緙撳瓨綆$悊鍣ㄢ曗旵acheManager銆傝繖涓璞℃槸spring鐨凟hCacheManagerFactoryBean瀵硅薄
ii. 瀹氫箟user緙撳瓨瀹為檯鎵ц瀵硅薄鈥曗昒serCacheBackend銆傝繖涓璞℃槸spring鐨凟hCacheFactoryBean銆傚畠鏈変袱涓睘鎬э細(xì)
1. cacheManager銆傝繖閲屾寚鍚戝墠闈㈠畾涔夌殑緙撳瓨綆$悊鍣ㄣ?br />2. cacheName銆?br />iii. 瀹氫箟user緙撳瓨鈥曗昒serCache銆傚畠鏄痑cegi鎻愪緵鐨凟hCacheBasedUserCache瀵硅薄銆傚畠鏈変竴涓睘鎬э細(xì)
1. cache銆傝繖閲屾寚鍚戠殑鏄墠闈㈠畾涔夌殑userCacheBackend銆?/p>
i) 瀹氫箟鎺ユ敹鏉ヨ嚜DaoAuthenticationProvider鐨勮璇佷簨浠剁殑listener鈥曗昄oggerListener銆?br />j)
4. 瑙f瀽applicationContext-common-business.xml銆?br />a) dataSource.
榪欓噷浣跨敤浜?jiǎn)spring鐨凞riverManagerDataSource瀵硅薄銆傝繖涓璞℃槸涓涓狫DBC鏁版嵁婧愮殑瀹氫箟銆?br />b) TransactionManager銆傝繖閲屼嬌鐢╯pring鐨凞ataSourceTransactionManager瀵硅薄銆?br />c) 浜嬪姟鎷︽埅鍣ㄣ傝繖閲屼嬌鐢╯pring鐨勪簨鍔℃嫤鎴櫒TransactionInterceptor銆傚畠鏈?涓睘鎬э細(xì)
transactionManager銆傝繖涓睘鎬ф寚鍚戝墠闈㈠畾涔夌殑TransactionManager銆?br />transactionAttributeSource銆傝繖涓睘鎬ч噷錛?鎸囧畾浜?jiǎn)ContactManager鐨勫悇涓柟娉曠殑浜嬪姟鏂歸潰鐨勮姹傘?br />d) DataSourcePopulator銆?br />浣跨敤sample.contact.DataSourcePopulator瀵硅薄錛屽線HSQL閲屽垱寤虹浉鍏崇殑琛ㄧ粨鏋勫拰鏁版嵁銆?br />瀹炵幇鍘熺悊錛欴ataSourcePopulator 瀹炵幇浜?jiǎn)鎺ュ?InitializingBean銆傚叾涓璦fterPropertiesSet鏂規(guī)硶灝嗗湪spring鍒濆鍖朌ataSourcePopulator鍚庤璋冪敤銆?br />e) ContactDao銆傝繖閲屾寚鍚戜竴涓狢ontactDaoSpring瀵硅薄銆傚畠緇ф壙spring鐨?JdbcDaoSupport錛実) 騫跺疄鐜癈ontactDao鎺ュ彛銆傚畠鏄湡姝e疄鐜癑DBC鎿嶄綔鐨勫璞°?br />h) ContactManager銆傝繖閲屼嬌鐢ㄧ殑鏄痵pring鐨凱roxyFactoryBean銆傚畠鏈?涓睘鎬э細(xì)
i. ProxyInterfaces銆備唬鐞嗘帴鍙o細(xì)sample.contact.ContactManager
ii. InterceptorNames銆傛嫤鎴櫒鍚嶇О銆傚彲浠ユ湁澶氫釜錛宨v. 榪欓噷鍖呮嫭錛歵ransactionInterceptor銆乧ontactManagerSecurity銆乧ontactManagerTarget銆傚叾涓紝v. transactionInterceptor鏄墠闈㈠畾涔夌殑浜嬪姟鎷︽埅鍣ㄣ侰ontactManagerSecurity鍒欐槸鍦?applicationContext-common-authorization.xml閲屽畾涔夌殑鏂規(guī)硶璋冪敤鎺堟潈銆?br />i) ContactManagerTarget銆傝繖閲屾寚鍚戠殑鏄痵ample.contact.ContactManagerBackend瀵硅薄銆?ContactManagerBackend瀹炵幇浜?jiǎn)ContactManager鎺ュ彛鍜孖nitializingBean鎺ュ彛銆傚畠鏈?涓嚜瀹氫箟灞炴э細(xì) contactDao鍜宐asicAclExtendedDao銆傝繖閲屼細(xì)璋冪敤ACL鐨凙PI鍘誨仛浜涘垱寤烘潈闄愬拰鍒犻櫎鏉冮檺鐨勫伐浣溿?/p>
Acegi瀹夊叏鎺у埗鑳藉姏:
ContactManager
鍖呭惈涓浜涘彈淇濇姢鐨勫拰鍏紑鐨勬柟娉曘?/span>
/secure
URI
Acegi
ROLE_USER
.
1.1.
id
Name
Email
1
John Smith
john@somewhere.com
2
Michael Citizen
michael@xyz.com
3
Joe Bloggs
joe@demo.com
4
Karen Sutherland
karen@sutherland.com
2.2.
3.3.
Del
4.4.
Admin Permission
sample.contact.Contact@26807f: Id: 1; Name: John Smith; Email: john@somewhere.com
3
絎竴鍒楄〃紺烘潈闄愶紝渚嬪錛屸?/span>
Del
5.5.
Contact:
sample.contact.Contact@1787005: Id: 1; Name: John Smith; Email: john@somewhere.com
Recipient:
Permission:
-R--- [2] dianne
-RW-D [22] peter
A---- [1] marissa
-RW-D
絎簩鍒椾篃琛ㄧず鏉冮檺錛屼絾瀹冩槸浠ョ被浼?/span>
unix
[22]
,
絎笁鍒楁槸鐢ㄦ埛鍚嶇О銆?/span>
scott
John
scott
John
]]>