Last Modified : 2009.09.19

Struts - First Steps

http://www.michael-thomas.com/tech/apache/struts/struts_eclipse_myhelloworld.htm
위에 링크된 원글은 Struts 를 시작하려는 프로그래머에게 성공적인 첫번째 예제를 제공하고 있습니다.
아래의 글은 원글을 해석한 내용입니다.

1. Struts 다운로드 & 예제 웹 애플리케이션 설치

http://struts.apache.org/download.html 에서 General Availability (GA) Releases 중 1.x 버전을 클릭하여 (현재 1.3.8) Full Distribution 을 다운로드 합니다. ( 파일명 struts-1.3.8-all.zip )
압축을 풀면 아래와 같은 디렉토리가 생깁니다.

예제 애플리케이션이 있는 apps 디렉토리에서 struts-blank-1.3.8.war 원본은 백업하고 카피본은 파일명을 mystruts-helloworld.war 라고 바꿉니다.
이 파일을 Tomcat 의 웹 애플리케이션을 등록합니다.
두 가지 방법이 있는데 하나는 mystruts-helloworld.war 파일을 단순히 {TOMCAT_HOME}/webapps 디렉토리에 파일을 두는 것입니다.
두번째 방법은 수동으로 Tomcat 에 웹 애플리케이션으로 등록하는 방법입니다.
[ 참조 : "새로운 자바 웹 애플리케이션을 작성" ]
먼저 mystruts-helloworld.war 파일을 적당한 디렉토리에 압축을 풉니다.
( 예, C:/www/jsp/mystruts-helloworld )

- mystruts-helloworld 애플리케이션 파일 구조

open all | close all

다음으로 {TOMCAT_HOME}/conf/Catalina/localhost 디렉토리에 mystruts-helloworld.xml 파일을 아래 내용으로 만듭니다.

mystruts-helloworld.xml

<?xml version="1.0" encoding="UTF-8"?>
<Context
    docBase="C:/www/jsp/mystruts-helloworld"
    reloadable="true">
</Context>

http://localhost:8080/mystruts-helloworld 을 방문하여 mystruts-helloworld 웹 애플리케이션이 성공적으로 로드되었는지 확인합니다.
Struts install Success Confirm
이름은 mystruts-helloworld 이지만 지금까지는 struts-blank-1.3.8.war 예제 웹 애플리케이션과 같습니다.

2. Eclipse 에서 mystructs-helloworld 프로젝트 생성 & 설정

Eclipse 에서 mystruts-helloworld 작업하기 위한 설정을 하겠습니다.

1) 프로젝트 생성

메뉴에서 File, New, Project 을 차례로 선택
Eclipse New Project Create Diagram 1
다이얼로그 박스에서 Java Project 를 선택, Next 버튼
Eclipse New Project Create Diagram 2
아래 그림처럼 설정 후, Next 버튼
Eclipse New Project Create Diagram 3
Default output folder 를 아래 그림과 같이 설정, Finish 버튼
Eclipse New Project Create Diagram 4

2) Build Path 설정

Package 뷰에서 새로 생성한 프로젝트 mystruts-helloworld 를 마우스 오른쪽 버튼으로 선택한 후 나타나는 컨텍스트 메뉴에서 아래 그림과 같이 Build Path, Configure Build Path.. 를 차례로 선택
빌드패스 설정으로 output 폴더 재설정
Libraries 탭을 선택, "Add External JARs..." 메뉴를 이용하여 아래 아카이브 파일 추가

  • mystruts-helloworld/WEB-INF/lib 에 있는 모든 아카이브 파일
  • {TOMCAT_HOME}/common/lib/servlet-api.jar

서브릿관련 외부 jar 파일 추가

3) 소스 폴더 설정

Package 뷰에서 mystruts-helloworld 프로젝트를 마우스로 선택, 메뉴에서 File, New, Source Folder 차례로 선택
소스 폴더 변경 WEB-INF/src 로
"New Source Folder" 다이얼로그 박스의 Folder Name 을 WEB/src 로 설정
소스 폴더 변경 WEB-INF/src

4) MessageResources.properties 파일 위치 변경 - struts-config.xml 편집

