반응형

Struts
웹 애플리케이션을 구현할 때 사용하는 오픈 소스 프레임웍인 Struts는 대중적인 디자인 패러다임에 근거하고 있다. 이 프레임웍은 Java Servlets, JavaBeans, ResourceBundles, XML 같은 표준 기술을 바탕으로 구현되어 유연하고 확장성 있는 컴포넌트를 제공한다. Struts는 Controller 레이어를 ActionServlet 의 형태로 구현하고 JSP 태그 라이브러리를 사용하여 View 레이어를 구현할 것을 권장한다. 또한, Struts는 Action 클래스를 통해 Model 레이어 주변에 래퍼를 제공한다. 그림 1은 Model-View-Controller 디자인에 기반한 Struts 프레임웍이다.

그림 1. Struts와 MVC
Struts and MVC

Struts 컴포넌트 개관
우선 Struts 컴포넌트를 설명하고 웹 애플리케이션 개발시 역할을 설명하겠다.


Action

애플리케이션의 모든 Action 은 Struts의 org.apache.struts.action.Action를 를 확장한다. 이 Action 클래스는 애플리케이션의 Model 레이어로의 인터페이스를 제공하면서 비즈니스 로직 주변의 래퍼로서 작동한다. 각 Action 클래스는 각자의 케이스 스팩(case-specific) 구현을 perform() 메소드에 제공해야 한다. perform() 메소드는 언제나 ActionForward의 값을 리턴한다.


ActionForm

애플리케이션의 모든 ActionForm은 Struts의 org.apache.struts.action.ActionForm을 확장한다. ActionForms 은 요청 매개변수들을 캡슐화 및 유효화하는 단순한 JavaBean이다. 요청 데이터를 유효화하기 위해 ActionFormvalidate() 메소드는 케이스 스팩의 구현을 제공해야 한다. ActionForm은 요청 데이터의 캐리어로서 Action 클래스에 작용한다. JSP 객체는 각각의 ActionForm 을 합하여 애플리케이션의 View 레이어를 만든다. JSP 객체의 거의 모든 폼(form) 필드는 이에 상응하는 ActionForm의 애트리뷰트로 매핑한다.

JSP 커스텀 태그 라이브러리
JSP 커스텀 태그 라이브러리는 태그로 표현되는 액션들의 모음이다. 이것은 JSP Specification 1.1의 강력한 기능이다. 프리젠테이션 티어를 다른 애플리케이션 티어들과 분리할 수 있다. 이 라이브러리는 사용이 쉽고 XML과 같은 방식으로 읽을 수 있다. 자바 스크립틀릿의 사용을 최소화 함으로서 JSP 컴포넌트를 쉽게 관리할 수 있다. Struts가 제공하는 JSP 태그에는 HTML, 로직, 빈 태그들이 포함된다.


ActionErrors

예외 핸들링을 지원할 때 ActionError를 사용한다. ActionError는 애플리케이션 예외를 잡아 View 레이어로 보낸다. 각각은 ActionError의 모음이다. ActionError는 에러 메시지들을 캡슐화 하면서 Presentation 레이어의 </html:errors>ActionError 컬렉션의 모든 에러 메시지들로 렌더링한다.


Best Practice 1. 다중 ActionForm을 통한 데이터 재사용

Struts 컴포넌트에 익숙해졌으니 이제 프레임웍을 활용하는 방법을 설명하겠다. 우선 Struts는 모든 JSP 객체를 ActionForm과 연합할 것을 권장한다. 스크린에 나타난 데이터를 캡슐화 하는 것이다.ActionForm에서 찾은 부속 메소드를 사용하여 JSP 객체에 있는 폼(form) 데이터에 액세스한다. Listing 1은 View 레이어에서 ActionForm 의 일반적이 사용법이다.

Listing 1. JSP에서 ActionForm 사용하기
   <html:form action="/bp1">   <html:text  property="attrib1" />   </html:form >

"BP1AForm" 이라고하는ActionForm에는 attrib1 애트리뷰트를 비롯하여 게터(getter)와 세터(setter) 메소드도 포함되어 있다. 설정 파일인 struts-config.xml에서 "/bp1" 액션은 name 애트리뷰트를 사용하여 bp1AForm 으로 매핑된다. 이것은 JSP에 데이터 디스플레이를 돕는다.

