struts 1 - validator

Published on: 2009.07.01 16:57 by krespo


struts1 에서 validator를 수행하는 방법은 두가지가 있다.
① 직접 validator logic을 수행하여 validate하는 방법
② validator plug-in을 통한 방법

1. 직접 validator logic을 수행하여 validate하는 방법


- 클라이언트로 들어온 요청은 ActionServlet으로 들어간다.

- ActionServlet은 config 파일에 있는 <action>을 실행하고 action property중에 validate= true 이면 Request processor에게 ActionForm이 validate() method를 가지고있으니 validate()를 실행해라라는 것을 알려준다.

- Request Processor를 거쳐 들어온 데이터는 ActionForm으로 가고 validate()메소드에서 각각의 validate logic을 수행하고 만약 validate에 문제가 있으면 ActionError에 메시지를 누적 시킨다. ActionForm에서 로직을 수행한 결과는 Request Processor에게 전달된다.

- Request Processor는 전달받은 결과중 ActionError에 에러 메시지가 들어있는지를 확인하고 없으면 Action으로 들어가 비지니스로직을 수행하고 에러메시지가 있다면 바로 Client로 돌려 보낸다.




1) MessageResource.properties파일을 만든다.
----------------------------------------------------------------------------------------
#validator message resource

name.error={0} 이름을 입력하세요!!!
age.error={0} 유효하지 않는 나이입니다.
email.error={0} 메일형식에 맞지 않습니다.
----------------------------------------------------------------------------------------
{0} 는 Action class에서 파라미터로 넘겨준 사용자 정의의 스트링으로 맵핑 시켜준다.
예를 들어 ValidatorFormBean class에서

error.add("age",new ActionMessage("age.error","나이 오류!"));

다음과 같은 파라미터로 넘겨오는 경우 나이오류라는 전달 인자가 age.error={0} 에 맵핑되어 에러메시지는
나이오류! 유요하지 않은 나이입니다.

이라는 에러 메시지를 출력하게 된다. 만약 properties 파일에서
age.error = {0} 유효하지 않은 나이 입니다. {1}
이렇게 선언 되어 있고
error.add("age",new ActionMessage("age.error","나이 오류!","나이를정확히 입력해 주세요"));
이렇게 전달인자를 넘겨 준다면 에러메시지 출력 결과는

나이 오류!
유효하지 않은 나이입니다. 나이를 정확히 입력해 주세요

와 같이 에러가 출력된다.

2) FormBean을 설정한다.
          - ActionForm Class를 상속한 class를 생성한다.
          - ActionForm Class 의 validate() 메소드를 override 한다.
          - 각각의 validate logic을 완성한다.
          - validate() method 안의 logic을 완성하고 error가 있을경우 ActionError 인스턴스에 에러 메시지를 add해준다.

----------------------------------------------------------------------------------------
package com.myhome.validator;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;

/**
 *  user login을 통한 validator 구현
 *  ActionForm class에서 validate()를 통해 구현
 *
 */

@SuppressWarnings("serial")
public class ValidatorFormBean extends ActionForm{
 /* form property fields  */
 private int    age;
 private String name;
 private String email;
 
 /*ActionForm class의 validate()를 overriding한다*/
 
 @Override
 public ActionErrors validate(ActionMapping mapping,
   HttpServletRequest request) {
  ActionErrors error = new ActionErrors();
  if(!isNameValid()){
   error.add("name",new ActionMessage("name.error","이름 오류!!"));
  }
  if(!isAgeValid()){
   error.add("age",new ActionMessage("age.error","나이 오류!"));
  }
  if(!isEmailValid()){
   error.add("email",new ActionMessage("email.error","이메일 오류!"));
  }
  return error;
 }
 
 /*validator logics*/
 //이름은 반드시 두자이상 입력을 요구한다.
 protected boolean isNameValid(){
  if(this.getName() == null) return false;
  else if(this.getName().length() < 2) return false;
  return true;
 }
 
 //나이는 20세부터 80세 까지만 허용한다.
 protected boolean isAgeValid(){
  if(this.getAge() < 20 || this.getAge() > 80)
   return false;
  return true;
 }
 
 //이메일 형식이 정확한 지 검사한다.
 protected boolean isEmailValid(){
  int delim = this.getEmail().indexOf('@');
  if(delim < 0)
   return false;
  if(this.getEmail().substring(0,delim).length() < 2)
   return false;
  if(this.getEmail().substring(delim).length() < 2)
   return false;
  return true;
 }
 
 public int getAge() {
  return age;
 }
 public void setAge(int age) {
  this.age = age;
 }
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public String getEmail() {
  return email;
 }
 public void setEmail(String email) {
  this.email = email;
 }
 
 
}