MessageResources.properties 파일은 /WEB-INF/classes 폴더에 있습니다.
이 파일은 자주 수정해야 하는 파일이므로 /WEB-INF/src 에 복사합니다.
이제 Eclipse 에서 수정하면 output 폴더로 설정된 /WEB-INF/classes 에 복사됩니다.

5) web.xml 수정

아래는 struts-blank 웹 애플리케이션의 web.xml 파일 내용으로 Struts 설정에서 핵심이 되는 부분입니다.

<!-- Standard Action Servlet Configuration -->

<servlet>
  <servlet-name>action</servlet-name>
  <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
  <init-param>
    <param-name>config</param-name>
    <param-value>/WEB-INF/struts-config.xml</param-value>
  </init-param>
  <load-on-startup>2</load-on-startup>
</servlet>

<!-- Standard Action Servlet Mapping -->

<servlet-mapping>
  <servlet-name>action</servlet-name>
  <url-pattern>*.do</url-pattern>
</servlet-mapping>

<!-- The Usual Welcome File List -->

<welcome-file-list>
  <welcome-file>index.jsp</welcome-file>
</welcome-file-list>

action 이란 이름으로 org.apache.struts.action.ActionServlet 서블릿을 정의하고 있습니다.
초기화 파라미터로서 config 란 이름으로 /WEB-INF/struts-config.xml 파일을 정의하고 있습니다.
load-on-startup 엘리먼트의 내용이 2라는 양수 값입니다.
이 값이 양수이므로 웹 애플리케이션이 로드될 때 ActionServlet 의 init 메소드가 실행됩니다.
ActionServlet 의 init 메소드는 struts-config.xml 파일의 내용을 메모리에 올립니다.
그렇기 때문에 즉, ActionServlet 이 struts-config.xml 파일 자체를 참조하는 것은 아니기에 struts-config.xml 의 내용이 변경되면 변경된 내용이 애플리케이션에 반영되기 위해서는 해당 애플리케이션을 다시 로드해야 합니다.
서블릿 매핑 설정은 *.do 인 요청은 모두 action 란 이름의 서블릿이 맡는다고 설정한 것입니다.
이 설정으로 인해 *.do 요청이 오면 Tomcat 은 ActionServlet에게 해당 요청을 전달합니다.

3. mystruts-helloworld 웹 애플리케이션으로 본격적인 편집

1) Welcome.jsp 편집

/index.jsp 는 http://localhost:8080/mystruts-helloworld 방문했을 때 보여지는 페이지입니다.
web.xml 에서 welcome-file-list 에서 index.jsp 라고 설정이 되어 있기 때문에 / 로 요청하면 index.jsp 파일로 요청이 전달됩니다.
/index.jsp 파일을 열고 코드를 분석하도록 하겠습니다.

<%@ taglib uri="/tags/struts-logic" prefix="logic" %>
<logic:redirect forward="welcome" />

<logic:redirect forward="welcome" /> 는 structs-config.xml 의 global-forwards 엘리먼트의 자식 엘리먼트인 forward 엘리먼트의 name 속성이 welcome 으로 정의된 곳으로 리다이렉트 하라는 코드입니다.
struts-config.xml 에서 welcome 부분을 찾습니다.

<!-- Global Forward Definitions -->

<global-forwards>
  <!-- Default forward to "Welcome" action -->
  <!-- Demonstrates using index.jsp to forward -->
  <forward
      name="welcome"
      path="/Welcome.do"/>
</global-forwards>

index.jsp 에서 forward="welcome" 이 부분은 struts-config.xml 의 <global-forwards> 설정이 적용되어 결국 /Welcome.do 를 요청하게 됩니다.
이제 Welcome.do 요청을 대한 설정을 struts-config.xml 파일에서 찾습니다.
action mappings 엘리먼트의 자식 엘리먼트 action 에서 속성 path="Welocme" 이라고 되어 있는 부분이 있습니다. ( Welcome.do 가 아닌 이유는 do 가 생략하여 쓰기 때문입니다. )
action 엘리먼트의 자식 엘리먼트 forward 의 속성값이 forward="/pages/Welcome.jsp" 라고 되어 있는 것을 확인할 수 있습니다.

<action-mappings>
<!-- Default "Welcome" action -->
<!-- Forwards to Welcome.jsp -->
  <action
    path="/Welcome"
    forward="/pages/Welcome.jsp"/>
	
    ... 중간 생략 ...
    
    
