본문 바로가기

Programing/Struts

ActionServlet과 ActionForm을 알아보자!

Struts ActionServlet javax.servlet.http.HttpServlet 클래스를 상속 받았으며

HTTP 요청을 스트럿츠의 특정  Action요소(적절한 핸들러)에게 보내는 역할을 수행 한다.


 

1) ActionServlet

스트럿츠에서 클라이언트의 요청을 처리하는 초기 진입은 ActionServlet이 담당하고 있다.

모델2에서는 UserServlet이나 또 다른 서블릿을 필요할 때마다 새로 작성할 필요가 있지만

스트럿츠에서는 ActionServlet 하나만을 이용하여 모든 요청을 처리하는 하는 것이 가능 한 것이다.

Struts1.1
이전 버전에서는 ActionServlet이 요청을 받아 핸들러를 호출하는 유일한 클래스 였지만 1.1 버전 이후 부터는

 ora.apache.struts.action.RequestProcessor라는 클래스가 추가되어 클라이언트의 요청을 처리 할 수 있게 되었다.

ActionServlet
은 클라이언트의 요청을 받게 되면 URI를 사용하여 어떤 Action이 주어진 요청을 처리할 것인지를 결정 하는데

 이때 struts-config.xml 파일에 설정된 Action 태그들을 검색 한다. (URI Action 설정의 path 속성과 일치해야 한다.)

아래 struts-config.xml 파일의 내용을 참고 해 보자
!

<action

     path="/send"

     type="form.FormAction"

     name="f1"

     validate="true"

     input="/inData.jsp" />

만약 특정 웹 페이지에서 HTML <form> tag action="send.st" 라고 한 후 submit 버튼을 누르게 되면 톰캣은

struts-config.xml action path와 일치함을 알고 form.FormAction 클래스를 실행시킴으로써

Action을 처리하게 되는 것이다.

ActionServlet
은 주어진 입력 값(파라미터) 들을 한꺼번에 자바 빈즈로 묶을 수 있는데 이 자바 빈은

스트럿츠 ActionForm 클래스의 서브클래스로 구성 된다.

이를 폼빈(FormBean) 이라고 하며 struts-config.xml 파일에서 <form-bean> 이라는 태그에서 설정을 하게 된다.

아래는 struts-config.xmml 파일에서 설정 예문이다
.
<form-beans>

        <form-bean name="f1" type="form.FormData">                  

            <form-property name="name" type="java.lang.String" />

            <form-property name="id" type="java.lang.String" />

                 <form-property name="pwd" type="java.lang.String" />

        </form-bean>            

</form-beans>

이때
<action> 태그의 name <form-bean> name이 일치함을 잊지말자
.

다른 자바 서블릿과 마찬가지로 Struts ActionServlet 역시 웹 애플리케이션의 배치 스크립트(web.xml)를 반드시

기억해야 한다.


 

2) ActionForm

ActionForm 객체는 클라이언트에서 입력한 데이터를 비즈니스 계층으로 전달하는 역할을 한다. Struts Framework에서는

사용자의 입력 화면에서 입력한 데이터를 자동으로 모아 ActionForm 인스턴스의 setter를 이용해 설정하며 이를 통해

비즈니스 계층으로 데이터를 전달 할 수 있다.

그럼 ActionForm객체인 클래스를 다음과 같이 작성해 보자!

 

package form;

import! org.apache.struts.action.*;

import! javax.servlet.http.*;

public class FormData extends ActionForm{

           private String name, id, pwd;

 

           public String getName(){

                     return name;

           }

           public String getId(){

                     return id;

           }

           public String getPwd(){

                     return pwd;

           }

////////////////////////////////////////////////////////////////////////////////////////

           public void setName(String n){

                     name = n;

           }

           public void setId(String n){

                     id = n;

           }

           public void setPwd(String n){

                     pwd = n;

           }

////////////////////////////////////////////////////////////////////////////////////////

           public void reset(ActionMapping mapping,

                                          HttpServletRequest request) {

                     name = "";

                     pwd = "";

                     id = "";

           }

