2013年5月19日 星期日

身份證字號驗證的 Annotation 寫法

文章來源 : http://www.javaworld.com.tw/jute/post/view?bid=35&id=245715&sty=1&tpg=1&age=0

需要在WEB驗證身份證字號的話,可以試試看用下列的程式喔!
如果我也寫錯的地方也請不吝指教,謝謝。

PersonId.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
import org.hibernate.validator.ValidatorClass;
 
/**
 * 身份證字號
 * @author pogi
 * @BuildTime 2008/11/27 下午 1:51:08
 */
@Documented //可以在 JavaDoc 顯示
@Target({ElementType.FIELD, ElementType.METHOD}) //可以用在類別的屬性或方法上
@Retention(RetentionPolicy.RUNTIME) //runtime 期間都會一直保留其值
@ValidatorClass(PersonIdValidator.class) //驗證時要呼叫的類別
public @interface PersonId{
  String message() default "請輸入正確的身份證字號";
}


PersonIdValidator.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import java.io.Serializable;
import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
import org.hibernate.validator.Validator;
 
/**
 * 中華民國身份證字號驗證
 * @author pogi
 * @BuildTime 2008/11/27 下午 1:58:20
 */
public class PersonIdValidator implements Validator<PersonId>, Serializable{
  private static final long serialVersionUID = 1;
  private Pattern pattern;
  private static final char[] FIRSTWORD = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
  private static final int[] FIRSTWORDNUMBER = {1,10,19,28,37,46,55,64,39,73,82,2,11,20,48,29,38,47,56,65,74,83,21,3,12,30};
 
  /* (non-Javadoc)
   * @see org.hibernate.validator.Validator#isValid(java.lang.Object)
   */
  public boolean isValid(Object arg0){
    if(arg0 == null) return true;
    if(!(arg0 instanceof String)) return false;
    String personId = ((String)arg0).toUpperCase();
    if(personId.length() == 0) return true;
    Matcher matcher = pattern.matcher(personId);
    if(matcher.matches()){
      int verifyNumber = 0;
      //英文字母的轉碼數字
      verifyNumber = FIRSTWORDNUMBER[Arrays.binarySearch(FIRSTWORD, personId.charAt(0))];
      //身份證字號第1~8個數字依次取出乘以8~1
      for(int i = 0; i < 8; i++){
        verifyNumber += Character.digit(personId.charAt(i + 1), 10) * (8 - i); 
      }
      //10 - 上述總和除10之餘數
      verifyNumber = 10 - (verifyNumber % 10);
      //若驗證碼與身份證字號最後一個數字相同即為正確
      if(verifyNumber == Character.digit(personId.charAt(9), 10) || verifyNumber == 10){
        return true;
      }
    }
    return false;
  }
 
  public void initialize(PersonId arg0){
    pattern = Pattern.compile("^\\p{Upper}{1}\\d{9}", Pattern.CASE_INSENSITIVE);
  }
}


上面兩個程式可以放在相同 package,這樣比較好管理

使用範例如下(JavaEE)
Person.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@Entity
public class Person inplements Serializable{
  private int id;
  private String personId;
 
  @Id
  @GeneratedValue
  public int getId(){
    return this.id;
  }
  public void setId(int id){
    this.id = id;
  }
 
  @NotNull
  @PersonId(message="你偷渡喔!!")
  public String getPersonId(){
    return this.personId;
  }
  public void setPersonId(String personId){
    this.personId = personId;
  }
}

沒有留言:

張貼留言