</action-mappings>	

사용자가 웹 애플리케이션의 / 요청하면 index.jsp 실행되는데 index.jsp 페이지에서는 Welcome.jsp 페이지로 리다이렉트하고 있습니다.
이제 우리는 / 를 방문했을 때 보여지는 페이지는 index.jsp 가 아니고 /pages/Welcome.jsp 라는 것을 알게 되었습니다. 이제 새로운 내용을 나타내기 위해서 /pages/Welcome.jsp 파일의 </body> 전에 다음을 추가합니다.

<p>
  <html:link action="/Logon"><bean:message key="welcome.logonlink" /></html:link>
  <bean:message key="welcome.logonmessage" />
</p>
<p>
  <html:link action="/Help"><bean:message key="welcome.helplink" /></html:link>
  <bean:message key="welcome.helpmessage" />
</p>

파일을 저장하고 다시 웹 애플리케이션(http://localhost:8080/mystruts-helloworld)을 방문합니다.

javax.servlet.ServletException: Missing message for key "welcome.logonlink"

위와 같은 에러 메시지가 나타납니다.
서블릿 컨테이너가 welcome.logonlink 에 알맞은 값을 MessageResources.properties 에서 찾지 못했기 때문입니다.
서블릿 컨테이너가 jsp 파일을 서비스하기 위해 해석할 때 태그 bean:message 부분에 이르면 resource 프로퍼티파일, MessageResources.properties 에서 해당하는 키값을 찾아 대입하여 해석하려고 시도합니다.
따라서 MessageResources.properties 에 해당하는 키값을 등록해야 합니다.
다음 코드를 MessageResources.properties 파일의 하단에 추가합니다.

welcome.logonlink=Logon
welcome.logonmessage=-logon page for the webapp "mystruts-helloworld"(jsp).
welcome.helplink=Help
welcome.helpmessage=-help instructions (html).

파일을 저장한 후 애플리케이션을 다시 올리거나 Tomcat 을 재시작한 후 다시 방문합니다.
에러가 보이지 않아야 않는 걸 확인할 수 있습니다.
다음은 MessageResources.properties 파일에서 추가가 아닌 기존의 내용을 다음과 같이 변경해 보겠습니다.

welcome.title=My Struts Hello World
welcome.heading=Welcome to "My Struts Hello World"
welcome.message=This web app is an example of a "Hello World" type Struts application.

파일을 저장한 후 웹 애플리케이션을 다시 올립니다. (또는 Tomcat 을 재시작합니다.)
수정이 끝나고 다시 방문하면 아래와 같이 화면을 볼 수 있습니다.
MessageResource 테스트 확인

2) Help 링크 수정 - help.html

위 화면에서 (Welcome.jsp) Help 링크를 클릭하면 아래와 같은 에러가 발생합니다.
아직 Help 링크에 대해 어떠한 작업도 하지 않았기 때문입니다.

org.apache.struts.chain.commands.InvalidPathException: No action config found for the specified url

Tomcat log 확인

이와 같은 에러 메시지는 {TOMCAT_HOME}/logs 에 위치한 catalina로 시작하는 로그 파일에서도 확인할 수 있습니다.

help.html 생성

pages 폴더에 아래와 같은 help.html 파일을 만듭니다.

/pages/help.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitonal.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR" />
<title>Help Screen</title>
</head>  
  
<body>
  <h1>Help Screen</h1>
  <p>Help info goes here.</p>
</body>
  
</html>
struct-config.xml 에서 action-mappings 추가

action-mappings 부분을 찾아서 </action-mappings> 태그 바로 전에 아래 코드를 추가합니다.

<!-- Display the "Help" documentation -->
<action
  path="/Help"
  forward="/pages/help.html"/>
Help 링크 테스트

웹 애플리케이션을 다시 올리고
http://localhost:8080/mystruts-helloworld
를 방문한 후 Help 링크를 클릭합니다.
help.html 페이지가 보이는지 확인합니다.

2. Logon 링크 수정 - logon.jsp

(1) logon.jsp 파일 생성

pages 폴더에 logon.jsp 라는 파일을 아래 내용과 같이 만듭니다.

/pages/logon.jsp

<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
    
