본문 바로가기

Web For All/Struts

Struts2 튜터리얼


본 튜토리얼은 제가 Struts 2를 공부할 목적으로 아래의 원문에 링크된 문서를 번역하여 정리한 것입니다.
원문: http://www.roseindia.net/struts/struts2/struts-2-features.shtml


Struts 2 프레임워크는 개발,구현,유지보수의 전체 소프트웨어 개발 사이클을 위해 디자인되었습니다. 프레임워크를 구성하는 각각의 클래스들은 인터페이스에 기반을 두고 있기 때문에 매우 큰 확장성을 가지며 모든 기본 클래스들은 특별한 기능을 가지고 있고 당신이 원하는 기능을 추가할 수도 있습니다. 요구되는 기본 플랫폼 요구사항으로는 Servlet API 2.4, JSP API 2.0, Java 5가 있습니다.

아파치 스트러츠 2 프레임워크의 몇개의 일반적인 특징은 아래와 같습니다.

Architecture
우선 웹브라우저가 리소스를 요청하면 Filter Dispatcher는 적절한 액션을 결정합니다. 그리고 나서 Interceptors는 요구된 함수들을 사용하고 난 후 Action 메서드는 데이터베이스 저장과 조회 등의 데이터베이스 관련 작업을 수행합니다. 그리고 나서 실행결과는 HTML, PDF, 이미지 혹은 그밖의 다른 것으로 변환되어 브라우저에 출력됩니다.

Tags
Struts 2의 태그는 보다 적은 코딩으로 동적 웹 어플리케이션을 생성하도록 도와줍니다.
이 태그들은 데이터 출력뿐아니라 마크업을 다룰 수 있는 스타일 시트를 제공하며 이것은 보다 적은 코드를 가지고 페이지를 생성할 수 있도록 도와줍니다. 태그는 보다 유용한 코딩의 validation과 localization을 지원합니다. 보다 적은 양의 코드는 또한 가독성을 좋게 하고 유지보수를 쉽게 만듭니다.

MVC
스트럿츠 2 프레임워크에서의 Model View Controller는 어플리케이션의 model과 웹 view 사이에서 조정자의 역할을 합니다. 스트럿츠 2의 컨트롤러와 뷰 컴포넌트는 모델을 구현하기 위한 다른 기술과 함께 사용될 수 있습니다. 프레임워크는 역동적인 데이터를 표현하기 위한 라이브러리와 마크업테그를 가집니다.

Configuration
리소스를 초기화하기 위한 배치디스크립터는 XML 포맷으로 제공됩니다.
이러한 초기화는 자바 패키지들을 사용하여 모든 클래스들을 스캐닝함으로써 단순화시키거나 전체 설정을 제어하기 위한 어플리케이션 설정 파일을 사용할 수 있습니다. 다용도의 기본값은 스트럿츠가 직접적으로 Out of the Box를 사용하도록 허락합니다.

설정 파일들은 웹 컨테이너를 재시작하지 않고도 변경이 적용되어 다시 로딩됩니다.

다른 특징들
* 모든 프레임워크 클래스는 인터페이스를 기반으로 하고 있고 핵심 인터페이스는 HTTP와 독립적이다.
* 체크박스들은 거짓값을 위한 어떠한 종류의 특별한 응용도 요구하지 않는다.
* 어떠한 클래스라도 액션 클래스로서 사용될 수 있고 하나의 클래스는 자바빈을 사용하여 액션 클래스에 직접적으로 프라버티를 입력할 수 있습니다.
* 스트럿츠 2 액션들을 Spring과 친화적이기 때문에 통합하기 쉽습니다.
* AJAX 테마는 어플리케이션을 보다 역동적으로 만들어 줄 수 있습니다.
* 자동화된 포틀릿이 코드변경없이 지원되므로 포탈과 서블릿 개발이 쉽습니다.
* 필요하다면 모든 액션의 request 처리를 커스터마이징 하기가 쉽습니다.

Apache Struts 는 자바 웹 어플리케이션을 개발할 때 사용할 수 있는 오픈소스 프레임워크입니다.
Craig R. McClanahan 로부터 시작된 스트럿츠 프로젝트는 2002년에 Apache Software Foundation에 의해 받아들여졌습니다. 스트럿츠는 자바코드, JSP, 서블릿을 사용하는 HTML 포맷을 기반으로 한 어플리케이션을 쉽게 개발하기 위한 뛰어난 프레임워크를 제공하여 왔습니다. 스트럿츠 1은 표준 자바 기술과 자카르타 패키지들을 사용하여 유연한 개발환경을 구축하도록 도와주었습니다. 그러나, 웹 어플리케이션의 요구가 변화함에 따라, 스트럿츠 1은 변화할 필요가 생겼으며 이것이 스트럿츠 2을 탄생시키게 되었습니다. 스트럿츠 2는 AJAX, 빠른 개발과 확장 등의 특징을 가지고 있으며 개발자에게 보다 친숙합니다.

스트럿츠는 MVC 아키텍처를 기반으로 한 잘조직화된 프레임워크 입니다. 모델-뷰-컨트롤러 아키텍처에서, 모델은 비즈니스 혹은 데이터베이스 코드를 위해 존재합니다. 뷰는 페이지 디자인 코드를 표현하고 컨트롤러는 네비게이션 코드를 표현합니다. 이러한 것들이 한데 합쳐져 스트럿츠를 자바 어플리케이션을 만들기 위한 필수적인 프레임워크로 만듭니다. 그러나 Spring, Stripes, Tapestry 같은 새롭고 가벼운 MVC 기반의 프레임워크가 개발됨에 따라 스트럿츠 프레임워크를 변경할 필요성이 생겼습니다. 그래서 아파치 스트럿츠 팀과 또 다른 J2EE 프레임워크인 OpenSymphony의 WebWork 팀은 개발자와 사용자 모두에게 친숙하고 모든 가능한 특징을 가지는 진보된 프레임워크를 개발하기 위해 힘을 모았습니다.

스트럿츠2는 Struts Ti와 플러그인 프레임워크, 새로운 API, Ajax 태그 등을 포함하는 WebWork2의 아키텍처를 사용하여 보다 높은 수준의 어플리케이션을 주창하는 WebWork 2 프로젝트의 조합된 특징들을 가집니다. 그래서 스트럿츠 커뮤니티와 WebWork 팀은 WebWork2 의 몇개의 특별한 특징을 보다 진보적으로 만들기 위해 오픈소스 세계 안에서 단합했습니다. 후에 WebWork2는 Struts2로 바뀌었고 아파치 스트럿츠 2는 개발, 구현, 유지보수를 위한 완벽한 어플리케이션 개발을 위한 역동적이고, 유연한 프레임워크입니다.

WebWork는 스트럿츠 2.0 릴리즈 버전 이후 부터 포함된 웹 어플리케이션 개발을 위한 프레임워크입니다.WebWork는 몇개의 고유한 컨셉을 가지며 자바에 존재하는 웹 API들을 완벽하게 대체하려고 시도하는 것보다 이미 존재하는 것을 사용함으로서 작업의 호환성을 구성합니다. WebWork는 특히 개발자의 생산성과 코드의 간결함을 고려하여 만들어졌습니다. 게다가 XWork 의 래퍼를 제공하는 컨텍스트에 의존적입니다. 웹어플리케이션을 개발할 때 WebWork는 특정한 구현에서 웹개발자를 도와주는 컨텍스트를 제공합니다. 반면 XWork는 설정과 팩토리 구현 관리에 사용된 메카니즘을 제공합니다. 이 메카니즘은 Dependency Injection(DI) 메커니즘이라고 합니다.

Struts 2 프레임워크를 개발하기 위해서 Struts와 webwork가 합쳐졌습니다. Struts 2는 엔터프라이즈 웹 어플리케이션을 개발하기 위한 매우 확장성이 있고, 고상한 프레임워크입니다. 이 섹션에서 Struts 2 프레임워크의 아키텍쳐를 설명합니다.

스트럿츠 2 어플리케이션에서의 Request 라이프사이클
  1. 사용자가 Request 전송
    - 사용자가 서버로 몇개의 리소스를 위한 요구사항을 전송한다.
  2. FilterDispatcher가 적절한 액션을 결정
    - FilterDispatcher 가 request를 살펴 본 후 적절한 액션을 결정합니다.
  3. Interceptors 적용
    - workflow, validation, file upload 등과 같은 공통적인 기능의 적용을 위해 설정된 Interceptors가 request에 자동으로 적용된다.
  4. Action 실행
    - 데이터베이스로부터 데이터를 저장하고 조회하는 등의 데이터베이스와 관련된 작업을 수행하기 위한 액션 메서드가 실행된다.
  5. Output 렌더링
    - 출력하기 위한 결과를 렌더링한다.
  6. Request 반환
    - 반대 순서로 Interceptors를 통해 request를 반환한다. 반환된 request는 클린업 작업이나 부가 프로세싱을 수행한다.
  7. 결과 표시
    - 마지막으로 컨트롤이 서블릿 컨테이너로 반환된다. 그리고 컨트롤은 사용자의 브라우저로 출력을 전송한다.

이미지: request 프로세싱의 스트럿츠 2 상위 레벨 개요


스트럿츠 2 아키텍쳐

스트럿츠 2는 자바 필터, 자바 빈즈, 리소스 번들, XML 등의 많은 표준 기술을 기반으로 만들어진 매우 고상하고 유연한 프론트 컨트롤러 프레임워크입니다.

모델을 위해, 프레임워크는 JDBC, EJB, Hibernate 등의 데이터 접근 기술을 사용할 수 있고 뷰를 위해, 프레임워크는 JSP, JTL, JSP, Velocity, Templates, PDF, XSLT 등을 통합시킬 수 있다.

예외 처리

스트럿츠 2 프레임워크는 예외 처리자와 후보자를 정의하도록 허용한다.

* 예외 처리자(Exception Handlers)
예외처리자는 전역적이고 지역적인 예외 처리 절차를 정의한다.
프레임워크는 예외를 감지하고 그 때 적절한 메시지와 상세한 예외내용을 표시한다.

* 후보자 (Inspectors)
후보자는 액션의 request-processing lifecycle에 특화되어 사용한다. 후보자는 request의 workflow, validation 등의 일반적인 기능에 적용하기 위해서 설정된다.

스트럿츠 2 아키텍처
아래의 그림은 스트럿츠 2 프레임워크의 아키텍처를 묘사한다 그리고 톰캣과 같은 서블릿 컨테이너에서 request가 어떻게 초기화되는지를 보여준다. 그리고 그것은 표준 필터체인을 통과하게 된다.

이미지: 스트럿츠 2 아키텍처


필터 체인 (Filter Chain)은 아래의 것을 포함한다.

* Action ContextCleanUp Filter:
ActionContextCleanUp Filter는 선택적이다.
SiteMesh 플러그인과 같은 다른 기술과 통합되어 함께 사용해야 할 때 유용하다.

* FilterDispatcher:
다음으로 FilterDispatcher가 호출된다. 이번에는 Action을 invoke를 하는지 안하는지를 결정하기 위해 ActionMapper를 사용한다. 액션이 invoked가 요구된다면, FilterDispatcher는 ActionProxy로 제어를 위임한다.

