====== Commons Validator에 validation rule 추가하기 ======
===== 개요 =====
Commons Validator는 primitive type, 필수값, 이메일등 흔히 사용되는 유형에 대한 validation rule을 template으로 제공하지만, \\
프로젝트의 특성에 따라 공통으로 사용되는 validation rule이 발생되고 이를 추가해야할 필요가 생길 수 있다. \\
공공프로젝트에서 흔히 사용되는 주민등록번호 validator를 추가해 봄으로써, validation rule을 추가하는 방법을 알아보고자 한다. \\
예제는 easycompany를 이용했다. \\ \\
===== 설명 =====
Spring Module을 이용해서 Commons Validator를 사용한다면 아래와 같은 내용을 validation rule 정의 파일(validator-rules.xml 같은)에서 보았을 것이다. \\
validator 태그의 각각의 attribute는 다음과 같은 의미를 같는다.
^ name | validation rule(required,mask,integer,email...) |
^ classname | validation check를 수행하는 클래스명 |
^ method | validation check를 수행하는 클래스의 메소드명 |
^ methodParams | validation check를 수행하는 클래스의 메소드의 파라미터 |
^ msg | 에러 메시지 key |
^ javascript | client-side validation을 위한 자바스크립트 코드 |
주민등록번호 rule을 아래와 같이 추가한다고 하면,
필요한 작업은 아래와 같다. \\
- [[#FieldCheck class 작성|FieldCheck class(RteFieldChecks) 작성]]
- [[#Validator class 작성|Validator class(RteGenericValidator) 작성]]
- [[#validator-rules.xml 설정|validator-rules.xml 설정]]
- [[#validator.xml 설정|validator.xml 설정]]
- [[#에러메시지 설정|에러메시지 설정]]
- [[#TEST|TEST]]
==== FieldCheck class 작성 ====
org.springmodules.validation.commons.FieldChecks를 상속 받는 RteFieldChecks 클래스를 생성한다. \\
그리고 주민등록번호 validation을 담당할 validateIhIdNum 메소드를 추가한다. \\
주민등록번호 validation 로직이 RteFieldChecks.validateIhIdNum() 안에 있어도 되지만, org.springmodules.validation.commons.FieldChecks와 같은 방식으로 다른 Validator에 위임했다.
package egovframework.rte.ptl.mvc.validation;
import org.apache.commons.validator.Field;
import org.apache.commons.validator.ValidatorAction;
import org.springframework.validation.Errors;
import org.springmodules.validation.commons.FieldChecks;
public class RteFieldChecks extends FieldChecks{
public static boolean validateIhIdNum(Object bean, ValidatorAction va,
Field field, Errors errors){
//bean에서 해당 field 값을 추출
String ihidnum = FieldChecks.extractValue(bean, field);
//주민등록번호 유효성 검사 알고리즘은 RteGenericValidator가 가지고 있다.
if(!RteGenericValidator.isValidIdIhNum(ihidnum)){ //유효한 주민등록번호가 아니면
FieldChecks.rejectValue(errors, field, va); //에러 처리
return false;
}else{
return true;
}
}
}
==== Validator class 작성 ====
주민등록번호 유효성체크 로직이 있는 RteGenericValidator 클래스를 작성해 보자. \\
유효성 체크 기준은
- 값의 길이가 13자리이며, 7번째 자리가 1,2,3,4 중에 하나인가?
- 앞 6자리의 값이 유효한 날짜인가?
- 주민등록번호 마지막 자리를 이용한 check
로 했다.
package egovframework.rte.ptl.mvc.validation;
import java.io.Serializable;
import org.apache.commons.validator.GenericTypeValidator;
public class RteGenericValidator implements Serializable {
public static boolean isValidIdIhNum(String value) {
//값의 길이가 13자리이며, 7번째 자리가 1,2,3,4 중에 하나인지 check.
String regex = "\\d{6}[1234]\\d{6}";
if (!value.matches(regex)) {
return false;
}
//앞 6자리의 값이 유효한 날짜인지 check.
try {
String strDate = value.substring(0, 6);
strDate = ((value.charAt(6) == '1' || value.charAt(6) == '2') ? "19":"20") + strDate;
strDate = strDate.substring(0, 4) + "/" + strDate.substring(4, 6)
+ "/" + strDate.substring(6, 8);
SimpleDateFormat dateformat = new SimpleDateFormat("yyyy/MM/dd");
Date date = dateformat.parse(strDate);
String resultStr = dateformat.format(date);
if (!resultStr.equalsIgnoreCase(strDate)) {
return false;
}
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}
//주민등록번호 마지막 자리를 이용한 check.
char[] charArray = value.toCharArray();
long sum = 0;
int[] arrDivide = new int[] { 2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5 };
for (int i = 0; i < charArray.length - 1; i++) {
sum += Integer.parseInt(String.valueOf(charArray[i]))
* arrDivide[i];
}
int checkdigit = (int) ((int) (11 - sum % 11)) % 10;
return (checkdigit == Integer.parseInt(String.valueOf(charArray[12]))) ? true
: false;
}
}
==== validator-rules.xml 설정 ====
이제 주민등록번호 validation rule을 추가해 보자. \\
rule 이름은 ihidnum으로 하고 위에서 작성한 코드를 바탕으로 설정하면, (이미 위 개요에 나온 대로) 아래와 같다. \\
client-validation을 위해서 자바스크립트 코드도 추가했다. \\
0) {
alert(fields.join('\n'));
}
return bValid;
}
/**
* Reference: JS Guide
* http://jsguide.net/ver2/articles/frame.php?artnum=002
*/
function checkIhIdNum(ihidnum){
fmt = /^\d{6}[1234]\d{6}$/;
if(!fmt.test(ihidnum)){
return false;
}
birthYear = (ihidnum.charAt(7) <= "2") ? "19" : "20";
birthYear += ihidnum.substr(0, 2);
birthMonth = ihidnum.substr(2, 2) - 1;
birthDate = ihidnum.substr(4, 2);
birth = new Date(birthYear, birthMonth, birthDate);
if( birth.getYear() % 100 != ihidnum.substr(0, 2) ||
birth.getMonth() != birthMonth ||
birth.getDate() != birthDate) {
return false;
}
var arrDivide = [2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5];
var checkdigit = 0;
for(var i=0;i
==== validator.xml 설정 ====
ihidnum이란 필드에 주민등록번호 validation 체크를 해보자. \\
validator.xml에 필요한 내용을 추가하고. \\
==== 에러메시지 설정 ====
messages 프로퍼티에 에러메시지를 추가하자.
errors.ihidnum=유효하지 않은 주민등록번호입니다.
==== TEST ====
주민등록번호 server-side,client-side validatin을 위한 환경은 다 갖추어졌다. \\
이제 EmployeeController에 validation을 추가하고,(이미 추가되어 있다면 pass) \\
package com.easycompany.controller.annotation;
...
import org.springmodules.validation.commons.DefaultBeanValidator;
...
@Controller
public class EmployeeController {
...
@Autowired
private DefaultBeanValidator beanValidator;
...
@RequestMapping(value = "/updateEmployee.do", method = RequestMethod.POST)
public String updateEmployee(@ModelAttribute("employee") Employee employee,
BindingResult bindingResult, Model model) {
beanValidator.validate(employee, bindingResult); //validation 수행
if (bindingResult.hasErrors()) { //만일 validation 에러가 있으면...
.....
return "modifyemployee";
}
employeeManageService.updateEmployee(employee);
return "changenotify";
}
}
VO Class(com.easycompany.model.Employee.java)에 주민등록번호 필드를 추가하고,
package com.easycompany.model;
public class Employee {
....
private String ihidnum;
private String ihidnum1;
private String ihidnum2;
...
public String getIhidnum() {
return ihidnum1+ihidnum2;
}
public String getIhidnum1() {
return ihidnum1;
}
public void setIhidnum1(String ihidnum1) {
this.ihidnum1 = ihidnum1;
}
public String getIhidnum2() {
return ihidnum2;
}
public void setIhidnum2(String ihidnum2) {
this.ihidnum2 = ihidnum2;
}
}
JSP(/easycompany/webapp/jsp/modifyemployee.jsp)에 주민등록번호 입력 필드를 추가하자.
...
주민번호 |
-
|
...
주민등록번호를 입력하지 않거나, 틀린번호를 입력시엔 아래와 같은 경고창이 뜬다. \\
{{:egovframework:rte:ptl:validation:ihidnum-validation.jpg|}} \\
틀린 입력값으로 client를 통과하더라도 Controller에서 validation이 추가로 동작하므로, server-side에서 validation error가 일어날것이다.
====== 참고자료 ======
* Spring Modules Reference Documentation v 0.9, Chapter 17.Validation, P133~136