<%@ taglib uri="/tags/struts-bean" prefix="bean" %>
<%@ taglib uri="/tags/struts-html" prefix="html" %>
<%@ taglib uri="/tags/struts-logic" prefix="logic" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitonal.dtd">

<html:html>
<head>
<title><bean:message key="logon.title"/></title>
<html:base/>
</head>
<body bgcolor="white">

<html:errors/>

<logic:notPresent name="org.apache.struts.action.MESSAGE" scope="application">
  <font color="red">
    ERROR:  Application resources not loaded -- check servlet container
    logs for error messages.
  </font>
</logic:notPresent>

<h3><bean:message key="logon.heading"/></h3>
<p><bean:message key="logon.message"/></p>

</body>
</html:html>
(2) struct-config.xml 에서 action-mappings 추가

action-mappings 부분에서 액션을 추가합니다.

<!-- Display the "Logon" page -->
<action
  path="/Logon"
  forward="/pages/logon.jsp"/>
(3) WEB-INF/src/java/MessageResources.properties 키 추가

logon.jsp 파일 소스에서 강조된 부분에 대한 키를 프로퍼티 파일에 아래와 같이 추가합니다.

logon.title=Logon Screen
logon.heading=Logon Screen
logon.message=Enter your user name and password then click "Submit"<br />(Note:test/password)
(4) web.xml 수정 - Struts Tag 라이브러리 사용하기 위해

logon.jsp 파일 소스를 보면 아래와 같이 Struts 태그 라이브러리를 이용하는 코드를 볼 수 있습니다.

<%@ taglib uri="/tags/struts-bean" prefix="bean" %>
<%@ taglib uri="/tags/struts-html" prefix="html" %>
<%@ taglib uri="/tags/struts-logic" prefix="logic" %>

struts-logic.tld, struts-bean.tld, struts-html.tld 를 struts를 압축을 푼 폴더에서 찾아 /WEB-INF 디렉토리에 복사합니다.
tld 파일 다운로드
web.xml 파일을 열고 </web-app> 바로 전에 아래 내용을 추가합니다.

<!-- Struts Tag Library Descriptors -->
<jsp-config>
  <taglib>
    <taglib-uri>/tags/struts-bean</taglib-uri>
    <taglib-location>/WEB-INF/tlds/struts-bean.tld</taglib-location>
  </taglib>

  <taglib>
    <taglib-uri>/tags/struts-html</taglib-uri>
    <taglib-location>/WEB-INF/tlds/struts-html.tld</taglib-location>
  </taglib>

  <taglib>
    <taglib-uri>/tags/struts-logic</taglib-uri>
    <taglib-location>/WEB-INF/tlds/struts-logic.tld</taglib-location>
  </taglib>

  <taglib>
    <taglib-uri>/tags/struts-nested</taglib-uri>
    <taglib-location>/WEB-INF/tlds/struts-nested.tld</taglib-location>
  </taglib>

  <taglib>
    <taglib-uri>/tags/struts-tiles</taglib-uri>
    <taglib-location>/WEB-INF/tlds/struts-tiles.tld</taglib-location>
  </taglib>
</jsp-config>

애플리케이션을 다시 올리고 Logon 링크를 클릭하여 다음 화면에 나오는지 확인합니다.
로그온 페이지 확인

3. Logon 폼 추가 - logon.jsp 에서 사용자 정보를 입력받기 위한 폼 태그 추가

logon.jsp 페이지에서 사용자 이름 ( User Name ) 과 패스워드 ( Password ) 를 입력 받기 위해 폼 태그를 추가합니다.
아래의 Struts 태그 라이브러리를 이용하겠습니다.

  • html:form
  • html:text
  • html:password
  • html:submit
  • html:reset
(1) 폼태그 추가

다음 소스 코드를 </body> 바로 전에 추가합니다.

<html:form 
   action="/LogonSubmit" 
   focus="username">

<table>
  <tr>
    <td><bean:message key="logon.username"/></td>
    <td><html:text property="username" size="16" maxlength="18"/></td>
  </tr>
  <tr>
    <td><bean:message key="logon.password"/></td>
    <td>
     <html:password property="password" size="16" maxlength="18" redisplay="false"/>
    </td>
  </tr>
  <tr>
    <td> </td>
    <td><html:submit property="Submit" value="Submit"/> <html:reset/></td>
  </tr>