----------------------------------------------------------------------------------------
주황색 부분이 가장 중요한 부분으로 ActionErrors 인스턴스인 error에 add메소드로 validate가 유효하지 않을때 message를 저장하게 된다.
error.add("name",new ActionMessage("name.error","이름 오류!!"));
이부분에서 앞의 name은 그냥 string형이름으로 정하고 name.error 는 앞에 properties파일에 설정된 key를 불러 들여오고 두번째 전달인자인 "이름오류" properties파일의 name.error ={0} 과 대응되어 결국 두메시지가 합쳐진 형태로 에러 메시지를 출력한다.

3)validate DTO를 생성한다. 일반적인 DTO와 다르지 않다.

4) struts-validatorModule.xml 파일을 생성하고 action과 message-resource, form-bean 영역을 설정한다.
----------------------------------------------------------------------------------------
<form-beans>
          <form-bean name="validatorBean" 
                            type="com.myhome.validator.ValidatorFormBean"/>
</form-beans>

<action-mappings>
   <action path="/register"
          name="validatorBean"
          scope="request"
          validate="true"
          input="/register.jsp"
          type="com.myhome.validator.ValidatorRegisterAction">
         <forward name="success" path="/result.jsp"/>
        </action>   
   </action-mappings>

<message-resources parameter="com.myhome.validator.ValidatorMessageResource"/>
----------------------------------------------------------------------------------------
여기서 가장 중요한 부분은 action mapping부분의 validate="true" 이다. 이부분을 true로 놓아야 action Servlet이 request processor에게 actionForm의 validate() 메소드를 실행 시켜야 된다 라는 것을 알려주기 때문이다.


5). web.xml에 struts-validatorModule.xml을 등록한다.
<init-param>
   <param-name>config/validatorModule</param-name>
   <param-value>/WEB-INF/config/struts-validatorModule.xml</param-value>
  </init-param>

6)jsp 페이지 에서 struts 태그를 사용하여 ErrorMessage를 출력한다.

<%@ taglib prefix="html" uri="http://struts.apache.org/tags-html"%>
<%@ taglib prefix="bean" uri="http://struts.apache.org/tags-bean"%>
<%@ taglib prefix="logic" uri="http://struts.apache.org/tags-logic"%>

<logic:messagesPresent> <!-- message stack에 에러메시지가 있으면 다음을 실행한다. -->
    <tr height=30 bgcolor="#ffffff">
      <td align="left" colspan="2">
        <html:messages name="error"> <!-- 메시지 id는 임의로 정의하고 -->
         <span style="font-size:10pt; color:red">
          <li><bean:write name="error"/></li> <!-- 메시지 이름이 ERROR인 애를 출력한다. -->
           </span>
         </html:messages>
      </td>
    </tr>
</logic:messagesPresent>

※struts-validatorModule.xml에 설정한 form-bean 이름으로 jsp페이지 까지 넘어 오기 때문에 <form>테그 안의 데이터 들을 그대로 남겨 두려면 EL 테그를 쓰면 된다.
예)
<input type="text" name="email" size=35 value="${validatorBean.email}">
이렇게 하면 데이터를 입력하고 서브밋을 눌러 ActionForm에 갔다가 다시 jsp페이지로 오면 사용자가 입력한 데이터가 다음의 bean에 입력되어 있기때문에 그대로 데이터를 살려 둘 수 있다.


2. validator plug-in을 통한 방법

validator plug-in방식으로 하려면 라이브러리 파일이 필요하지만 struts-core 라이브러리에 있기 때문에 특별히 라이브러리를 추가할 필요가 없다.

작업순서

1)validator Formbean 생성
VaidatorForm class를 상속받은 Formbean class를 작성한다.
----------------------------------------------------------------------------------------
package com.myhome.validator;

import org.apache.struts.validator.ValidatorForm;


@SuppressWarnings("serial")
public class ValidatorPropertyBean extends ValidatorForm implements java.io.Serializable{

 /*Form property fields*/
 private String name;
 private int    age;
 private String email;
 
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public int getAge() {
  return age;
 }
 public void setAge(int age) {
  this.age = age;
 }
 public String getEmail() {
  return email;
 }
 public void setEmail(String email) {
  this.email = email;
 }
 
 
}
----------------------------------------------------------------------------------------

2)struts-validatorModule(사용할 xml파일).xml 에 validator plug-in 설정을 한다.

<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
         <set-property
              property="pathnames"
              value="/org/apache/struts/validator/validator-rules.xml,
                     /WEB-INF/validation.xml"/><!-- 뒤에 xml은 우리가 만든 validation xml 파일 -->
     </plug-in>

3)struts-validatorModule(사용할 xml파일).xml 에 form-bean설정을 한다.
<form-bean name="propertyBean"
          type="com.myhome.validator.ValidatorPropertyBean"> <!-- validation.xml(사용자가 validate할 옵션을 정해준 xml 파일)에서 사용한 bean 이름과 같아야 한다. -->
      <!-- validatorForm을 상속받은 bean의 property와 똑같이 설정한다 -->
      <form-property name="name"
            type="java.lang.String"/>
      <form-property name="age"
            type="java.lang.Integer"/>
      <form-property name="email"
            type="java.lang.String"/>
     </form-bean> 