* ActionProxy:
ActionProxy는 sturts.xml 로 부터 초기화되는 설정 파일 관리자를 도와줍니다. 그 때 ActionProxy는 ActionInvocation을 생성하고 명령 패턴을 구현합니다. ActionInvocation은 (설정되어 있을경우) Interceptors invokes를 수행하고 그 때 action을 invokes합니다. ActionInvocation는 적절한 결과를 조사합니다. 그때 결과가 실행되고 그 결과는 JSP 혹은 템플릿의 렌덩링을 포함합니다.

그러고 나서 Interceptors는 반대의 순서로 다시 실행된다. 마지막으로 response는 web.xml 파일에 설정된 필터를 통해서 돌아온다. 만약 ActionContextCleanUp 필터가 설정되었다면, FilterDispatcher는 ThreadLocal ActionContext를 제거하지 않는다. 만약 ActionContextCleanUp 필터가 나타나지 않는다면 그 때 FilterDispatcher는 모든 ThreadLocals 을 말끔히 제거한다.

이번 섹션에서 스트럿츠 2 프레임워크의 아키텍처에 대해서 배웠다.


Struts 2 는 Struts Action 프레임워크와 WebWork를 융합한 프레임워크입니다. Struts 2.0.1 릴리즈 공지에 따르면 몇가지 특징이 있습니다.

* 단순화된 디자인
인터페이스 대신에 추상클래스를 이용한 프로그래밍은 스트럿츠 1 프레임워크의 디자인 문제 중의 하나인데 스트럿츠 2 프레임워크에서는 해결이 되었습니다. 스트럿츠 2 클래스의 대부분이 인터페이스를 기반으로 되어 있고 핵심 인터페이스는 HTTP에 독립적입니다. 스트럿츠 2 액션 클래스들은 프레임워크에 독립적이고 단순 POJO 처럼 보일 정도로 단순합니다. 프레임워크 컴포넌트들은 느슨하게 결합되도록 시도되었습니다.

* 단순화된 액션
액션은 단순 POJO입니다. execute() 메서드를 가진 어떠한 자바 클래스라도 액션 클래스로서 사용될 수 있습니다. 심지어 항상 인터페이스를 구현할 필요도 없습니다. 액션 클래스를 개발하는 동안 Inversion of Control이 도입됩니다. 이것은 액션을 근원적인 프레임워크에 중립적이게 합니다.

* ActionForm이 없다.
ActionForm의 특징은 스트럿츠 2 프레임워크의 특징이 아닙니다. 직접적으로 프라퍼티에 값을 설정하기 위해서액션에 맛들인 단순한 자바빈즈가 사용됩니다. 더이상 String 프라터티를 사용할 필요가 없습니다.

* 단순한 테스트
스트럿츠 2 액션은 HTTP에 독립적이고 프레임워크에 중립적입니다. 이것은 mock 객체를 재분류하지 않고 스트럿츠 어플리케이션의 테스트를 매우 쉽게 만들어 줍니다.

* 지능적인 기본값
대부분의 환경 요소는 필요에 따라 설정된 기본값을 가집니다. 심지어 필요에 따라 재설정 가능한 XML기반의 기본 설정 파일이 있습니다.

* 향상된 결과값
ActionForward와 다르게, 스트럿츠 2의 결과값은 다양한 형태의 아웃풋을 생성하기 위한 유연성을 제공합니다. 그리고 이것은 response 를 준비하는 것을 도와줍니다.

* 향상된 태그
스트럿츠 2 태그들은 마크업을 다룰 수 있는 스타일 시트를 추가할 수 있습니다. 그러므로 보다 적은 코드를 사용해서 일관성있는 페이지들을 생성할 수 있습니다. 스트럿츠 2 태그들은 보다 유용하고 결과 지향적입니다.
스트럿츠 2 태그 마크업은 근원적인 스타일시트를 변경함으로써 교체될 수 있습니다. 사용자 태그 마크업은 FreeMaker 템플릿을 수정함으로서 변경될 수 있습니다. JSP와 FreeMaker 태그 모두 지원됩니다.

* Annotations 도입
스트럿츠 2의 어플리케이션은  XML 대신에 자바 프라퍼티 설정 같은 자바 5 Annotations 을 사용할 수 있습니다. Annotations 은 XML의 사용을 최소화시켜줍니다.

* Stateful 체크박스
스트럿츠 2 체크박스는 false 값에 대한 특별한 핸들링이 요구되지 않습니다.

* 빠른시작
웹 컨테이너를 재시작 하지 않고 변경된 사항을 적용할 수 있습니다.

* 커스터마이징 컨트롤러
스트럿츠 1은 모듈별로 request 프로세서를 커스터마이징해야 합니다. 스트럿츠 2는 원한다면 액션 단위로 request 핸들링을 커스터마이징 할 수 있습니다.

* 쉬운 Spring과의 통합
스트럿츠 2 액션은 Spring에 대해 알고있습니다. 단지 Spring Beans만 추가만 필요합니다.

* 쉬운 플러그인
스트럿츠 2 확장은 JAR파일을 추가함으로써 이루어집니다. 더이상 수동적인 환경설정이 필요하지 않습니다.

* AJAX 지원
AJAX 테마는 인터렉티브한 어플리케이션을 만드는데 생산성을 향상시켜줍니다.
프레임워크는 어플리케이션에 ajax와 심지어 Dojo를 적용할 수 있도록 태그집합을 제공합니다. 

AJAX 특징은 아래의 것들을 포함합니다.
1.AJAX 클라이언트 사이트 Validation
2.원격 폼 서브빗 지원 (submit 태그와 함께 잘 동작합니다.)
3.부분적인 HTML의 동적 리로딩을 제공하는 향상된 div 탬플릿
4.원격 자바스크립트를 평가하고 로드하는 능력을 제공하는 향상된 템플릿
5.AJAX 탭 패널 구현
6.풍부한 pub-sub 이벤트 모델
7.인터렉티브한 자동 완성 태그

이섹션에서 두개의 프레임워크 사이의 다양한 특징을 비교할 예정이다. 스트럿츠 2.x는 스트럿츠 1.x와 비교하여 매우 단순하다. 스트럿츠 2.x의 엑설런트한 특징 몇가지가 아래와 같다.

1. 서블릿 의존
스트럿츠 1의 액션은 하나의 액션이 invoked될 때 HttpServletRequest과 HttpServletResponse 객체가 execute 메서드를 통과하기 때문에 서블릿 API에 의존성을 가지고 있다. 그러나 스트럿츠 2의 경우에 액션은 컨테이너에 의존적이지 않다. 왜냐하면 액션이 단순한 POJO이기 때문이다. 스트럿츠 2에서 서블릿 컨텍스트는 고립되어 테스트된 액션을 허락하는 단순한 맵으로서 표현됩니다. 필요하다면 스트럿츠 2 액션은 진짜 request와 response에 접근할 수 있습니다. 그러나 다른 아키텍쳐 요소들이 HttpServletRequest나 HttpServletResponse에 직접적으로 접근할 필요를 줄어거나 제거했습니다.

2. Action 클래스들
인 터페이스 기반이 아닌 추상클래스 기반으로 개발된 스트럿츠1의 디자인 관련 이슈들은 스트럿츠2에서 해결이 되었습니다. 스트럿츠1의 Action 클래스들은 프레임웍에 의존적인 기반 추상클래스를 상속받도록 되어 있었지만 스트럿츠2의 Action클래스들은 옵셔널하고 커스텀한 서비스를 적용하기 위해 인터페이스를 구현할 수도 있고 아예 하지 않을 수도 있습니다. 스트럿츠2의 경우 Action 클래스들은 단순 POJO들로 개발되기 때문에 컨테이너에 대한 종속관계가 없습니다. 스트럿츠2는 ActionSupport 클래스를 제공하여 공통적으로 사용되는 인터이스들을 구현할 수 있도록 지원합니다.  그럼에도 불구하고 Action 클래스가 어떤 인터페이스를 구현하도록 요구되지는 않습니다. 어떤 POJO 오브젝트라도 execute 메소드만 존재한다면 스트럿츠2에서 Action 오브젝트로 사용이 가능합니다.

3. 검증
스트럿츠 1과 스트럿츠 2 모두 검증 메서드를 통한 수동 검증을 지원합니다.
스트럿츠 1은 검증 메서드를 액션 폼에서 사용하거나 확장시킨 Commons Validator를 통하여 검증합니다. 
그러나, 스트럿츠2 는 검증메서드와 XWork 검증 프레임워크를 통하여 수동 검증을 지원한다. XWork Validation 프레임워크는 프라퍼티 클래스 타입과 validation 컨텍스트를 위해 정의된 valadations를 사용하여 서브 프라퍼티까지 연결된 검증을 지원한다. 

4.쓰레딩 모델
스트럿츠1에서, 액션 리소스들은 thread-safe하거나 synchronized 되어야만 한다. 그래서 액션들은 singletons이고 thread-safe 이다. 그 액션을 위한 모든 리퀘스트를 처리하기 위한 단 하나의 인스턴스만 존재해야 한다. 
싱글톤 전략은 스트럿츠 1 액션에서 할 수 있는 것에 대한 제한을 두게 되었고 개발을 하기 위해 주의가 요구된다. 그러나 스트럿츠 2에서, 액션 객체는 각각의 리퀘스트에 대해 초기화된다, 그래서 thread-safety 이슈가 없다. (사실, 서블릿 컨테이너들은 각각의 리퀘스트에 대해 버리는 객체를 많이 생성한다, 그리고 하나 이상의 객체는 실행 패널티를 부과하지 않거나 garbage collection에 영향을 주지 않는다.)

5.테스트용이
스트럿츠 1 어플리케이션의 테스트는 조금 복잡하다. 스트럿츠1 액션들을 테스트하기 위한 주요 장애물은 실행 메소드이다. 왜나하면 그것은 서블릿 API를 나타내기 때문이다. 써드파티 확장인 Struts TestCase는 스트럿츠 1을 위한 mock object 집합을 제공한다. 그러나 스트럿츠 2 액션들은 액션을 초기화하고, 프라퍼티를 세팅하고 메소드들을 invoke 함으로써 테스트될 수 있다. Dependency Injection 지원은 또한 테스팅을 보다 쉽게 만든다. 스트럿츠 2의 액션은 간단한 POJO들이고 프레임웍에 독립적이다. 그러므로 스트럿츠2에서의 테스트는 매우 쉽다.

6.입력값 수집
스트럿츠 1은 입력값을 받기 위해서 ActionForm 객체를 사용합니다. 그리고 모든 ActionForm들은 프레임워크에 종속적인 기본 클래스를 확장하는 것이 필요하다. 자바빈즈는 ActionForm으로 사용될 수 없다. 그래서 개발자들은 입력값을 받기 위해 불필요한 클래스들을 생성해야만 한다.
그러나 스트럿츠 2는 Action 프라퍼티(근원적인 프레임워크에 독립적인 입력 프라퍼티)를 사용은 추가적인 입력 객체의 필요성을 제거했다. 그러므로 불필요성을 감소시켰다. 스트럿츠 2에서는 추가적으로, Action 프라퍼티들은 tag라이브러리들을 통해서 웹 페이지로부터 엑세스될 수있다. 스트럿츠 2는 또한 POJO 폼 뿐만아니라 POJO Action 을 지원하며 ActionForm 패턴도 지원한다. 심지어는 비즈니스나 도메인 객체를 포함한 풍부한 객체 타입을 입/출력 객체로서 사용할 수 있다.