Best Practice 1을 구현할 때 Struts는 다음의 두 가지를 권장한다:

  1. BP1AForm의 애트리뷰트 서브셋을 형성하고있는 애트리뷰트로 JavaBean (BP1BForm) 을 만들고 아울러 이 애트리뷰트의 게터와 세터 메소드도 만든다.
  2. 빈과 BP1AForm을 결합하여 BP1AForm 의 애트리뷰트를 BP1BForm 빈으로 대체한다. 이제 BP1BForm을 통해 BP1AForm 의 애트리뷰트 서브셋에 액세스 할 수 있다. (Listing 2)
Listing 2. JSP의 폼(form) 애트리뷰트에 액세스하기
   <html:form action="/bp1">   
<bean:define name="bp1AForm" property="bp1BForm" id="bp1B"
type="com.ibm.dw.webarch.struts.BP1BForm" />
<html:text name="bp1B" property="subsetAtt1" />
</html:form >

기억하세요!
이 Best Practice 1의 주요 장점은 애트리뷰트 세트에 액세스하기 위해 다중 ActionForm이 필요할 때 이를 사용할 수 있다는 것이다. 다음은 기억해야 할 점이다:

  • Struts는<bean:define/> 태그를 구현한다.
  • <%@ taglib uri="struts-bean.tld" prefix="bean" %> 코드가 struts-bean.tld를 가르킬때 <bean:define/> 태그는 JSP 컴포넌트에서 작동을 시작한다.
  • ActionForm을 확장하는 BP1AForm의 밸리데이션 프레임웍은 BP1BForm의 데이터를 반드시 유효화해야 한다.

애플리케이션에서 Action 클래스를 만들 때, org.apache.struts.action.Action을 직접 확장하는 대신org.apache.struts.action.Action을 확장하여 Action 클래스 (IntermediateAction)를 만든다. 다른 모든 Action 클래스들은 이 IntermediateAction 클래스를 확장한다.

Best Practice 2. Action 클래스를 사용하여 요청 핸들하기
일반적으로 Struts 프레임웍을 사용할 때 JSP 컴포넌트가 애플리케이션을 실행하기위해 요청하는 모든 액션의 경우, 애플리케이션은 Struts의 org.apache.struts.action.Action 을 확장하여 Action 클래스를 만들어야 한다. 이 개별적인 Action 클래스는 요청을 처리하면서 애플리케이션의 Model 레이어와 인터페이싱한다.