</table>  
         
</html:form>
(2) MessageResources.properties 수정 - 키 추가

빨강색으로 강조된 키를 프로퍼티 파일, MessageResources.properties 에 추가합니다.

logon.username=User Name
logon.password=Password
(3) struts-config.xml 수정 - action-mappings 추가

action-mappings 부분에 액션을 추가합니다.

- LogonSubmit 액션 추가
<!-- Process a user logon -->
<action path="/LogonSubmit"
	   type="com.michaelthomas.mystrutshelloworld.LogonAction"
	   name="logonForm"
	   scope="request"
	   input="/Logon.do"
	   validate="true">
 <forward name="success"  path="/MainMenu.do"/>
 <forward name="failure"  path="/Logon.do"/>
	   
</action>

설정대로라면,
LogonAction 이 success 을 리턴하면 /MainMenu.do 로, faliure 를 리턴하면 /Logon.do 로 이동하게 됩니다.

(4) struts-config.xml, validation.xml 수정 - DynaValidation 사용하기 위해
<!-- Logon form bean -->
<form-bean  name="logonForm"  type="org.apache.struts.validator.DynaValidatorForm">
  <form-property name="username" type="java.lang.String" initial=""/>
  <form-property name="password" type="java.lang.String" initial=""/>
</form-bean>

위 내용을 struts-config.xml 의 <form-beans> 부분에 추가합니다.
폼(Form)을 검사하기 위해서 DynaValidation 이라는 Struts Validator를 사용토록 하는 설정입니다.
DynaValidation 쓰면 ActionForm 를 따로 만들지 않아도 됩니다.
위에서 처럼 XML 파일 설정만으로 따로 ActioForm 자바 클래스를 없이 폼에 대한 기본적인 검사가 가능하다는 얘기입니다.
/WEB-INF/validation.xml 파일을 오픈하고 위에서 설정한 <form name="logonForm"> 부분을 찾아서 아래 볼드체로 되어 있는 것과 같이 수정합니다.

<form name="logonForm">
  <field
      property="username"
      depends="required">
          <arg key="logon.username"/>
  </field>
  <field
      property="password"
      depends="required,mask">
          <arg key="logon.password"/>
          <var>
              <var-name>mask</var-name>
              <var-value>^[0-9a-zA-Z]*$</var-value>
          </var>
  </field>
</form>
(5) Logon Valitaion 테스트

톰캣을 재가동하고 Welcome.jsp 페이지에서 Logon 링크를 클릭합니다.
2개의 텍스트필드에 값을 넣지 않고 "Submit" 버튼을 클릭합니다.
Validator 가 작동하면 사용자가 보는 페이지에 다음과 같이 나타나게 됩니다.

  • User Name is required.
  • Password is required.

만약 위와 같은 메시지가 아니라

  • null is required.
  • null is required.

와 같이 나타난다면 /WEB-INF/validation.xml 파일을 열고
<arg key="logonForm.username"/> 을 <arg key="logon.username"/> 으로
<arg key="logonForm.password"/> 을 <arg key="logon.password"/> 으로
변경한 되어 있는지 확인합니다.

(6) Validation 작동 원리 설명 & 에러 메시지 수정
  • User Name is required.
  • Password is required.

아무것도 입력하지 않고 Submit 버튼을 클릭하면 위와 같은 에러 메시지를 페이지에서 볼 수 있습니다.
이 메시지는 /pages/logon.jsp 에서 출력하고 있고, 메시지를 출력하는 태그는 <html:errors/> 입니다.
이런 메시지는 어떻게 화면에 출력되는 걸까요?
DynaValidator 는 메시지를 프로퍼티 파일에서 얻습니다.
MessageResources.properties 프로퍼티 파일을 오픈하고 다음 키에 주목해서 보세요.

errors.required={0} is required.

MessageResources.properties 는 사용자명과 패스워드에 대한 유효성 검사 메시지가 있어야 하는 곳입니다.

  • User Name is required.
  • Password is required.