7.표현언어
스트러츠1은 JSTL과 통합되어 있습니다. 그리고 JSTL-EL을 사용한다. 스트럿츠 1 EL은 기본 객체를 가집니다. 그러나 상대적으로 컬렉션과 인덱스된 프라퍼티의 지원은 약하다. 스트럿츠 2도 또한 JSTL을 사용한다. 그러나 Object Graphic Notation Language(OGNL)라고 불리우는 보다 강력하고 유연한 표현언어를 지원한다.

8.뷰와 값의 연결
뷰의 영역에서, 스트럿츠 1은 접근하기 위한 페이지 컨텍스트에서 객체(모델 영역에서 진행된) 를 바인드하기 위해 표준 JSP 메카니즘을 사용한다. 그러나 스트럿츠 2는 "ValueStack"이라는 기술을 사용한다. 태그라이브러리는 view와 그것을 렌더링할 객체 타입을 연결해 놓지 않고서 값에 접근할 수 있습니다. ValueStack 전략은 같은 프라퍼티 이름을 가졌지만 타입은 다른 타입의 범위를 넘나들며 view의 재사용을 허가합니다. 

9.형변환
보통, 스트럿츠 1 Actionform 프라퍼티는 모두 String입니다. 스트럿츠1은 형변환시에 Commons-Beanutils를 사용한다.  이 타입 변환기들은 클래스당이며 인스턴스 당으로 설정되지 않는다. 그러나 스트럿츠 2는 형변환시에 OGNL을 사용한다. 프레임워크는 기본적이고 공통적인 객체타입과 프리머티브의 변환기를 포함한다.

10.Action 실행제어
스트럿츠1은 각각의 모듈에 대한 Request Processr를 분리합니다. 그러나 한개의 모듈안에서 모든 액션은 같은 라이프 사이클을 공유해야합니다. 그러나 스트럿츠 2는 Interceptor Stacks을 통해 생성된 각각의 액션에 대해 다른 라이프 사이클의 생성을 지원합니다. 사용자 스택이 생성될 수 있으며 필요하다면 다른 액션을 사용할 있습니다.


이번 섹션에서는 톰캣 컨테이너의 최신버전위에서 스트럿츠 2.0을 다운로드 하고 설치할 것이다. 먼저 개발 서버인 톰캣을 다운로드하고 설정한다. 그리고 스트럿츠 2.0을 다운로드 하고 예제들을 살펴보기 위한 톰캣 서버위에 빈 스트럿츠 어플리케이션을 설치한다.

스트럿츠 2.0 다운로드
스트러츠 다운로드 사이트에 방문한 후 스트럿츠 2.0을 다운로드 받는다.
본 튜토리얼을 위해 2.0.11-all.zip을 다운로드 받는다. 아래는 스트럿츠 다운로드 사이트이다.
주소: http://struts.apache.org/download.cgi
http://struts.apache.org/download.cgi

Struts 2 다운로드


톰캣 다운로드
톰캣 다운로드 사이트에 방문한 후 톰캣 5.5를 다운로드 받는다.
본 튜토리얼을 위해 최신버전의 톰캣(2007.11.27 현재: apache-tomcat-5.5.20.zip)을 다운로드 받는다.
아래는 톰캣다운로드 사이트이다.
주소: http://tomcat.apache.org/download-55.cgi
http://tomcat.apache.org/download-55.cgi

Tomcat 5.5 다운로드


톰캣 실행
본 튜토리얼은 시스템에 자바의 최신버전이 설치되어 있다고 가정합니다. 
다운로드 받은 톰캣의 압축을 풀고 "압축해제폴더 > bin > startup.bat"를 실행시킵니다.
웹 브라우저를 실행시킨 후 http://localhost:8080을 입력하면 아래와 같은 화면이 나오면 된다.
http://localhost:8080

Tomcat 5.5


축하합니다.
이제 여러분은 스트럿츠 2.0을 배우기 위한 톰캣의 최신 버전을 설치하는데 성공하였습니다.
이제 우리는 톰캣 컨테이너 위에 스트럿츠의 빈 어플리케이션과 테스트 어플리케이션을 설치할 것입니다.

톰캣 위에 스트럿츠 2.0 배포판의 압축을 풀고 설치하세요.
struts2-2.6.11-all.zip을 다운로드 받은 후 임의의 폴더에 압축을 해제합니다.
스트럿츠의 빈 어플리케이션을 설치하기 위해서 먼저 struts2-blank-2.0.11을 복사하여 톰켓의 webapps 디렉토리로 붙여넣기 하면 톰캣이 자동으로 어플리케이션을 배치할 것입니다.

* 참고struts2-blank-2.0.11의 위치: 압축해제 폴더\struts-2.0.11-all\struts-2.0.11\apps)

아래는 톰캣서버의 메시지 창입니다.
Tomcat Server Message

Tomcat Server Message


방금 배치한 스트럿츠 어플리케이션을 테스트하기 위해서는 웹브라우저 주소창에 http://localhost:8080/struts2-blank-2.0.11 이라고 입력한다. 그러면 스트럿츠 어플리케이션은 아래와 같이 나타나게 된다.
http://localhost:8080/struts2-blank-2.0.11

스트럿츠 2 예제 어플리케이션


링크를 클릭하여 스트럿츠 예제 어플리케이션을 익혀라.

스트럿츠 2.0 배포판은 또한 실행해볼 수 있는 아래와 같은 샘플 어플리케이션을 포함한다 
  • struts2-mailreader-2.0.11.war
  • struts2-portlet-2.0.11.war
  • struts2-showcase-2.0.11.war

이러한 파일들은 톰캣 서버의 webapps 디렉토리에 복사할 수 있다. 톰캣은 자동으로 이러한 어플리케이션을 배치할 것이며 당신은 이 어플리케이션을 테스트해볼 수 있다.

참고로 어플리케이션의 테스트 주소는 아래와 같다.

http://localhost:8080/어플리케이션이름

이번 섹션에서는 스트럿츠 2 프레임워크를 기반으로 한 Hello World 어플리케이션을 개발할 것이다. 스트럿츠 2 Hello World 어플리케이션은 스트럿츠 2 프레임워크 기반으로 어플리케이션을 개발하기 위한 첫번째 단계이다. 이제 스트럿츠 2 프레임워크에서 Hello World 어플르키에션을 개발하기 위한 단계별 가이드를 제공한다.

튜토리얼은 폴더 구조 생성, 빌드 툴을 사용한 어플리케이션 빌드를 위한 build.xml 파일 생성과 같은 기본 단계들을 포함한다. Java, JSP, 그리고 환경 설정 파일이 이 어플리케이션을 이해하기 위한 선수지식이다.

프로젝트를 위한 폴더구조생성

1단계
스트럿츠 2를 다운로드 한 후 struts2-blank-2.0.11.war파일(만약 당신이 최신버전의 스트럿츠2를 사용한다면 이름은 바뀔것이다.)을 톰캣의 webapps 폴더로 복사한다. struts2-blank-2.0.6.war을 struts2tutorial로 이름을 변경한다. 그리고 톰캣 webapps 폴더에서 압축으르 해제한다. 이제 톰캣을 시작한다. 그리고 웹브라우저를 실행하여 주소창에http://localhost:8080/struts2tutorial을 입력한다. 이제 브라우저는 아래와 같은 것을 보여줄 것이다.


스트럿츠 2 빈 어플리케이션을 성공적으로 설치한 것을 축하한다.

2단계
이제 struts2tutorial\WEB-INF\src과 struts2tutorial\WEB-INF\classes 폴더에 있는 파일들을 지운다. 왜냐하면 이 파일들은 스트럿츠 2 빈 어플리케이션이 생성한 파일들이고 필요없기 때문이다.

3단계
struts2tutorial\WEB-INF\src에 build.xml을 생성하고 아래의 내용을 복사해서 붙여넣는다.
<project name="Struts 2 Tutorial" basedir="../" default="all">
<!-- Project settings -->
<property name="project.title" value="RoseIndia Struts 2 Tutorials"/>
<property name="project.jar.file" value="struts2tutorial.jar"/>

<path id="class.path">

<fileset dir="lib">

<include name="**/*.jar"/>

</fileset>

<fileset dir="libext">

<include name="**/*.jar"/>

</fileset>

</path>

<!-- Classpath for Project -->

<path id="compile.classpath">

<pathelement path ="lib/commons-beanutils.jar"/>

<pathelement path ="lib/commons-digester.jar"/>

<pathelement path ="lib/struts.jar"/>

<pathelement path ="libext/servlet-api.jar"/>

<pathelement path ="libext/catalina-ant.jar"/>

<pathelement path ="classes"/>

<pathelement path ="${classpath}"/>

</path>

<!-- Check timestamp on files -->

<target name="prepare">

<tstamp/>
<copy
file="src/struts.xml"
todir="src/classes"/>


</target>
<!-- Copy any resource or configuration files -->

<target name="resources">

<copy todir="src/classes" includeEmptyDirs="no">

<fileset dir="src/java">

<patternset>

<include name="**/*.conf"/>

<include name="**/*.properties"/>

<include name="**/*.xml"/>

</patternset>

</fileset>

</copy>

</target>

<!-- Normal build of application -->

<target name="compile" depends="prepare,resources">

<javac srcdir="src" destdir="src/classes"
debug="true" debuglevel="lines,vars,source">

<classpath refid="class.path"/>

</javac>

<jar

jarfile="lib/${project.jar.file}"

basedir="src/classes"/>

</target>
<!-- Remove classes directory for clean build -->

<target name="clean"

description="Prepare for clean build">

<delete dir="classes"/>

<mkdir dir="classes"/>

</target>

<!-- Build Javadoc documentation -->

<target name="javadoc"

description="Generate JavaDoc API docs">

<delete dir="./doc/api"/>

<mkdir dir="./doc/api"/>

<javadoc sourcepath="./src/java"

destdir="./doc/api"

classpath="${servlet.jar}:${jdbc20ext.jar}"

packagenames="*"

author="true"

private="true"

version="true"

windowtitle="${project.title} API Documentation"

doctitle="&lt;h1&gt;${project.title}
Documentation (Version ${project.version})&lt;/h1&gt;"

bottom="Copyright &#169; 2002">

<classpath refid="compile.classpath"/>

</javadoc>

</target>

<!-- Build entire project -->

<target name="project" depends="clean,prepare,compile"/>

<!-- Create binary distribution -->

<target name="dist"

description="Create binary distribution">

<mkdir

dir="${distpath.project}"/>

<jar

jarfile="${distpath.project}/${project.distname}.jar"

basedir="./classes"/>

<copy

file="${distpath.project}/${project.distname}.jar"

todir="${distpath.project}"/>



<war

basedir="../"

warfile="${distpath.project}/${project.distname}.war"

webxml="web.xml">

<exclude name="${distpath.project}/${project.distname}.war"/>

</war>

</target>


<!-- Build project and create distribution-->

<target name="all" depends="project"/>

</project>

4단계
struts2tutorial\WEB-INF\ 폴더에 libext 폴더를 생성한 후 최신의 서블릿 API jar (우리의 경우에는 여기)을 복사한 후 이곳에 둔다. 이 라이브러리 파일은 어플리케이션에서 서블릿을 컴파일하기 위해 사용될 것이다.