Best Practice 2를 구현할 때 Struts는 다음과 같은 절차를 권장한다:

  1. org.apache.struts.action.Action을 확장하여 BP2Action이라고 하는Action 클래스를 만든다.
  2. BP2Action 을 확장하여 웹 애플리케이션에서 다른 모든 Action 클래스들을 만든다.
  3. 퍼블릭 앱스트랙트 ActionForward performTask(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException에서 그랬던 것처럼, BP2Action에서 performTask()메소드를 만든다.
  4. BP2Action에서 한 개 이상의 일반적인 메소드를 애플리케이션에 추가한다. 예를 들면 serverSideValidate()과 같은 것이다. 다음 요소들을 고려하여 메소드의 액세스 변경자를 결정할 수 있다:
    • 모든 Action 클래스들이 이 메소드를 구현한다면 이를 추상화하라.
    • 어떤 Action 클래스가 케이스 스팩 구현을 제공한다면 메소드 보호를 선언하고 여기에 디폴트 구현을 제공한다.
  5. BP2Action에서 마지막으로 perform() 메소드를 선언한다. 위에 언급된 일반 메소드를 선언하라. 이는 요청 프로세스 전에 항상 호출되어야 한다. 이제 3단계에서 만들어진 performTask() 메소드를 호출한다.
  6. BP2Action을 확장하는 모든 Action 클래스에서 performTask() 와 케이스 스팩 구현을 추가하라.

장점
Best Practice 2는 두 가지 주요 장점이 있다. 첫째, 웹 애플리케이션의 모든 Action 클래스에서 과잉의 코드를 피할 수 있다. 둘째, 하나의 Action 클래스에 작동을 중앙화 함으로서 애플리케이션의 일반적인 태스크에 대한 제어력을 높인다.

Best Practice 3. ActionForm을 세션 데이터에 작동시키기
Struts 기반의 웹 애플리케이션에서 각ActionFormorg.apache.struts.action.ActionForm을 확장한다. 이 ActionForm은 페이지 데이터를 캡슐화하고 밸리데이션 프레임웍을 제공하여 요청 매개변수의 타당성 검사를 한다.

대부분의 웹 애플리케이션들은 세션에서 데이터를 관리하여 애플리케이션을 통해 사용할 수 있도록 한다. Best Practice 3은 웹 애플리케이션 기능을 다룬다. toSession()fromSession() 메소드가 세션 데이터를 폼(form) 데이터 간 이동할 수 있도록 한다.

  1. org.apache.struts.action.ActionForm을 확장하여 추상 클래스 BP3Form을 만든다.
  2. BP3Form에서 퍼블릭 앱스트랙트void toSession(SessionData sessionData)void fromSession(SessionData sessionData)처럼 메소드와 액세스 변경자를 추가한다.
  3. 모든 ActionForm에서BP3Form을 확장하고 추상 메소드를 구현한다. 이 곳에서 폼 데이터가 세션으로(부터) 옮겨진다.
  4. 상응하는 Action 클래스는 이들 메소드가 호출되는 순서를 결정할 수도 있다. 예를 들어. actionForward가 결정되기 전에 ActionForm에서 toSession() 메소드를 호출할 수 있다.

Best Practice 3을 사용할 때는
Best Practice 3은 세션 데이터들이 하나의 객체로서 관리될 때 가장 유용하다. 또는 모든 페이지가 세션 데이터를 조작하거나 사용할 때도 유용하다.

Best Practice 4.효과적인 예외 핸들링
전통적으로 애플리케이션 예외는 Action 클래스에서 발생한다. 이 예외는 첫 번째로 기록된다. 그런 다음 Action 클래스는 ActionError를 만들고 이를 애플리케이션 범위 안에 저장한다. 이 클래스는 콘트롤을 적절한 ActionForward에 전달한다. Listing 3은 Action 클래스가 예외를 핸들하는 방법을 보여준다.

Listing 3. Action 클래스에서의 예외 핸들링
   try {   //Code in Action class   }   
catch (ApplicationException e) {
//log exception
ActionErrors actionErrors = new ActionErrors();
ActionError actionError = new ActionError(e.getErrorCode());
actionErrors.add(ActionErrors.GLOBAL_ERROR, actionError);
saveErrors(request, actionErrors); }

일반적인 예외 핸들링 절차가 모든 Action 클래스에 예외 정보를 저장하는 반면, Best Practice 4의 목적은 예외 핸들링을 하면서 과잉의 코드를 막는 것이다:

  1. org.apache.struts.action.Action을 확장하여 BP4Action라는 Action 클래스를 만든다.
  2. BP4Action을 확장하여 웹 애플리케이션에 다른 모든 Action 클래스들을 만든다.
  3. BP4Action에서, ActionErrors actionErrors = new ActionErrors(); 변수를 선언한다.
  4. 퍼블릭 앱스트랙트 ActionForward performTask(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, ActionErrors actionErrors) throws IOException, ServletException처럼 BP4ActionperformTask() 메소드를 만든다.
  5. BP4Action에서 마지막으로 perform() 메소드를 선언한다. 그런 다음 일반적인 메소드를 호출한다. 이들은 항상 요청 프로세스 전에 호출되어야 한다. 이제 이전 단계에서 만들어진 performTask() 메소드를 호출할 수 있다.
  6. BP4Action을 확장하여 모든 Action 클래스에서 performTask()메소드를 구현하면서 애플리케이션 예외를 처리한다. (Listing 4)
Listing 4. ActionErrors를 효과적으로 사용하기
   try		 {   //Code in Action class   }   
catch(ApplicationException appException) {
//Log exception
//Add error to actionErrors
actionErrors.add(ActionErrors.GLOBAL_ERROR,
new ActionError(appException.getErrorCode())); }

BP4Action에서 performTask() 메소드를 호출한 후에 saveErrors(request, errors)를 사용하여 ActionErrors를 저장한다.

장점
Best Practice 4의 큰 장점은 ActionErrors를 핸들하는 Action 클래스에서 코드 과잉을 막는다.

Posted by 1010