메시지에서 단어 "User Name" 과 "Password" 는 validation.xml 파일 내에 arg 엘리먼트의 key 속성값에 해당합니다. <arg key="logon.username"/> 에서 logon.username 을 MessageResources.properties 에서 찾으면 키값이 User Name 임을 확인할 수 있습니다.
이 값이 errors.required={0} is required. 에서 {0} 의 인자로 작용한 것입니다.
{0} is required. 에서 {0}에 logon.username 과 logon.password 키 값이 인자로 작용해서 결국은 우리가 확인한 UserName is required. 와 같은 메시지를 보게 되는 것입니다.
errors.required={0} is required 메시지가 적용된 이유는 validatiion.xml 안에 답이 있습니다.

<form name="logonForm">
  <field
      property="username"
      depends="required">
          <arg key="logon.username"/>
  </field>
  <field
      property="password"
      depends="required,mask">
          <arg key="logon.password"/>
          <var>
              <var-name>mask</var-name>
              <var-value>^[0-9a-zA-Z]*$</var-value>
          </var>
  </field>
</form>

depends 속성에 required 라고 설정되었기 때문에 프로퍼티 파일에서
errors.requird={0} is required. 가 작동한 것입니다.

이제 User Name is required. Password is required 라는 퉁명스런 메시지 외에 좀더 친숙한 메시지를 출력하려 합니다.
에러 메시지의 header 메시지를 아래와 같이 수정합니다.

errors.header=<h3><font color="red">Validation Error</font></h3><p>You must correct the following error(s) before proceeding:</p><UL>
(7) 로그인 실패시 지시 메시지 수정 후 테스트

애플리케이션을 다시 로드한 후 로그인 페이지로 가서 아무런 값을 넣지 않고 Submit 버튼을 클릭합니다.
다음과 같은 메시지를 나오는지 확인합니다.
유효성 검사 에러 메시지
계속해서 텍스트 필드 중 하나에만 값을 입력하고 Submit 버튼을 클릭합니다.
에러 메시지가 어떻게 변경되었는지 확인합니다.

Validation - validation.xml

Validation 에 관련된 파일은 validation.xml 과 validation_rules.xml 파일이 있습니다.
validation.xml 파일에서 <formset> 부분의 첫번째 태그는 <form name="logonForm"> 입니다.
struts-blank 예제 애플리케이션의 validation.xml 의 form 엘리먼트의 이름이 우리가 사용하는 ActionForm 인 logonForm 과 일치합니다. (그래서 추가가 아닌 수정을 한 것입니다.)

언어에 대해서 특별히 명시되지 않는다면 디폴트 form 태그의 언어는 영어입니다.
<formset language="fr"> 이것은 언어가 프랑스어일 때 사용됩니다.

struts-config.xml 의 plug-in 엘리먼트를 찾아봅니다.
Validation 프레임워크가 플러그인으로 설정되어 있는 것을 확인할 수 있습니다.

<formset> 이 부분에 여러분이 유효성 검사를 원하는 폼(form)에 대한 내용을 추가하여 사용합니다.
<form name="logonForm"> <arg key="logon.username"/> 는 Validator 에게 메시지리소스 프로퍼티 파일에서 키logon.username 키에 해당하는 값을 찾아서 errors.required={0} is required. 에서 {0}의 아규먼트로 전달하여 Validation 메시지를 만들게 합니다.
만약 logon.username 값이 메시지리소스 프로퍼티 파일에 있지 않다면 null is required. 와 같은 메시지를 보게 될 것입니다.
이와 같은 에러를 일부러 내고 확인해 보도록 합니다.

(8) UserName, Password 필드에 모두 입력 후 테스트 - LogonSubmit.do

다시 로그인 페이지로 이동해서 이번에는 텍스트 필드에 모두 입력한 다음에 Submit 버튼을 클릭합니다.
다음과 같은 에러를 확인합니다.

java.lang.ClassNotFoundException: com.michaelthomas.mystrutshelloworld.LogonAction

http://localhost:8080/mystruts-helloworld/Logon.do 를 다시 방문해서, 서블릿 컨테이너가 만든 html 코드를 웹브라우저의 "소스 보기" 를 이용하여 아래 코드를 확인합니다.

<form name="logonForm" method="post" action="/mystruts-helloworld/LogonSubmit.do">