5단계
이제 struts2tutorial\WEB-INF\src 폴더 아래에 java와 classes 폴더를 생성한다. struts2tutorial\WEB-INF\src\java 폴더는 모든 자바 소스파일이 위치하며 struts2tutorial\WEB-INF\src\classes 폴더는 컴파일된 자바 파일을 저장하기 위해서 ant 빌드툴이 사용하게 될 것이다.

이제 스트럿츠 2 Hello World 어플리케이션을 위한 폴더 구조와 ant 빌드파일이 성공적으로 생성되었다.
다음 섹션에서 JSP, Java 파일, 환경설정 파일을 생성할 것이다. 그리고 스트럿츠 2 Hello World 어플리케이션을 테스트하게 된다.

Struts 2 Tutorial - 08.JSP, Java, 환경설정파일 작성하기

이번 섹션에서는 스트럿츠 2 Hello World 어플리케이션을 위한 JSP, Java, 환경설정파일을 작성할 것입니다.
지금 스트럿츠 2의 struts.xml이 어플리케이션을 설정하기 위해 사용되고 있습니다.

어플리케이션의 이해
어플리케이션은 현재시간과 서버시간과 Hello World 메시지를 표시하는 간단한 어플리케이션입니다.

튜토리얼 홈페이지의 "Run Struts 2 Hello World Application" 링크를 클릭하면, request는 스트럿츠 프레임워크로 보내집니다. 그 때 스트럿츠 프레임워크는 입력을 액션클래스(이 경우에는 Struts2HelloWorld.java)로 보냅니다. 액션이 소멸된 후 결과는 응답을 렌더링하기 위해 "/pages/HelloWorld.jsp"  리소스를 선택한다 

예제에서 액션 클래스와 액션과 결합된 매핑(struts.xml), 그리고 페이지의 세가지 부분의 뷰를 개발해야만 한다. 이러한 세가지 콤포넌트를 생성함으로서 어플리케이션을 모델, 뷰, 컨트롤러로 분리할 수 있습니다.


이 페이지는 브라우저에서 결과를 보여주는데 사용된다.HelloWorld.jsp는 어플리케이션의 뷰의 일부이다. struts2tutorial\pages 폴더에 "HelloWorld.jsp" 를 생성하고 아래 내용을 추가하라.
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>Struts 2 Hello World Application!</title>
</head>
<body>
<h2><s:property value="message" /></h2>
<p>Current date and time is: <b><s:property value="currentTime" /></b>
</body>
</html>

<%@ taglib prefix="s" uri="/struts-tags" %> 는 스트럿츠 라이브러리의 데이타 태그를 선언한다.
스트럿츠 데이터 태그는 동적인 데이터를 표시하는데 사용된다. <s:property value="message" /> 태그와 <s:property value="currentTime" /> 태그는 Struts2HelloWorld 액션 클래스에서 각기 getMessage()와 getCurrentTime()메서드를 호출하고 값은 response 객체에 합쳐진다.

액션 (모델과 상호작용)
이제 Struts2HelloWorld.java를 생성하고 "struts2tutorial\WEB-INF\src\java\net\roseindia" 폴더에 저장하라. 이 액션 클래스는 화면에 표시하기 위한 메시지를 생성한다. 여기 Struts2HelloWorld.java 코드가 있다.

package net.roseindia;
import com.opensymphony.xwork2.ActionSupport;
import java.util.Date;

public class Struts2HelloWorld extends ActionSupport {

   public static final String MESSAGE = "Struts 2 Hello World Tutorial!";

   public String execute() throws Exception {
       setMessage(MESSAGE);
       return SUCCESS;
   }

   private String message;

   public void setMessage(String message){
       this.message = message;
   }

   public String getMessage() {
       return message;
   }

 public String getCurrentTime(){
     return new Date().toString();
 }
}


컨트롤러 설정파일

스트럿츠 2는 어플리케이션을 설정하기 위해서 struts.xml 파일을 사용한다.struts.xml 파일을 생성하고 "struts2tutorial\WEB-INF\src" 디렉토리에 저장한다. 파일의 내용은 아래와 같다.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>

<constant name="struts.enable.DynamicMethodInvocation" value="false" />
<constant name="struts.devMode" value="true" />

<package name="roseindia" namespace="/roseindia" extends="struts-default">

<action name="HelloWorld" class="net.roseindia.Struts2HelloWorld">
<result>/pages/HelloWorld.jsp</result>
</action>

<!-- Add actions here -->
</package>


<!-- Add packages here -->

</struts>

struts.xml 파일은 어플리케이션의 클래스패스에 있어야만 한다. jar 파일에 포함시키던지 어플리케이션의 lib 폴더에 위치시킬 수 있다. 혹은 웹 어플리케이션의 classes 폴더에 위치시킬수 있다. 우리의 어플리케이션은 struts.xml 파일을 jar 파일에 넣는 ant 빌드 툴을 사용하고 있다. 

* struts2tutorial\index.html을 아래와 같이 수정해준다.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
    <META HTTP-EQUIV="Refresh" CONTENT="0;URL=roseindia/HelloWorld.action">
</head>

<body>
<p>Loading ...</p>
</body>
</html>

어플리케이션 빌드

나는 ant 빌드 툴을 이미 설치했다고 가정한다.  ant 빌드 툴을 사용한 이래로 어플리케이션 빌딩이 매우 쉬워졌다.어플리케이션을 빌드하기 위해서 명령프롬프트 창을 열고 웹 어플리케이션 폴더인 "struts2tutorial\WEB-INF\src" 로 이동한 후 "ant"라는 명령어만 실행하면 된다. ant 빌드 툴은 자바 파일을 컴파일 하고 "struts2tutorial.jar"라는 jar 파일을 웹 어플리케이션의 lib 디렉토리에 생성할 것이다. 아래는 ant 빌드툴의 출력이다.

ant 실행 후 메시지

스트럿츠 2 Hello World 웹어플리케이션 테스트
위의 섹션에서 어플리케이션을 컴파일했고 이제 마침내 어플리케이션을 테스트를 할 것이다. 어플리케이션을 테스트하기 위해서 톰캣 서버를 시작하고 웹브라우저 주소창에 http://localhost:8080/struts2tutorial 을 입력하면 아래와 같은 화면이 뜬다.
사용자 삽입 이미지

어플리케이션은 "Struts 2 Hello World Tutorial!" 라는 메시지를 현재 시간과 서버 시간을 함께 출럭한다. 

어플리케이션이 어떻게 작동하는가?

여기 스트럿츠 2 Hello World 어플리케이션이 작동하는 방법을 짧게 설명해놓았다.