           public ActionErrors validate(ActionMapping mapping,

                                          HttpServletRequest request) {

                     ActionErrors err = null;

                               

                     if((name == null) || (name.length()<1) ||

                                          (id == null) || (id.length()<1) ||

                                          (pwd == null) || (pwd.length()<1)) {

                                err = new ActionErrors();

                                err.add("ERROR!!", new ActionMessage("Error.required"));

                     }

                     return err;                       

           }

}

 


다음은 위의 ActionForm객체를 받아 실제 모든 비즈니스적인 일들을 처리하는 Action객체를 작성해 보자!

package form;

import! org.apache.struts.action.*;

import! javax.servlet.http.*;

public class FormAction extends Action {

        

         public ActionForward execute(ActionMapping mapping,

               ActionForm form,

               HttpServletRequest req,

               HttpServletResponse response) throws Exception{

                 

                  req.setAttribute("dataObj",form);

 

                  return mapping.findForward("res");

         }

}

 

다음은 자원을 입력하는 폼 양식이다. > inData.jsp

<%@ page contentType="text/html;charset=euc-kr"%>

<HTML>

<HEAD>

      <TITLE> New Document </TITLE>

      <style type="text/css">

             input,textarea,select {background-color:#ffd700;border:1 solid #d2691e;color:#4b0082};

             .ff{background-color:#ffcc33};

             .fa{background-color:#fae78b};

       </style>

</HEAD>

 

<BODY>

       <form method="post" action="send.st">

           <table width="450" cellspacing="0" cellpadding="4" border="1"

                             bordercolordark="#cc9900" bordercolorlight="#ffff66">

                     <tr>

                         <td width="25%" align="center" class="ff">

                                   <font size="2"><b>이름</b></font>

                          </td>

                          <td class="fa">

                                    <input type="text" name="name">

                           </td>

                     </tr>

                     <tr>

                            <td align="center" class="ff">

                                     <font size="2"><b>ID</b></font>

                             </td>

                             <td class="fa">

                                     <input type="text" name="id">

                              </td>

                      </tr>

                      <tr>

                              <td align="center" class="ff">

                                       <font size="2"><b>Password</b></font>

                              </td>

                              <td class="fa">

                                       <input type="password" name="pwd" maxlength="12" size="15">

                               </td>

                      </tr>

                      <tr>

                               <td width="25%" align="center" class="ff">&nbsp;</td>

                               <td class="fa">

                                        <input type="submit" value="정보 보내기">

                                        <input type="reset" value="다시 입력">

                                </td>

                       </tr>

           </table>

       </form>

</BODY>

</HTML>

 

이제 마지막에 출력할 view문서이다. > resForm.jsp

<%@ page contentType="text/html;charset=euc-kr"%>

<%@ page import!="form.FormData"%>

<h1>입력 자료</h1><hr>

<%

             FormData d = (FormData)request.getAttribute("dataObj");

%>

<table border="1" borderColor="#ababab" width="400" style="border-collapse:collapse" cellspacing="0">

     <tr bgcolor="#cdcdcd" align="center">

           <td>Name</td><td>ID</td><td>PWD</td>

      </tr>

      <tr align="center">

            <td><%=d.getName()%></td>

            <td><%=d.getId()%></td>

            <td><%=d.getPwd()%></td>

      </tr>

</table>

 

스트럿츠에서는 다음과 같이 ActionForm 을 처리 한다.

1.  Action의 매핑 정보를 확인 하고 Action이 설정 되어 있는지 확인 한다.

Action 매핑의 name 속성에 해당 하는 <form-bean > 매핑이 있는지 확인 한다.
<!-- ========== Form Bean Definitions ================================ -->
    <form-beans>
        <form-bean name="f1" type="form.FormData">                 
            <form-property name="name" type="java.lang.String" />
            <form-property name="id" type="java.lang.String" />

<form-property name="pwd" type="java.lang.String" />
        </form-bean>           
    </form-beans>
<!-- ========== Action Mapping Definitions ============================ -->
    <!--valiedate true라고 함으로써 f1 validate가 호출됩니다.      -->
    <action-mappings>
            <!-- FormAction에 대한 정의 -->
          <action path="/in" forward="/inData.jsp"/>

<action path="/send" type="form.FormAction" name="f1"                       

            validate="true"

            input="/inData.jsp"> 

    <forward name="res" path="/resForm.jsp" redirect="false"/>

</action>
      </action-mappings>
2.  메모리에 ActionForm 인스턴스가 있는지 확인하여 이미 만들어진 타입이 같고 scope적당 한

 것이 있으면 재사용하고 없으면 새로 인스턴스를 생성 한다. 새 인스턴스를 만드는 경우엔

scope 속성이 있다면 속성에 따른 scope에 저장 합니다.

3.  Controller는 요청 파라미터에 있는 ActionForm의 인스턴스에 입력 하기전에 reset() 메소드를

수행 한다. 결국 reset이라는 것은 초기화의 의미이며 폼빈의 인스턴스를 공유하는 경우엔 중요한

부분 이다.

public void reset(ActionMapping mapping, HttpServletRequest request) {
               name= "";

         pwd = "";
               id = "";
        }

4.  ActionForm setter를 통해 요청 파라미터 값을 ActionForm에 입력 한다.

    public void setId(String id) {

               this.id = id;
        }
       
        public void setPwd(String pwd) {
                this.pwd = pwd;
        }

5.  validate속성이 true로 설정 되어 있으면 ActionForm객체에 validate() 메소드를 자동 호출한다.

그리고 에러가 있다면 에러를 반환하도록 코드하는 것이 좋다.

public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {

                ActionErrors errors = new ActionErrors();
               
                if((id == null) || (id.length()<1)) {
                        errors.add("error.id.required", new ActionError("error.id.required"));
                }
               
                if((pwd == null) || (pwd.length()<1)) {
                        errors.add("error.pwd.required", new ActionError("error.pwd.required"));
                }               
                return errors;                       
        }

폼 데이터를 전송 하는 모든 HTML 페이지에서 ActionForm 사용해야 하는데 HTML의 폼필드의 이름과

 ActionForm의 속성의 이름이 일치한다면 ActionForm을 여러 페이지에서 사용 가능 하다.

중요한 메소드는 reset(), validate() 메소드 인데 하나씩 보도록 하자~

reset() 메소드의 원형은 다음과 같다.
  public void reset(ActionMapping mapping, HttpServletRequest request);

스트럿츠의 ActionForm 클래스의 위 두메소드는 기본적으로 아무 기능도 수행 하지 않으므로 ActionForm

 상속한 하위 클래스에서 필요하다면 재정의(Override) 해야 한다.

Controller는 요청 파라미터에 있는 ActionForm의 인스턴스에 입력 하기전에 reset() 메소드를 수행 한다.

결국 reset()이라는 것은 초기화의 의미이며 폼빈의 인스턴스를 공유하는 경우엔 중요한 부분인

것이다.

Controller는 요청값들이 ActionForm setter에 의해 설정 되면 validatetrue로 설정 된 경우에는

valiedate() 메소드를 호출 하는데 이 메소드에서는 사용자의 입력 값에 대한 validation check를 수행 한다.

오류가 있다면 ActionError 객체에 담아서 리턴 한다. ActionForm에서의 validate()는 비즈니스 로직 이라기 보다는

입력 값의 단순한 검사 정도로 보면 되며, 실제 들어온 값에 대한 논리적인 타탕성등 여러가지 검사를

하기 위해서는 별도의 비즈니스 로직을 만들어 처리해야 한다.

validate() 메소드의 원형은 다음과 같다.
public ActionErrors validate(ActionMapping mapping, HttpServletRequest request);

 

 

이제 위의 내용을 확인해 보는 결과다.

 

사용자 삽입 이미지

 

위와 같이 입력한 후 [정보 보내기] 버튼을 선택 하면 입력한 정보들이

하나의 ActionForm객체가 되어 Action객체에게 던져 진다. 그리고 Action객체는

자신이 하고자 하는 일에 맞도록 처리한 후 forward를 수행하게 되어 있다. 

사용자 삽입 이미지