Logon.do 에서 Submit 버튼을 눌렸을 때 LogonSubmit.do 를 요청하게 됩니다.
이 요청에 대해 일을 하는 클래스가 LogonAction 클래스입니다.
하지만, LogonAction 이 일을 하기 전에 Struts는 struts-config.xml 에서 action 에서 설정(validate="true")대로 Validation 체크를 먼저 수행합니다.
이 Validation 체크가 통과되면 그제서야 LogonAction 의 execute 메소드가 호출됩니다.
struts-config.xml 파일에서 <action-mappings> 부분을 보면 아래의 자바 클래스가 불리워진다는 것을 알 수 있습니다.

<action path="/LogonSubmit" type="com.michaelthomas.mystrutshelloworld.LogonAction"

이제 이 자바 파일을 만들어야 합니다.

(9) LogonAction.java 생성

Package 뷰에서 mystruts-helloworld 프로젝트를 선택한 후, 툴메뉴중 아래 메뉴를 선택합니다.
toolbar 메뉴
Name 필드에는 com.michaelthomas.mystrutshelloworld 라고 입력하고 Finish 버튼을 클릭하여 Package 생성이 완료합니다.
팩키지 선택
Package 뷰에서 com.michaelthomas.mystrutshelloworld 팩키지를 선택한 후 그림과 같이 툴바에서 New Java Class 를 클릭합니다.
LogonAction 클래스 작성
Name 필드에 LogonAction 이라고 입력한 후 Finish 를 클릭하여 완료합니다.
LogonAction 클래스 작성
에디터에서 LogonAction.java 을 아래와 같이 작성합니다.

LogonAction.java

package com.michaelthomas.mystrutshelloworld;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;
import org.apache.struts.action.Action;

public final class LogonAction extends Action {

  public ActionForward execute(
    ActionMapping mapping,
    ActionForm form,
    HttpServletRequest request,
    HttpServletResponse response) throws Exception {

    String username = (String) PropertyUtils.getSimpleProperty(form,"username");
    String password = (String) PropertyUtils.getSimpleProperty(form,"password");
    
    ActionMessages errors = new ActionMessages();

    if ( username.equals("test") && password.equals("password") ) {
      // Set a request attribute to be used by a JSP page.
      request.setAttribute("fullName", "John Doe");
      request.setAttribute("logonID", username);
    } else {
      errors.add(
      ActionMessages.GLOBAL_MESSAGE,
      new ActionMessage("errors.logon.invalid"));
    }
    
    if ( errors.isEmpty() ) {
      return (mapping.findForward("success"));
    } else {
      this.saveErrors(request, errors);
      return (mapping.findForward("failure"));
    }
  }
}

위의 코드중 중요한 부분을 분석해 봅시다.

String username = (String) PropertyUtils.getSimpleProperty(form, "username");

전송된 폼으로부터 값(여기서는 사용자명과 패스워드)을 가져오는 코드입니다.

request.setAttribute("fullName", "John Doe");

다음 액션이나 JSP 페이지로 보낼 데이터를 HttpServletRequest 에 저장하는 코드입니다.

errors.add(ActionMessages.GLOBAL_MESSAGE,new ActionMessage("errors.logon.invalid"));