1.웹 브라우저에서 웹 서버로 해당 URL(여기서는 http://localhost:8080/struts2tutorial/roseindia/HelloWorld.action)을 위한 요구를 전송한다. 컨테이너는  org.apache.struts2.dispatcher.FilterDispatcher을 통하여 들어온 모든 *.action 요청을 받아들이도록 설정된 스트럿츠 빈 어플리케이션의 기본 web.xml 파일에 의해서 HelloWorld.action의 리소스를 요청합니다. 아래는 web.xml 파일의 설정입니다.

<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
</filter>

<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

2.그러면 프레임워크는 "HelloWorld" 액션의 매핑정보를 찾고 바로 그 때 프레임워크가 적절한 클래스로 초기화되고 실행할 메서드를 호출합니다. 이 경우에 액션 클래스는 Struts2HelloWorld입니다. 아래는 액션과 매핑된 "struts.xml"의 설정입니다. 
<action name="HelloWorld" class="net.roseindia.Struts2HelloWorld">
<result>/pages/HelloWorld.jsp</result>
</action>

3.이제 실행된 메서드는 메시지를 세팅하고 SUCCESS를 반환합니다.
public String execute() throws Exception {
    setMessage(MESSAGE);
    return SUCCESS;
}
프레임워크는 SUCCESS 일 경우 반환되었을 경우 로드 되어야 하는 어떤 페이지를 결정합니다. 여기에서 프레임워크는 컨테이너에게 HelloWorld.jsp를 로딩하라고 알려줍니다. 그리고 출력을 렌더링합니다.
스트럿츠 2 프레임워크에서 액션은 폼과 사용자 리퀘스트를 처리하곤 합니다. 액션의 실행된 메서드는 SUCCESS, ERROR 혹은 INPUT 값을 반환합니다. 그 때 이러한 값들을 기반으로 프레임워크는 컨테이너에게 적절한 결과를 렌더링하고 로딩할 것을 알려줍니다.

4.컨테이너는 HelloWorld.jsp를 처리하고 출력을 생성합니다.

5.그리고 HTML 포맷의 출력이 브라우저로 전송됩니다.

어플리케이션과 소스코드 다운로드
시간을 절약하고 어플리케이션 설정에 노력을 쏟기 위해 튜토리얼의 소스코드와 어플리케이션을 다운로드 하세요.

Struts 2 Tutorial - 09.Struts 2 xml 환경설정파일

이번 섹션에서는 struts.xml 파일을 소개합니다. 이 섹션은 대규모 프로젝트에서 struts.xml 파일을 어떻게 사용하는 것이 좋은가를 설명합니다.

struts.xml 파일
스트럿츠 2 프레임웍은 자신의 리소스를 초기화하기 위해서 설정파일(struts.xml)을 사용합니다.
초기화되는 리소스는 아래의 것들을 포함합니다.

  • 요청이 일어나기전 처리와 요청이 일어난 후 처리하는 인터셉터
  • 비즈니스 로직과 데이터에 접근하는 코드를 호출하는 액션 클래스
  • 자바서버페이지, 벨로시티, 프리메이커 탬플릿을 사용하여 뷰를 표시하기 위해 준비된 결과
런타임시에, 어플리케이션을 위한 하나의 설정파일이 있습니다. 런타임이전에, 기본적으로 struts.xml 문서를 포함하여 하나 혹은 그 이상의 XML 문서에 의해서 설정이 정의됩니다. 패키지, 네임스페이스, 인클루드, 액션, 결과, 인터셉터, 예외과 같이 설정될 수 있는 몇개의 요소가 있다.

struts.xml 파일은 프레임워크를 위한 핵심적인 설정 파일이고 이러한 설정은 웹 어플리케이션의 클래스 패스 안에 있어야만한다.

스트럿츠 2 설정 파일의 특징

  • struts.xml 파일을 작은 파일로 분리하는 것을 허용하며 설정 파일은 필요에 따라 삽입되어 사용될 수 있습니다. 아래에 이것에 대한 샘플이 있습니다.
    <struts>
    .....
    ......
    <include file="file1.xml"/>
    <include file="file2.xml"/>
    .....
    .....
    </struts>
  • struts-plugin.xml파일을 JAR파일 안에 둘 수도 있으며 이것은 웹 어플리케이션에 자동적으로 적용됩니다. 이것은 프로그래머로 하여금 자체적으로 설정파일을 포함한 컴포넌트를 개발할 수 있게 해줍니다.
  • 만약 프레임워크를 프리메이커나 벨로시티와 함께 사용하고 싶다면, 탬플릿들은 클래스패스로부터 로딩될 수 있습니다. 이것은 개발자가 하나의 JAR파일안에 전체 모듈을 패키징할 수 있게 할 수 있게 합니다.


struts.xml 파일의 구조
마지막 섹션에서 Hello World 어플리케이션을 개발하고 테스트했었습니다. 이 마지막 예제에서 사용된 struts.xml 파일이 아래와 같습니다.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>

<constant name="struts.enable.DynamicMethodInvocation" value="false" />
<constant name="struts.devMode" value="true" />

<package name="roseindia" namespace="/roseindia" extends="struts-default">

<action name="HelloWorld" class="net.roseindia.Struts2HelloWorld">
<result>/pages/HelloWorld.jsp</result>
</action>

<!-- Add actions here -->
</package>


<!-- Add packages here -->

</struts>

struts.xml 파일은 스트럿츠 2 문서 정의 (DTD)를 만족시켜야 합니다.

스트럿츠 2 문서 정의 (DTD) 는 struts.xml 파일이 가져야만 하는 구조와 요소에 대한 정보를 제공합니다.

아래는 스트럿츠 2.0의 DTD 입니다.

<!--
Struts configuration DTD.
Use the following DOCTYPE

<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
-->

<!ELEMENT struts (package|include|bean|constant)*>

<!ELEMENT package (result-types?, interceptors?,
default-interceptor-ref?, default-action-ref?, global-results?,
global-exception-mappings?, action*)>

<!ATTLIST package
name CDATA #REQUIRED
extends CDATA #IMPLIED
namespace CDATA #IMPLIED
abstract CDATA #IMPLIED
externalReferenceResolver NMTOKEN #IMPLIED
>

<!ELEMENT result-types (result-type+)>

<!ELEMENT result-type (param*)>
<!ATTLIST result-type
name CDATA #REQUIRED
class CDATA #REQUIRED
default (true|false) "false"
>

<!ELEMENT interceptors (interceptor|interceptor-stack)+>

<!ELEMENT interceptor (param*)>
<!ATTLIST interceptor
name CDATA #REQUIRED
class CDATA #REQUIRED
>

<!ELEMENT interceptor-stack (interceptor-ref+)>
<!ATTLIST interceptor-stack
name CDATA #REQUIRED
>

<!ELEMENT interceptor-ref (param*)>
<!ATTLIST interceptor-ref
name CDATA #REQUIRED
>

<!ELEMENT default-interceptor-ref (param*)>
<!ATTLIST default-interceptor-ref
name CDATA #REQUIRED
>

<!ELEMENT default-action-ref (param*)>
<!ATTLIST default-action-ref
name CDATA #REQUIRED
>

<!ELEMENT global-results (result+)>

<!ELEMENT global-exception-mappings (exception-mapping+)>

<!ELEMENT action (param|result|interceptor-ref|exception-mapping)*>
<!ATTLIST action
name CDATA #REQUIRED
class CDATA #IMPLIED
method CDATA #IMPLIED
converter CDATA #IMPLIED
>

<!ELEMENT param (#PCDATA)>
<!ATTLIST param
name CDATA #REQUIRED
>

<!ELEMENT result (#PCDATA|param)*>
<!ATTLIST result
name CDATA #IMPLIED
type CDATA #IMPLIED
>

<!ELEMENT exception-mapping (#PCDATA|param)*>
<!ATTLIST exception-mapping
name CDATA #IMPLIED
exception CDATA #REQUIRED
result CDATA #REQUIRED
>

<!ELEMENT include (#PCDATA)>
<!ATTLIST include
file CDATA #REQUIRED
>

<!ELEMENT bean (#PCDATA)>
<!ATTLIST bean
type CDATA #IMPLIED
name CDATA #IMPLIED
class CDATA #REQUIRED
scope CDATA #IMPLIED
static CDATA #IMPLIED
optional CDATA #IMPLIED
>

<!ELEMENT constant (#PCDATA)>
<!ATTLIST constant
name CDATA #REQUIRED
value CDATA #REQUIRED
>

만약 어플리케이션의 기능이 struts.xml 파일에 의존적이지 않을 경우 어플리케이션에서 "struts.xml"파일을 완전히 제거하는 것은 가능합니다. 여기에는 주석, "web.xml" 구동 파라미터들, URL 매핑정보들과 같은 다루어질수 있는 몇가지 설정이 있습니다.  여전히 struts.xml 파일에는 전역 결과, 예외처리, 사용자 인터셉텨 스택과 같은 항상 필요한 몇가지 설정들이 있습니다.

struts.xml 탐험하기
<struts> 태그는 struts.xml 파일의 루트 태그입니다. 이것은 pacakge, include, bean, constant 같은 태그들을 포함할 수 있습니다.

1. Package 태그
package는 액션, 결과, 결과형태, 인터셉터 스택 등을 논리적인 설정 단위로 그룹핑하는 방법입니다. 개념적으로 package는 "sub" package 에 의해 오버라이드 될 수 있으며 확장될 수 있고 개인적인 부분을 가지고 있는 객체와 유사합니다. 

<package /> 태그는 인터셉터 스택이나 URL 네임스페이스 같은 공통적인 속성을 공유하는 설정과 함께 그룹핑하는데 사용되곤 합니다. 함수를 조직적으로 분리하는데 유용합니다. 그리고 이것은 별도의 설정 파일로 분리되게 됩니다.

package 요소는 하나의 필수 속성(name)이 있습니다. 이것은 나중에 package를 참조할 때 key로서 사용됩니다. 확장된 요소는 옵션이며 하나의 패키지가 두개 혹은 그이상의 이전 패키지(모든 인터셉터, 인터셉터 스택, 액션 설정)의 환경설정을 상송하는 것을 허락합니다. 

환경설정 파일은 문서를 순차적으로 처리한다는 것을 주목해야 합니다. 그래서 "확장(extend)" 에 의해서 참고된 package는 확장(extended)된 package 보다 상위에 정의되어 있어야만 합니다.

부가적이고 추상적인 요소는 액션 환경설정을 생략할 수 있는 기본 package를 생성합니다.

요소
필수
설명
name 필수 다른 package가 참조하기 위한 key
extends 선택
package는 확장하기로 한 package의 행위를 상속한다 
namespace 선택 URL과 package의 매핑을 제공한다
abstract 선택 패키지를 추상적으로 선언한다 (패키지에 액션 설정이 필요없다.)
1.name - 패키지를 위한 유일한 이름이 주어진다.

2,extends - 이 패키지는 확장하려고 하는 package 의 이름; 확장된 package로 부터 모든 설정 정보 (액션 설정을 포함하여)가 새로운 namespace의 새로운 package에서 이용가능하다.
3.namespace - namespace는 URL과 package의 매핑을 제공한다. 즉, namespace 속성으로 "pack1"과 "pack2"로 정의된 두개의 다른 package에서 URL은 "/webapp/pack1/my.action" 과 "/webapp/pack2/my.action" 처럼 될 수 있다.
4.abstract - 만약 이 속성값이 "true"이면 package가 진짜 설정 그룹이고 설정된 액션은 package 이름을 통하여 엑세스 불가능할 것이다.  이미 설정된 특성들을 사용하기 위해서는 정확한 부모 패키지를 확장해야 한다.

2.include 태그
<include /> 태그는 다른 설정 파일의 포함이 필요한 스트럿츠 2 어플리케이션을 모듈화하기 위해 사용된다.
이것은 포함할 xml 파일의 이름을 제공하는 "file" 이라는 단지 하나의 속성만을 가진다. 이 파일은 "struts.xml" 설정 파일과 정확하게 같은 구조를 가진다. 예를 들면, 재정 어플리케이션의 설정 파일을 분리하기 위해서는 구매, 관리자, 보고서 설정 등을 함께 그룹지을 것을 아래와 같이 선택한다.
<struts>

<include file="invoices-config.xml" />
<include file="admin-config.xml" />
<include file="reports-config.xml" />

</struts>
파일을 포함하는 경우, 순서가 중요하다. 포함된 파일의 정보는 파일안의 include 태그가 위치한 지점으로부터 이용가능하다. 

무조건 포함되어야 하는 파일이 있다. "strutsdefault.xml"과 "struts-plugin.xml" 파일이 있다. 두 개의 파일은 모두 결과 타임, 인터셉터, 인터셉터 스택, 패키지를 위한 기본 설정과 웹 어플리케이션 실행 환경 설정 정보("struts.properties"안에 설정된)를 포함한다. "struts-default.xml"은 스트럿츠2의 핵심설정을 제공하고 "struts-plugin.xml"은 특별한 플러그인에 대한 환경설정을 제공한다는 차이가 있다. 각각의 플러그인 JAR 파일은 실행하는 동안에 로딩되는 "struts-plugin.xml"파일을 보함해야 한다. 

3.bean 태그
대부분의 어플리케이션은 bean 설정을 확장할 필요가 없습니다. bean 요소는 생성되거나 교정하기 위한 자바클래스를 명기하는 클래스 속성을 요구합니다.

bean은

1. 프레임워크의 컨테이너에 의해서 생성되어 내부 프레임워크 객체로 투입되거나
2.스태틱 메소드에 포함된 값

이 될 수 있다.

객체 투입의 첫번째 사용은 일반적으로 타입 어트리뷰트를 동반하며 컨테이너에게 이 객체 인터페이스의 구현체를 알려준다. 값 투입의 두번째 사용은 컨테이너에 의해서 생성되지 않은 객체가 프레임워크 상수를 받아들이도록 하는 것이 좋다. 값 투입을 사용한 객체는 스태틱 어트리뷰트로 정의되어야만 한다.
속성
필수
설명
class 필수 bean 클래스의 이름
type 선택 이 클래스가 구현한 주요 자바 인터페이스
name 선택 이 bean의 유일한 이름; 같은 타입의 다른 bean사이에서 유일해야 한다.
scope 선택 bean의 범위; 기본, 싱글톤, 리퀘스트, 세션, 쓰레드 중에 선택
static 선택 스태틱 메소드에 투입하거나 그렇지 않거나; 타입이 특성화 되면 사실이 아니다.
optional 선택 선택적이거나 아니거나

Bean 샘픔(struts.xml)
<struts>
  <bean type="roseindia.net.ObjectFactory" name="factory" class="roseindia.net.MyObjectFactory" />
...
</struts>

4.constant 태그
constants를 위한 두개의 주요 규칙이 있다.
1.최대 파일 업로드 크기나 스트럿츠 프레임워크의 devMode여부 같은 오버라이드 세팅을 사용한다.
2.주어진 타입의 다양한 구현체중에서 어떤 bean이 선택되었는지 자세히 기술한다.
constant는 다양한 파일안에서 선언될 수 있다. 기본적으로 constant는 아래와 같은 순서대로 검색된다.
이전의 constant는 따라서 나오는 파일에 의해 오버라이드 될 수 있다.
  • struts-default.xml
  • struts-plugin.xml
  • struts.xml
  • struts.properties
  • web.xml

struts.properties 파일은 WebWork에 후방 호환성을 제공한다. struts.properties 파일안에 각각의 엔트리는 상수로서 다루어진다. web.xml 파일에서 FilterDispatcher 초기화 파라미터는 상수로서 로딩된다.

다양한 XML 다양한, 상수 요소는 name과 value의 두개의 요소가 필요하다.

속성
필수설명
name
필수 상수이름
value
필수 상수값

constant 의 예 (struts.xml)
<struts>

<constant name="struts.devMode" value="true" />

...

</struts>

constant 의 예 (struts.properties)
struts.devMode = true
Struts 2 Tutorial - 10.Struts 2 Action 소개
클라이언트의 요청이 액션의 이름과 일치할 때, 프레임워크는 struts.xml 파일로 부터 요청을 처리할 매핑을 사용합니다. 액션 매핑은 보통 
스트럿츠 태그에 의해서 생성됩니다. 액션 태그(struts.xml 파일의 struts 루트 노드에 있는)는 이름을 가지고 액션을 구체화시키고 
프레임워크는 기본 확장과 다른 필요한 요소들을 렌더링합니다.핸들러 클래스의 기본 엔트리 메소드는 액션 인터페이스로 정의된다.

스트럿츠 2 액션 인터페이스

모든 액션은 이 인터페이스로 구현된다. 그리고 그것은 execute() 메서드를 나타낸다. 실제 인터페이스를 구현하지 않고 이 인터페이스에 의해 같은 계약을 유지하는 POJO를 생성하는 것은 자유다.
package com.opensymphony.xwork2;
public interface Action {
//The action execution was a failure.
public final static String ERROR;
//The action execution require more input in order to succeed
public final static String INPUT;
//The action could not execute, since the user most was not logged in
public final static String LOGIN;
// The action execution was successful but do not show a view.
public final static String NONE;
//The action execution was successful.
public final static String SUCCESS;
	//the logic of the action is implemented
	public String execute() throws Exception;
}
액션 인터페이스를 구현하는 것은 옵션이다. 만약 액션이 구현되지 않는다면, 프레임워크는 execute method 를 찾기위해 리플렉션(reflection)을 사용할 것이다. 만약 설정파일에 기술된 execute method 가 없고, 다른 method도 없다면 프레임워크는 예외를 발생시킬 것이다.
스트럿츠2 액션은 POJO(Plain Old Java Objects)로서의 액션클래스를 지향하는 간단한 구현을 이끈다. 액션의 가장 기본적인 사용법은, 항상 하나의 결과를 반환하는 작업을 수행하는 것이다.

그것은 아래와 같다.

public class NewAction {
public String execute() throws Exception {
// do the work
return "success";
}
}

액션 클래스는 어떠한 다른 클래스나 인터페이스를 상속하지 않는다는 것을 주목하라. 액션의 처리과정에서 invoked 메서드는 "execute" 메서드이다. "execute" 메서드는 파라미터가 없고 문자열객체를 반환한다. 그러나 스트럿츠 2 액션에서 문자열 객체와 다른 반환 타입들을 가질 수 있다. 헬퍼 인터페이스를 사용가능합에 따라 (헬퍼 인터페이스는 "success", "none', "error", "input", "login" 과 같은 상수로서 공통적인 결과를 제공한다.)

액션 클래스는 보통 모델로서 행동하고 리퀘스트 객체와 입력 파라미터에 의존한 특별한 비즈니스 로직을 실행한다. 스트럿츠의 이전 버전에서(스트럿츠2.0이전), 액션 클래스는 org.apache.struts.Actions의 확장이고 4개의 파라미터를 테이크하는 Action.execute() 매서드를 오버라이드해야만 한다고 알려져있다.

기본적으로 액션은 HttpServletRequest, HttpServletResponse 과 같은 다양한 객체를 처리하는 것을 의미한다. 그러나 여기에서, 액션 클래스는 어떠한 객체 파라미터도 접근하지 않는다. 여기 중요한 한가지 이슈가 있다. - 작업을 할 때 필요한 어떤 객체를 어떻게 접근할 것인가? 해답은 "inversion of control"이나 "dependency injection" 패턴에 있다.

느슨하게 결합된 시스템을 제공하기 위해서, 스트럿츠 2는 dependency injection 혹은 inversion of control이라고 불리는 기술을 사용한다. dependency injedtion은 constructor injection, interface injection, setter injection에 의해서 구현될 수 있다. 스트럿츠2는 setter injection을 사용한다. 이것은 액션을 이용할 수 있는 객체의 소유를 의미하고,  단지 setter 메서드를 제공하는것이 필요하다.

ActionContext에 요청하거나 ServletRequestAware를 구현함으로써 얻을 수 있는 HttpServletRequest 과 같은 객체가 있다. ServletRequestAware 를 구현하는 것이 선호된다. 비즈니스 객체가 아닌 각각의 객체에 대응하는액션이 구현할 필요가 있는 인터페이스("aware" 인터페이스라고 알려진)가 있다.

inversion of control 을 잘 이해하기 위해서, 액션의 처리가 현재 요구 HttpServletRequest 객체에 접근을 요구하는 곳의 샘플을 살펴보자. dependency injediton 메카니즘은 이 예에서 인터페이스 injection으로 사용된다. interface injection 이름이 함축하고 있는 것처럼 구현이 필요한 인터페이스가 있다. 이 인터페이스는 setter 메서드를 포함한다. 그리고 차례로 액션에 데이터를 제공하기 위해서 사용된다. 이 예에서 우리는 ServletRequestAware interface를 사용하고 있다.
public interface ServletRequestAware {
    public void setServletRequest(HttpServletRequest request);
}

이 인터페이스를 구현할 때, 액션은 조금 변경된다. 그러나 지금 우리가 사용할 HttpServerRequest 객체를 가지고 있다.

public class NewAction implements addDependency {
private HttpServletRequest request;
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
public String execute() throws Exception {
// do the work using the request
return "SUCCESS";
}
}

스트럿츠2에서 액션 인스턴스는 각각의 요구에 대해 생성된다. 이것은 공유되지 않으며 요청이 완전히 처리된 후 폐기된다.

액션 매핑
액션 매핑은 결과 타입, 예외 처리자, 인터셉터 스택의 집합이다. 단지 name 어트리뷰트만 요구된다. 다른 어트리뷰트는 struts.xml 파일을 통해 기술된 패키지 스코프로서 제공될 수 있다.

이 액션을 위한 설정은 아래와 같다.
<action name="new" class="NewAction" >
<result>view.jsp</result>
</action>

"네임" 어트리뷰트는 "/new.action"과 같은 액션을 실행하기 위한 URL 정보를 제공한다. ".action" 확장자는 "struts.properties" 설정파일안에서 설정된다. "클래스" 어트리뷰트는 풀패키지과 실행될 액션의 클래스 이름을 제공한다.

스트럿츠 2는 POJO로서 액션클래스를 처리하고 로직의 결과에 종속적인 다른 결과들을 반환할 수 있다. 다른 결과를 얻기 위해, 클래스를 아래와 같이 변경하는 것이 요구된다.

class NewAction {

public void String execute() throws Exception {
if ( its-ok() ) {
return "login";
} 
else {
return "none";
}}}

여기 두개의 다른 결과를 제공하는 클래스가 있다, 우리는 각각의 경우를 위해 strtus.xml 파일의 액션 태그를 설정해야만 한다. 설정을 아래와 같이 변경하라.

<action name="new"  class="NewAction" >
<result>login.jsp</result>
<result name="none">none.jsp</result>
</action>
Struts 2 Tutorial - 11.Struts 2 Redirect Action
이번 섹션에서는, 스트럿츠2 리다이렉트 액션에 친숙해질 것입니다. 그리고 스트럿츠 2 어플리케이션에서 이것을 사용하는 방법을 배울 
것입니다.

Post 후 Redirect: 이 Post 패턴은 스트럿츠 2에 의해 지원된다. 이것은 웹 어플리케이션의 일반적인 패턴입니다. 액션은 다른 액션으로 리다이렉트욉니다. 리다이렉트액션을 페이지를 표시하기 위해 일반적으로 사용됩니다.

리다이렉트 액션 결과: 이것은 스트럿츠 2에 의해 지원되는 리다이렉트 패텬입니다. ActionMapperFactory가 제공하는 ActionMapper는 지정된 액션을 invoked하는 URL로 브라우저를 리다이렉트하려고 사용합니다. 아래의 스트럿츠 2 어플르케이션에서 이것의 간단한 구현 예제를 볼 수 있습니다.

리다이렉트 동적 파라미터: 액션-리다이렉트는 아래의 파라미터를 가집니다.

    * actionName
    * namespace
    * method
    * encode
    * parse
    * location
    * prependServletContext

리다이렉트 액션을 개발하기 위핸 예제를 만들기 위한 단계를 따라하세요.

Step 1: struts.xml 파일을 생성하고 struts.xml 파일에 아래의 내용을 추가합니다.
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>

    <!-- Rose India Struts 2 Tutorials -->
    <constant name="struts.enable.DynamicMethodInvocation" value="false" />
    <constant name="struts.devMode" value="true" />
<include file="struts-default.xml"/>
    <package name="roseindia" namespace="/roseindia" extends="struts-default">

        
    <!-- Redirect Action -->

     <action name="showAjaxLoginCancelForm">
      <result>/pages/ajaxloginCancel.jsp</result>
     </action>

    <action name="ajaxloginCancel" class="net.roseindia.Login">
      <result  name="input">/pages/ajaxloginCancel.jsp</result>
      <result  name="error">/pages/ajaxloginCancel.jsp</result>
      <result name="cancel" type="redirect">/pages/ajaxloginCancel.jsp</result>
      <result>/pages/ajaxloginsuccess.jsp</result>
    </action>
    
         <!-- Add actions here -->
    </package>


    <!-- Add packages here -->

</struts>

Step 2 : 입력 폼을 생성합니다.

ajaxloginCancel.jsp

<%@ taglib prefix="s" uri="/struts-tags"%>
<html>
  <head>
    <s:head theme="ajax" debug="true"/>
  </head>
  <body>
    <s:div id="loginDiv" theme="ajax">
    <div style="width: 300px;border-style: solid">
      <s:form action="ajaxloginCancel"  validate="true">
        <tr>
          <td colspan="2">
            Login
          </td>
        </tr>
        <tr>
          <td colspan="2">
            <s:actionerror />
            <s:fielderror />
          </td>  
          <s:textfield name="username" label="Login name"/>
          <s:password name="password" label="Password"/>
          <s:submit value="Submit" theme="ajax" targets="loginDiv" notifyTopics="/ajaxloginCancel"/>
          <s:submit action="showAjaxLoginCancelForm" value="Cancel" onclick="form.onsubmit=null"/>
          
      </s:form>
    </div>
    </s:div>
  </body>
</html>

Step 3 : 액션 클래스를 생성합니다.
Login.java

package net.roseindia;
import com.opensymphony.xwork2.ActionSupport;
import java.util.Date;


/**
 * <p> Validate a user login. </p>
 */
public  class Login  extends ActionSupport {


    public String execute() throws Exception {
    if(!getUsername().equals("Admin") || !getPassword().equals("Admin")){
            addActionError("Invalid user name or password! Please try again!");
            return ERROR;
    }
    if(getUsername().equals("Admin") || getPassword().equals("Admin")){
      return SUCCESS;
    }else{
      return NONE;
    }
  }


    // ---- Username property ----

    /**
     * <p>Field to store User username.</p>
     * <p/>
     */
    private String username = null;


    /**
     * <p>Provide User username.</p>
     *
     * @return Returns the User username.
     */
    public String getUsername() {
        return username;
    }

    /**
     * <p>Store new User username</p>
     *
     * @param value The username to set.
     */
    public void setUsername(String value) {
        username = value;
    }

    // ---- Username property ----

    /**
     * <p>Field to store User password.</p>
     * <p/>
     */
    private String password = null;


    /**
     * <p>Provide User password.</p>
     *
     * @return Returns the User password.
     */
    public String getPassword() {
        return password;
    }

    /**
     * <p>Store new User password</p>
     *
     * @param value The password to set.
     */
    public void setPassword(String value) {
        password = value;
    }

}

Step 4 : 적절한 validator를 생성한다.
validation.xml 포맷은 <ActionClassName>-validation.xml 이거나 <ActionClassName>-<ActionAliasName>-validation.xml 중에 하나이다.

Login-validation.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC 
      "-//OpenSymphony Group//XWork Validator 1.0.2//EN" 
      "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
      
<validators>
  <field name="username">
    <field-validator type="requiredstring">
      <param name="trim">true</param>
      <message>Login name is required</message>
    </field-validator>
  </field>
  <field name="password">
    <field-validator type="requiredstring">
      <param name="trim">true</param>
      <message>Password is required</message>
    </field-validator>
  </field>
</validators>

정확한 사용자 이름과 패스워드를 입력하면 사용자는 ajaxloginsuccess.jsp 페이지를 볼 수 있다.

ajaxloginsuccess.jsp
<html>
  <head>
    <title>Login Success</title>
  </head>
  <body>
    <p align="center"><font color="#000080" size="5">Login Successful !</font></p>
    <h1> Welcome to <%=request.getParameter("username")%>  </h1>
  </body>
</html>

출력:

어플리케이션이 실행(http://localhost:8080/struts2tutorial/roseindia/showAjaxLoginCancelForm.action)되면 아래와 같은 결과를 보여줍니다.
http://localhost:8080/struts2tutorial/roseindia/showAjaxLoginCancelForm.action

http://localhost:8080/struts2tutorial/roseindia/showAjaxLoginCancelForm.action



아무것도 입력하지 않고 "Submit"버튼을 클릭하면 아래와 같은 결과를 얻을 수 있다.
http://localhost:8080/struts2tutorial/roseindia/showAjaxLoginCancelForm.action

http://localhost:8080/struts2tutorial/roseindia/showAjaxLoginCancelForm.action


만약 "Cancel"버튼을 클릭하면 리다이렉트액션이 실행되고 아래의 결과를 제공한다.
http://localhost:8080/struts2tutorial/roseindia/ajaxloginCancel.action

http://localhost:8080/struts2tutorial/roseindia/ajaxloginCancel.action

Struts 2 Tutorial - 12.Login 어플리케이션 개발
스트럿츠2 로그인 어플리케이션 개발하기
이번 장에서, 우리는 스트럿츠 2 프레임워크 기반으로 로그인 어플리케이션을 개발할 것이다. 우리의 로그인 어플리케이션은 데이터베이스와 연동되어 사용자를 확인하지 않는다. 대신에 로그인 이름과 패스워드(사용자: Admin, 패스워드: Admin)가 액션 클래스안에 하드코딩된 값으로 확인한다.

어플리케이션 작업
  1. 입력을 받기 위한 로그인 페이지가 표시됩니다.
  2. 사용자이름과 패스워드를 입력하고 "Login" 버튼을 클릭합니다.
  3. 액션클래스에서 사용자 검증이 끝나고 사용자가 사용자이름/패스워드로 Admin/Admin를 입력했다면, 성공페이지가 표시됩니다. 그렇지 않다면 에러메시지가 화면에 표시됩니다.
어플리케이션 개발단계
스트럿츠2 프레임워크를 사용하여 로그인 페이지를 개발하는 간단하고 쉬운 방법이 있습니다.

1.로그인폼 개발
어플리케이션의 GUI에는 로그인 폼(login.jsp)과 성공 메시지 페이지(loginsuccess.jsp)가 있습니다.
login.jsp 는 사용자에게 로그인페이지를 표시합니다. 우리 어플리케이션에서는 "webapps\struts2tutorial\pages\" 폴더에 저장됩니다. 아래는 login.jsp 의 코드입니다.

<%@ taglib prefix="s" uri="/struts-tags" %>
      <html>
      <head>
      <title>Struts 2 Login Application!</title>

      <link href="<s:url value="/css/main.css"/>" rel="stylesheet" type="text/css"/>

      </head>
      <body>
      <s:form action="doLogin" method="POST">
      <tr>
      <td colspan="2">
      Login
      </td>

      </tr>

        <tr>
         <td colspan="2">
               <s:actionerror />
               <s:fielderror />
         </td>
        </tr>

      <s:textfield name="username" label="Login name"/>
      <s:password name="password" label="Password"/>
      <s:submit value="Login" align="center"/>

      </s:form>

      </body>

      </html>

아래의 코드
<s:actionerror />
<s:fielderror />
는 액션 에러들와 필드 검증에러를 표시한다.

아래의 코드
<s:form action="doLogin" method="POST">
는 어플리케이션을 위한 html 폼을 생성한다.

아래의 코드
<s:textfield name="username" label="Login name"/>
<s:password name="password" label="Password"/>
는 로그인 이름과 패스워드 필드를 생성한다.

submit 버튼은 <s:submit value="Login" align="center"/> 코드가 생성한다.

어플리케이션이 실행되면 아래의 html 코드가 생성된다.
      <html>
          <head>
              <title>Struts 2 Login Application!</title>

              <link href="/struts2tutorial/css/main.css" rel="stylesheet"
                type="text/css"/>
                
          </head>
          <body>

      <form id="doLogin" name="doLogin" onsubmit="return true;" 
      action="/struts2tutorial/roseindia/doLogin.action" method="POST">
      <table class="wwFormTable">
                  
       <tr>
             <td colspan="2">
                 Login
             </td>

         </tr>

         <tr>
          <td class="tdLabel"><label for="doLogin_username" class="label">
           Login name:</label>
          </td>
          <td><input type="text" name="username" value="" id="doLogin_username"/>
         </td>
        </tr>

       <tr>
          <td class="tdLabel"><label for="doLogin_password" class="label">
          Password:</label></td>
          <td><input type="password" name="password" id="doLogin_password"/>
      </td>
      </tr>

       <tr>
          <td colspan="2"><div align="center"><input type="submit" 
           id="doLogin_0" value="Login"/>
      </div></td>
      </tr>
      </table></form>
          </body>

      </html>

위의 생성된 html 코드를 보면 스트럿츠 2가 자동으로 form과 html 테이블과, label의 html 요소들을 생성한다는 것을 알 수 있다. 이것은 스트럿츠 1.x와 비교되는 또 다른 큰 특징이다.

loginsuccess.jsp 페이지는 사용자가 성공적으로 로그인을 할 때 로그인 성공 메시지를 표시한다.
아래는 loginsuccess.jsp의 소스이다.
      <html>

      <head>

      <title>Login Success</title>

      </head>

      <body>

      <p align="center"><font color="#000080" size="5">Login Successful</font></p>

      </body>

      </html>

2.액션클래스 개발
이제 로그인 요청을 처리할 액션 클래스를 개발해보자. 스트럿츠 2에서는 액션 인터페이스를 구현하는 것이 필수적이지 않다. 실행 서명을 가진(with execute signature) 어떠한 POJO 객체라도 스트럿츠 2에서 사용될 수 있다. 스트럿츠 2 프레임워크는 일반적으로 사용되는 인터페이스를 구현한 기본 ActionSupport 클래스를 제공합니다. 우리의 액션 클래스(Login.java)에서 우리는 ActionSupport 인터페이스를 구현합니다. 우리의 "Login.java"는 "webapps\struts2tutorial\WEB-INF\src\java\net\roseindia" 폴더에 저장됩니다.
아래는 Login.java 액션 클래스의 소스입니다.
      package net.roseindia;
      import com.opensymphony.xwork2.ActionSupport;
      import java.util.Date;


      /**
       * <p> Validate a user login. </p>
       */
      public  class Login  extends ActionSupport {


          public String execute() throws Exception {
              System.out.println("Validating login");
          if(!getUsername().equals("Admin") || !getPassword().equals("Admin")){
                  addActionError("Invalid user name or password! Please try again!");
                  return ERROR;
          }else{
            return SUCCESS;
          }
        }


          // ---- Username property ----

          /**
           * <p>Field to store User username.</p>
           * <p/>
           */
          private String username = null;


          /**
           * <p>Provide User username.</p>
           *
           * @return Returns the User username.
           */
          public String getUsername() {
              return username;
          }

          /**
           * <p>Store new User username</p>
           *
           * @param value The username to set.
           */
          public void setUsername(String value) {
              username = value;
          }

          // ---- Username property ----

          /**
           * <p>Field to store User password.</p>
           * <p/>
           */
          private String password = null;


          /**
           * <p>Provide User password.</p>
           *
           * @return Returns the User password.
           */
          public String getPassword() {
              return password;
          }

          /**
           * <p>Store new User password</p>
           *
           * @param value The password to set.
           */
          public void setPassword(String value) {
              password = value;
          }

      }

3.액션매핑설정 (struts.xml)
이제 우리는 struts.xml 파일에 액션매핑을 만들것입니다. 아래의 코드를 struts.xml 파일에 추가하세요.
      <action name="showLogin">
      <result>/pages/login.jsp</result>
      </action>

      <action name="doLogin" class="net.roseindia.Login">
      <result name="input">/pages/login.jsp</result>
      <result name="error">/pages/login.jsp</result>
      <result>/pages/loginsuccess.jsp</result>
      </action>

위에 매핑된 "showLogin" 액션은 로그인 페이지를 표시하는데 사용되고 "doLogin"은 액션 클래스(Login.java)를 사용하여 사용자를 검증한다.

4.CSS 파일 (main.css)
이 css 파일은 로그인 폼의 프리젠테이션을 높이기 위해 사용됩니다. main.css는 "\webapps\struts2tutorial\css" 폴더에 저장됩니다. 아래는 main.css의 코드입니다.
      @CHARSET "UTF-8";

      body {
      font: 12px verdana, arial, helvetica, sans-serif;
      background-color:#FFFFFF;
      } 

      table.wwFormTable {
      font: 12px verdana, arial, helvetica, sans-serif;
      border-width: 1px;
      border-color: #030;
      border-style: solid;
      color: #242;
      background-color: #ada;
      width: 30%;
      margin-left:35%;
      margin-right:35%;
      margin-top:15%;
      } 

      table.wwFormTable th {
      }

      table.wwFormTable tr td {
      background-color: #dfd;
      margin: 5px;
      padding: 5px;
      }

      .tdLabel {
      /*
      border-width: 1px;
      border-color: #afa;
      border-style: solid;
      */
      font-weight: bold;
      align: top;
      } 

      .label {
      } 

      .errorMessage {
      color: red;
      font-size: 0.8em;
      } 

      #headerDiv {
      border-style: solid;
      border-width: 1px 1px 0px;
      border-color: black;
      padding: 5px;
      background-color: #7a7;
      /* height: 22px; */
      height: 1.8em;
      /* margin-bottom: 12px; */
      }

      #buttonBar {
      border-width: 0px 1px 1px;
      border-style: solid;
      border-color: black;
      color: white;
      margin-bottom: 12px;
      background-color: #7a7;
      height: 1.6em;
      padding: 5px;
      }

      #appName {
      color: white;
      font-size: 1.8em;
      }

      #pageTitle {
      font-size: 1.4em;
      color: #dfd;
      clear: none;
      }

      #appName, #pageTitle {
      float: right;
      }

      #menuContainer {
      float: left;
      }

      #brandingContainer {
      float: right:
      text-align: right;
      }

아래는 http://localhost:8080/struts2tutorial/roseindia/showLogin.action 의 결과입니다.
http://localhost:8080/struts2tutorial/roseindia/showLogin.action

http://localhost:8080/struts2tutorial/roseindia/showLogin.action

아래는 패스워드를 잘못입력했을 때의 화면입니다.
패스워드 틀림

패스워드 틀림

아래는 아무것도 입력하지 않고 Login 버튼을 클릭했을 때의 화면입니다.
입력값 없이 Login 버튼 클릭

입력값 없이 Login 버튼 클릭


다음 섹션에서, 우리는 로그인 어플리케이션에 검증을 추가하는 방법을 배웁니다.
Struts 2 Tutorial - 13.로그인 어플리케이션에 Validation 추가
로그인 어플리케이션 검증
이번 섹션에서, 우리는 로그인 어플리케이션을 검증하기 위한 코드를 작성할 것이다. 이 섹션이 완료된 후, 스트럿츠 2 프로젝트를 위한 검증 코드를 작성할 수 있게 될 것이다. 이 섹션에 정의된 개념은 매우 설명적이여서 학습자들이 스트럿츠 2 프레임워크에서 그들의 기술을 빠르게 개발할 수 있게 한다.

스트럿츠 2는 웹기반의 어플리케이션을 빠르게 개발하기 위한 많은 기능을 제공하는 매우 고상한 프레임워크이다. 여기에서 당신은 스트럿츠 2에서 배우 쉽게 폼 검증 코드 작성 방법을 배울 것이다.

로그인 어플리케이션의 검증을 위한 자바 스크립트는 jsp 페이지나 액션 클래스에 포함될 수 있다. 그러나 스트럿츠 2는 당신의 필드를 자동으로 검증하는 매우 쉬운 다른 방법을 제공한다. 당신은 클라이언트 사이트 스크립트를 생성하기 위해 심지어 같은 설정 파일을 사용할 수도 있다. (다음 섹션에서, 우리는 클라이언트 사이트 검증 코드를 생성하는 방법을 살펴볼 것이다.)

스트럿츠 2 검증 프레임워크는 xml 기반의 설정 파일을 사용합니다. 파일 이름은 <Your action class> -validation.xml 형태가 되어야만 합니다. 우리의 경우, 우리의 액션 클래스 이름이 Login.java 이므로 우리의 검증 설정 파일은 Login-validation.xml 가 되어야 합니다. Login-validation.xml 는 "webapps\struts2tutorial\WEB-INF\src\java\net\roseindia" 폴더에 저장될 것입니다. 아래는 Login-validation.xml  파일의 내용입니다.
<?xml version="1.0" encoding="UTF-8"?>

        <!DOCTYPE validators PUBLIC 

          "-//OpenSymphony Group//XWork Validator 1.0.2//EN" 

          "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">

        <validators>

    <field name="username">

        <field-validator type="requiredstring">

            <param name="trim">true</param>

            <message>Login name is required</message>

        </field-validator>

    </field>

    <field name="password">

        <field-validator type="requiredstring">

            <param name="trim">true</param>

            <message>Password is required</message>

        </field-validator>

    </field>

        </validators>

위의 설정파일에서 필드 이름은 액션폼 프라퍼티와 대응한다. username과 password 요소를 위해 requiredstring 검정이 적용되며, <message>....</message> 태그 에 있는 메시지가 검증이 실패했을 경우를 표시할 때 사용됩니다.

어플리케이션 컴파일
어플리케이션을 컴파일 하기 위해서 "\webapps\struts2tutorial\WEB-INF\src"로 이동한 후 ant 명령어를 입력하라. ant 도구는 어플리케이션을 컴파일 할 것이다.

index.html 에 링크 추가
마지막으로 index.html에 로그인 폼으로 접근하기 위한 링크를 추가하라.
<ul>
<li><a href="roseindia/showLogin.action">Login Application</a></li>
</ul>

다음 섹션에서 우리는 어플리케이션을 실행하고 테스트하게 된다.
Struts 2 Tutorial - 14.실행 및 테스트
스트럿츠2 로그인 예제 실행
이번 섹션에서 우리는 톰캣 6.0 서버위에서 예제를 실행해보고 그것이 어떻게 작동하는지 체크해볼 것이다.

톰캣 실행
톰캣을 실행하기 위해, bin 폴더로 이동한 후 startup.bat 파일을 더블클릭하라, startup.bat 는 톰캣을 실행시켜줄 것이다.

어플리케이션 테스트
어플리케이션을 테스트하기 위해 http://localhost:8080/struts2tutorial/ 를 입력하라. 아래의 화면을 볼 수 있을 것이다.
http://localhost:8080/struts2tutorial/

http://localhost:8080/struts2tutorial/


이제 "Login Application"을 클릭하면 아래와 같은 화면을 볼 수 있다.
사용자 삽입 이미지

이제 Login 버튼을 클릭해보자. 아래와 같이 에러 화면이 표시될 것이다.
사용자 삽입 이미지
이제 로그인 이름으로 Admin을 입력한 후 Login 버튼을 클릭하면 아래와 같은 화면이 표시된다.
사용자 삽입 이미지
이제 Admin을 제외한 패스워드를 입력해보자. 아래와 같은 에러 화면이 나타날 것이다. 이 에러는 실제로 액션 클래스가 생성한 것이다.
사용자 삽입 이미지
이제 Admin으로 패스워드를 입력하고 Login 버튼을 클릭해보자. 아래와 같은 환영메시지가 표시될 것이다.
사용자 삽입 이미지
축하한다. 이제 당신은 스트럿츠 2 로그인 어플리케이션을 성공적으로 개발했고 테스트했다. 다음 섹션에서 우리는 스트럿츠 2 검증 프레임워크를 사용하여 클라이언트 사이트 자바 스크립트를 어떻게 추가하는 지를 보여줄 것이다.
Struts 2 Tutorial - 15.스트럿츠2에서의 클라이언트측 검증
이번 섹션에서, 우리는 클라이언트 측의 검증을 위한 자바 스크립트 코드를 생성하는 코드를 작성하는 방법을 알 수 있을 것입니다. 이전의 섹션에서 
우리는 서버측 검증을 위한 Login-validator.xml 서렁 파일을 개발했습니다. 이번 섹션에서 우리는 클라이언트측 자바 스크립트를 
생성하기 위해 똑같은 Login-validator.xml 파일을 사용할 것입니다.

JSP 페이지 개발
아래는 login jsp (loginClientSideValidation.jsp) 페이지 코드입니다.
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>Struts 2 Login Application!</title>

<link href="<s:url value="/css/main.css"/>" rel="stylesheet"
type="text/css"/>

</head>
<body>


<s:form action="doLoginClientSideValidation" method="POST" validate="true">

<tr>
<td colspan="2">
Login
</td>

</tr>

<s:actionerror />
<s:fielderror />

<s:textfield name="username" label="Login name"/>
<s:password name="password" label="Password"/>
<s:submit value="Login" align="center"/>

</s:form>

</body>

</html>

<s:form tag...> 안에 validate="true" 를 추가한 것을 주목하라. 이것이 우리가 해야할 유일한 작업이고 나머지작업은 스트럿츠 검증 프레임워크가 할 일이다. 검증 프레임워크는 클라이언트 측에서 폼을 검증하기 위한 자바스크립트를 생성한다.

struts.xml 변경
struts.xml 파일에 아래의 코드를 추가하라.
<action name="showLoginClientSideValidation">
<result>/pages/loginClientSideValidation.jsp</result>
</action>

<action name="doLoginClientSideValidation" class="net.roseindia.Login">
<result name="input">/pages/loginClientSideValidation.jsp</result>
<result name="error">/pages/loginClientSideValidation.jsp</result>
<result>/pages/loginsuccess.jsp</result>
</action>

doLoginClientSideValidation 가 검증 요청을 다루는 반면에 showLoginClientSideValidation 액션은 로그인 폼을 표시한다.

index.html 에 링크 추가
마지막으로 우리는 index.html에 클라이언트측 검증을 테스트하기 위한 로그인 폼으로 접근하기 위한 링크를 추가한다.
<ul>
<li><a href="roseindia/showLoginClientSideValidation.action">Login Application (Client Side Validation)</a></li>
</ul>

클라이언트 측 검증 테스트
톰캣을 실행시키고 http://localhost:8080/struts2tutorial/ 를 입력하라. 브라우저에 아래와 같이 표시될 것이다.
http://localhost:8080/struts2tutorial/

http://localhost:8080/struts2tutorial/


이제 "Login Application (Client Side Validation)" 링크를 클릭하자. 그러면 아래와 같은 화면이 표시될 것이다.
사용자 삽입 이미지

아무것도 하지 않은 상태에서 "Login" 버튼을 클릭해보자. 아래와 같이 자바스크립트가 에러메시지를 보여줄 것이다.
사용자 삽입 이미지

이제 "Login Name"을 입력하고 "Login" 버튼을 클릭하자. 어플리케이션이 아래와 같은 에러를 보여줄 것이다.
사용자 삽입 이미지

자바스크립트 코드 생성 실험

프레임워크에 의해 아래와 같은 html 코드가 생성된다.
<html>

<head>

<title>Struts 2 Login Application!</title>

<link href="/struts2tutorial/css/main.css" rel="stylesheet"

type="text/css"/>
</head>

<body>
<script src="/struts2tutorial/struts/xhtml/validation.js"></script>
<form namespace="/roseindia" id="doLoginClientSideValidation" name="doLoginClientSideValidation" onsubmit="return validateForm_doLoginClientSideValidation();" action="/struts2tutorial/roseindia/doLoginClientSideValidation.action" method="POST">

<table class="wwFormTable">

<tr>

<td colspan="2">

Login

</td>

</tr>

<tr>

<td class="tdLabel"><label for="doLoginClientSideValidation_username" class="label">Login name:</label></td>

<td

><input type="text" name="username" value="" id="doLoginClientSideValidation_username"/>

</td>

</tr>

<tr>

<td class="tdLabel"><label for="doLoginClientSideValidation_password" class="label">Password:</label></td>

<td

><input type="password" name="password" id="doLoginClientSideValidation_password"/>

</td>

</tr>

<tr>

<td colspan="2"><div align="center"><input type="submit" id="doLoginClientSideValidation_0" value="Login"/>

</div></td>

</tr>

 

</table></form>

 

 

<script type="text/javascript">

function validateForm_doLoginClientSideValidation() {

form = document.getElementById("doLoginClientSideValidation");

clearErrorMessages(form);

clearErrorLabels(form);

var errors = false;

// field name: username

// validator name: requiredstring

if (form.elements['username']) {

field = form.elements['username'];

var error = "Login name is required";

if (field.value != null && (field.value == "" || field.value.replace(/^\s+|\s+$/g,"").length == 0)) {

addError(field, error);

errors = true;

}

}

// field name: password

// validator name: requiredstring

if (form.elements['password']) {

field = form.elements['password'];

var error = "Password is required";

if (field.value != null && (field.value == "" || field.value.replace(/^\s+|\s+$/g,"").length == 0)) {

addError(field, error);

errors = true;

}

}

return !errors;

}

</script>

</body>

</html>
위의 코드에서, 당신은 클라이언트측 검증을 위해 생성된 자바스크립트 코드와 validateForm_doLoginClientSideValidation() 함수를 볼 수 있다.

여기까지입니다. 더 많은 원문을 보시려면 그곳으로 가세요 ^^

참조> http://wholic.tistory.com/52