4)validation.xml(validation할 설정이 들어있는 xml) 생성

required – 폼 데이터가 입력되지 않을 때 검증한다.
minlength – 폼 데이터의 최소길이를 설정하여 검증한다.
maxlength – 폼 데이터의 최대길이를 설정하여 검증한다.
mask – 필요한 문자만 입력되었는 지 검증한다.
intRange – 폼데이터에서 정수의 범위를 설정하여 검증한다.
email – 이메일 형식에 맞게 입력되었는 지 검증한다.

http://struts.apache.org/1.3.8/faqs/validator.html 가면 더 확인 할 수 있다.

----------------------------------------------------------------------------------------
<?xml version="1.0" encoding="euc-kr" ?>
<!DOCTYPE form-validation PUBLIC
     "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.3.0//EN"
     "http://jakarta.apache.org/commons/dtds/validator_1_3_0.dtd">

<form-validation>
  <formset>
 <form name="propertyBean">  <!-- struts-validatorModule에서 form-bean 이름과 같아야 함 -->
     <field property="name" depends="required,minlength,mask">   <!--property : form-bean에 설정되어 있는 property, depends: 미리 설정되어 있는 옵션들을 석어 준다 -->
        <arg key="propertyBean.name"/>    <!-- form-bean 이름이 propertyBean인곳의 property중 name을 가지고 아래의 validation을 처리하겠다. -->
        <arg name="minlength" key="${var:minlength}" resource="false" position="0"/> 
     <arg name="mask" key="${var:mask}" resource="false" position="1"/>
<!--
      name: 윗쪽에 기술된 미리 작성된 validation을 하기 위한 정의된 것을 가져와서 쓴다
      key: 아래의 <var>태그에 선언된 value를 가져와서 validation에서 사용한다.
      position: 먼저 validation 되는 순서를 정한다. 아래의 경우 글자 수가 2개 이상이 아니거나 한글이 들어오지 않을 경우 체크하는것으로서
                   .properties 설정된 것이 로딩되어 경고 메시지를 출력한다.
-->         
           <var>
              <var-name>minlength</var-name>
              <var-value>2</var-value>
           </var>
           <var>
              <var-name>mask</var-name>
              <var-value>^[&#44032;-&#55203;]*$</var-value> <!-- 한글 외에 다른것을 다 걸러준다 -->
           </var>
     </field>
    
     <field property="age" depends="required,integer,intRange">
        <arg key="propertyBean.age" position="0" />
        <arg name="intRange" key="${var:min}" position="1" resource="false"/>
        <arg name="intRange" key="${var:max}" position="2" resource="false"/>
        <var>
         <var-name>min</var-name>
         <var-value>20</var-value>
        </var>
        <var>
         <var-name>max</var-name>
         <var-value>80</var-value>
       </var>
        </field>

     <field property="email" depends="required,email">
          <arg key="propertyBean.email"/>
     </field>
 </form>
  </formset> 
</form-validation>
----------------------------------------------------------------------------------------
5) struts-validatorModule.xml 에 action-mapping을 선언한다.
<action path="/register"
          name="propertyBean"
          scope="request"
          validate="true"
          input="/register.jsp"
          type="com.myhome.validator.ValidatorRegisterAction">
         <forward name="success" path="/result.jsp"/>
        </action> 
validate는 반드시 true로 설정해 주어야 한다.

6) properties 파일 생성과 선언

errors.required=필수 입력항목입니다.
errors.minlength=최소 2자이상 입력해야합니다.
errors.email=메일형식이 맞지 않습니다.
errors.invalid=사용할 수 없는 문자가 입력되었습니다.
errors.range=등록할 수 없는 나이입니다.
----------------------------------------------------------------------------
앞의 errors는 임의로 아무거나 설정할 수 있으나 뒤의 string은 validator plug-in에 있는것으로만 설정해야 한다.
다음을 입력하고 properties 파일로 저장한다. 그리고 struts-validatorModule.xml에 message-resource를 등록한다.

<message-resources parameter="com.myhome.validator.ValidatorMessageResource"/>

7)jsp 페이지 설정
<logic:messagesPresent> <!-- message stack에 에러메시지가 있으면 다음을 실행한다. -->
    <tr height=30 bgcolor="#ffffff">
      <td align="left" colspan="2">
        <html:messages name="error"> <!-- 메시지 id는 임의로 정의하고 -->
         <span style="font-size:10pt; color:red">
          <li><bean:write name="error"/></li> <!-- 메시지 이름이 ERROR인 애를 출력한다. -->
           </span>
         </html:messages>
      </td>
    </tr>
</logic:messagesPresent>
Name
Password
Homepage
Secret