여기서 errors.logon.invalid 키는 메시지리소스 프로퍼티 파일에 반드시 있어야 합니다. (현재는 프로터피 파일에 없습니다. 수정하는 내용은 조금 후에 나옵니다.

return (mapping.findForward("success"));
return (mapping.findForward("failure"));

Struts 에게 다음 액션이 무엇인지 알리는 코드입니다.
스트러츠 컨트롤러는 이 코드에 의해 다음 액션을 결정합니다.

(10) UserName, Password 필드에 모두 입력 후 테스트 2 - LogonSubmit.do

Logon 페이지로 이동합니다.
User Name, Password 에 다음과 같이 입력합니다.
User Name: test
Password: test ( password 라고 입력하지 않습니다. 분명 validation error 가 만들어질 것입니다.)
Submit 버튼을 클릭하면 나타나는 페이지에서 Validation error 를 설명하는 어떠한 글도 없습니다.
우리의 LogonAction 은 DynaValidator 뿐 아니라 추가적인 validation 을 가지고 있습니다. (코드에 구현되어 있는 유효성 검사를 말하고 있습니다.)
그래서 test/test 로 로그온을 시도한 사용자가 유효한 사용자가 아니라고 결정하는 것입니다.
우리의 프로그램에서는 test/password 인 단 하나의 유효한 user/password 를 가 있습니다.
결과적으로 Struts 컨트롤러는 struts-config.xml의 설정대로 "failure" 에 해당하는 "/Logon.do" 를 요청합니다.
(- LogonSubmit 액션 추가 를 참고하세요. ) 그러면 logon.jsp 페이지는 Validation errors 를 보여주게 됩니다.
메시지리소스 프로퍼티 파일에서 errors.logon.invalid 키값에 해당하는 메시지가 보이지 않습니다. 이제 메시지리소스 프로퍼티 파일에 errors.logon.invalid 키와 키값을 설정하겠습니다.

(11) LogonAction 에서 발생한 Validation error 출력 - MessageResources.properties

프로퍼티 파일에 아래 내용을 error 키의 맨 마지막 부분 다음에 추가합니다.

# -- validator (Custom) --
errors.logon.invalid=Invalid password. Try username='test' and password='password'

웹 애플리케이션을 다시 올립니다.
Logon 페이지로 이동하여 User Name 과 Password 텍스트필드에 다음과 같은 값을 입력합니다.
User Name: test
Password: test ( password라고 입력하지 않습니다. Validation error 가 발생할 것입니다.)
Submit 버튼을 클릭하고 우리의 문제가 고쳐졌는지 확인합니다.

(12) mainMenu.jsp 없기 때문에 나는 에러 수정.

Logon 페이지로 돌아와서 이제는 유효한 값을 텍스트필드에 넣습니다.
User Name: test
Password: password
Submit 버튼을 클릭하면 다음과 같은 에러를 볼 수 있습니다.

javax.servlet.ServletException: No action config found for the specified url.

스트러츠 컨트롤러는 struts-config.xml 설정대로 "success" 에 해당하는 /MainMenu.do 요청합니다.
( - LogonSubmit 액션 추가를 참조하세요 )
그런데 MainMenu.do 액션 설정이 struts-config.xml 파일에 없기 때문에 위와 같은 에러가 발생하는 것입니다.
이제 이 액션에 대한 설정을 struts-config.xml 에 추가하도록 합니다.
다음을 <action-mappings> 섹션에 추가합니다.

<!-- Display MainMenu page -->
<action path="/MainMenu"
        forward="/pages/mainMenu.jsp"/>

/pages/mainMenu.jsp 페이지를 아직 없으므로 JSP 페이지를 아래 내용으로 만듭니다.

<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
    
<%@ taglib uri="/tags/struts-bean" prefix="bean" %>
<%@ taglib uri="/tags/struts-html" prefix="html" %>
<%@ taglib uri="/tags/struts-logic" prefix="logic" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitonal.dtd">
	
<html:html>
<head>
<title><bean:message key="mainmenu.title"/></title>
<html:base/>
</head>
<body bgcolor="white">

<p>
  <bean:message key="mainmenu.welcome"/>
  <bean:write name="fullName" /> ( <bean:write name="logonID" /> )
</p>

<logic:notPresent name="org.apache.struts.action.MESSAGE" scope="application">
  <font color="red">
    ERROR:  Application resources not loaded -- check servlet container
    logs for error messages.
  </font>
</logic:notPresent>

<h3><bean:message key="mainmenu.heading"/></h3>
<p><bean:message key="mainmenu.message"/></p>

</body>
</html:html>

mainMenu.jsp 코드에서 LogonAction 이 request 객체 넣어 전달한 데이터를 어떻게 접근하는지를 주목합니다.

<bean:write name="fullName" /> ( <bean:write name="logonID"/> )

다음 키를 메시지리소스 프로퍼티 파일에 추가합니다.

mainmenu.title=Main Menu Screen
mainmenu.heading=Main Menu Screen
mainmenu.message=The main menu goes here.
mainmenu.welcome=Welcome

웹 애플리케이션을 다시 올리고 Logon 페이지로 이동합니다.
User Name 에 test, Password 에 password 라고 입력한 후 Submit 버튼을 클릭하면 mainMenu.jsp 페이지로 이동하는지 확인합니다.
mainMenu.jsp 페이지에서 관련 메시지가 프로퍼티 파일에서 설정한대로 나타나는지 확인합니다.