Struts Framework 소개
프레임웍은 특정 개념들의 추상화를 제공하는 여러 클래스나 컴포넌트로 구성된다. What is framework? 프레임웍은 특정 개념들의 추상화를 제공하는 여러 클래스나 컴포넌트로 구성된다. 프레임웍과 라이브러리의 가장 큰 차이는 얼마나 확장이 가능하며, 이를 고려해서 설계되었는가의 문제이다. 프레임웍은 이렇게 추상적인 개념들이 문제를 해결하기 위해 같이 작업하는 방법을 정의한다. 거의 모든 프레임웍은 지정된 패턴에 맞게 구성되어 있으며, 이를 확장하고자 할 때 패턴에 맞게 확장하기 용이하도록 구성되어 있다. 프레임웍의 주된 사용이유는 개발의 속도와 유지보수의 용이성 측면에서 고려 되어야 한다. 프레임웍은 컴포넌트들의 재사용이 가능하다. 개발자들이 개발하지 않아도 되는 공통적인 코드를 통해서 보다 비즈니스 로직에 전념할 수 있는 방안을 제공한다. 프레임웍은 좀 더 높은 수준에서 패턴들을 조직화 한다. 다른 프레임웍들과 상호 보완관계를 구성한다. 하나의 프레임웍이 완전하기 보다는 각 분야에 맞는 프레임웍들을 쉽게 융화시킬 수 있어야 한다.
Framework 기반 개발의 장.단점 지정된 패턴을 따른다. 공통적인 코딩에 신경 쓰지 않는다. 디자인 패턴의 집합체이다. 장: 누구나 동일한 방식으로 개발하게 되므로 개발자의 능력의 편차를 줄여줄 수 있다. 단: 하나의 방식에 적용하게 되면 다른 방식으로 바꾸려고 하지 않아 결국에는 편협한 방식으로만 개발하게 되는 문제 공통적인 코딩에 신경 쓰지 않는다. 장: 비즈니스 로직에만 집중하므로, 개발속도에서 좋은 성과를 가져올 수 있다. 단: 프레임웍 자체의 문제나 프레임웍에 대한 수정을 요구하는 경우에 전체에 영향을 주게 된다. 디자인 패턴의 집합체이다. 장: 원하는 부분의 설계에 즉각적인 반영이 가능하다. 단: 알지 못하는 상태에서 무작정 개발을 하게 된다. 재 사용이 가능하다. 장: 재사용을 통해서 개발 및 유지보수 시간을 최소화 시킨다. 단: 재사용의 수준을 판단하고 프레임웍 자체의 기능을 이해하는데 많은 시간이 소요된다. 다른 프레임웍들과의 상호보완관계 장: 우수한 프레임웍들을 결합, 개발 시간 단축, 유지보수의 용이함을 목표로 삼을 수 있다. 단: 통합에 대한 경험 부재시, 많은 부가적인 개발 부담으로 작용한다.
Struts 프레임웍 Struts 1.0 Struts의 이해를 위한 필수사항 Struts의 현황 MVC 구조에 기반을 둔 개발 방식 사용시에 채택되기 시작 이후 다른 프레임웍들의 개발 모델이 됨 J2EE에서 사용되던 디자인패턴들의 적극적인 반영 FrontController Service to Worker Session Facade Struts의 이해를 위한 필수사항 JDBC Servlet Servlet Context JSP JSP Bean 도메인 객체와 OOAD DD Struts의 현황 2007년 6월 1.3.8 버전 발표 별도로 Struts2.0의 버전은 2007년에 진행되고 있음 Struts2.0은 Struts1.x와 전혀 다르며, 쉽게 Migration 할 수 없음
Struts의 탄생배경 – Model1방식 초창기의 모델, 현재 가장 많이 사용됨 하나의 업무 처리에 관련된 모든 프로그램을 하나의 파일에 작성하는 방식 하나의 파일에 모두 작성하기 때문에 개발 속도가 빠르고 테스트가 용이 각 기술 부분에서 공동작업이 힘들고 이후의 수정, 확장, 유지보수가 어려움
Struts의 탄생배경 – Model2방식 요청에 대한 처리 및 응답 처리, Business Logic 처리, Persistence 처리에 대한 프로그램을 별도의 모듈로 작성 모듈화에 따른 작업의 overhead가 불가피 새로운 개발 방식이기 때문에 MVC에 대한 이해와 테크닉이 필요 각각의 개발자들의 업무 분장 및 공동 작업이 용이 재사용성이 높아짐 설계 시 공통 모듈과 전체의 관계를 명확히 해야함
Model1 방식과 Model2의 비교 Model1 Model2 개발 속도 초기 진행 용의, 규모가 클수록 진행 후기 속도 느림 초기 설계, 공통 모듈 구축 시 느림, 규모가 클수록 진행 후기 속도 빠름 확장 새로운 프로젝트의 진행과 거의 차이가 없음 확장을 고려한 설계가 되었을 경우 용이 유지 보수 규모가 클수록 유지 보수 난해 설계가 잘 되어 있을 경우 유지 보수 용이 공동 작업 공통적인 모듈을 작성하기 어려우며 한가지 스타일로 개발을 강제하기 어려워 공동 작업 난해 개발 방식을 강제할 수 있기 때문에 한가지 스타일로 개발이 가능해 공통 작업 용이
Struts를 구성하는 기본 원리의 파악 및 J2EE 디자인 패턴, Java 디자인 패턴의 학습
FrontController 패턴 중앙에 하나의 Control을 담당하는 부분을 두고 모든 요청은 중앙의 컨트롤러를 이용하게 한다. 컨트롤러는 하나의 인스턴스로 동작하도록 설계하는 것이 일반적이다 (사용자의 수와 상관없이 서버의 부하를 줄이는 방안으로 설계) 모든 페이지의 처리는 컨트롤러에서 별도의 자원으로 관리하므로 페이지의 유지보수시에 용이하게 사용할 수 있다.
뷰가 프리젠테이션과 직접적으로 관련 없는 일을 하는 것을 분리해 주는 패턴 View Helper 뷰가 프리젠테이션과 직접적으로 관련 없는 일을 하는 것을 분리해 주는 패턴 주로 Request정보중에 원하는 정보를 쉽게 처리 할 수 있도록 객체화 시키는 작업을 의미할 때가 많다. Composite view 하나의 뷰를 여러 개로 구성하여 변경이나 코드의 중복을 처리해 주는 방식
Service To Worker 패턴 Front Controller와 View Helper를 이용해서 하나로 만든 방식(Micro) 별도의 Application Controller를 이용하는 방식 헬퍼를 이용하는 방식으로 구성
Strategy 패턴 알고리즘군이 존재할 경우 각각의 알고리즘을 별도의 클래스로 캡슐화하고 이들을 상호 교환 가능한 것으로 정의한다.
객체마다 가진 수행 메쏘드에 대한 캡슐화의 목적 호출하는 객체는 어떤 메쏘드를 호출해야 하는지 신경 쓰지 않는다. Command 패턴 인터페이스를 이용한 가장 기본적인 패턴으로 특정 인터페이스에 맞는 객체들을 묶어서 하나의 별도의 객체가 처리할 수 있는 방안을 제공한다. 객체마다 가진 수행 메쏘드에 대한 캡슐화의 목적 호출하는 객체는 어떤 메쏘드를 호출해야 하는지 신경 쓰지 않는다. 여러 개의 Command Object로 작업하게 되면 MacroCommand 패턴이라고 한다. Command 패턴의 구성 Receiver: 실제로 동작을 수행하는 객체 Command: 구현해야 하는 동작에 대한 추상화된 인터페이스 ConcreateCommand: 특정 행동과 동작객체가 묶여 있는 객체 Invoker: Command 인터페이스에 실행을 요청하는 객체
Struts를 구성하는 기본 원리의 파악 및 J2EE 디자인 패턴, Java 디자인 패턴의 학습 Filter 기능 Struts를 구성하는 기본 원리의 파악 및 J2EE 디자인 패턴, Java 디자인 패턴의 학습
서블릿 스펙 2.3이후에 처음으로 등장한 Filter HTTP요청과 응답 사이 중간에 필터링기능을 할 수 있게 되어 있는 인터페이스 여러 개의 필터로 연결해서 작업할 수 있다. Filter 체이닝 기존의 소스를 하나도 손대지 않고 사용할 수 있다. 중간에 특정 로직에 따라 분기하는 기능도 사용한다.
Filter의 기능 데이터의 조작 한글 처리 로그 기록 검증 다른 필터의 호출 체이닝 흐름 변경 로그인 처리 인증 처리
javax.servlet.ServletReqestWrapper javax.servletServletReponseWrapper Filter 인터페이스 javax.servlet.Filter 실제 Filter 역할을 해야 하는 클래스가 구현해야 하는 인터페이스 javax.servlet.ServletReqestWrapper ServletRequest 객체의 Wrapper 클래스 javax.servletServletReponseWrapper ServletResponse 객체의 Wrapper 클래스 Filter 인터페이스 public void init(FilterConfig filterconfig) throws ... 필터를 초기화 하기 위한 작업 수행 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 실제 필터링 하는 작업 수행 chain을 통해서 다음 연결된 필터로 이동하게 한다. public void destroy() 필터가 컨테이너에서 제거될 때 시행되는 메소드
FilterEx1 package com.study; import java.io.IOException; import java.util.*; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public class FilterEx1 implements Filter { public void destroy() { System.out.println("Filter destroy()"); } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { Enumeration paramNames = request.getParameterNames(); System.out.println("-------------------------------------"); while(paramNames.hasMoreElements()){ System.out.println(paramNames.nextElement()); chain.doFilter(request, response); public void init(FilterConfig arg0) throws ServletException { System.out.println("Filter inited... ");
필터의 설정 web.xml에 두가지 작업 필요 필터로 등록 필터가 동작할 경로 지정 필터가 동작하는 타입 지정 servlet 등록처럼 컨테이너가 관리 대상으로 삼도록 작업 필터가 동작할 경로 지정 필터가 특정 경로나 확장자에 맞게 동작하도록 지정 필터가 동작하는 타입 지정 dispatcher 속성으로 지정 기본은 REQUEST – 클라이언트의 요청시에만 필터 동작 FORWARD INCLUDE <filter> <filter-name>filter1</filter-name> <filter-class>com.study.FilterEx1</filter-class> </filter> <filter-mapping> <url-pattern>/*</url-pattern> </filter-mapping>
동일한 경로를 대상으로 web.xml을 통해서 여러개의 필터를 등록하는 경우에는 연결된 필터로 동작한다. 필터 체이닝 및 사용 팁 동일한 경로를 대상으로 web.xml을 통해서 여러개의 필터를 등록하는 경우에는 연결된 필터로 동작한다. 다른 페이지로 포워드를 해야 하는 경우 필터의 doChain()을 통해서 다른 필터로 가기 전에 RequestDispatcher를 이용해서 특정 페이지로 이동시킨다. 한글 변환 ServletRequest이므로 HttpServletRequest로 변환시킨다. 파일 다운로드 금지 처리 요청한 URL경로를 확인하고, 요청 URI를 파악해서 분기 시킨다. 인증 처리 init() 메소드를 통해서 인증 모듈과 연결하고 필요시에 인증을 처리할 수 있게 한다. Struts의 처리 Struts는 가능하면 모든 JSP로 요청을 권장하지 않으므로 jsp로 요청을 하는 경우 강제적으로 특정 페이지로 이동하거나 로그를 기록하게 한다.
Struts를 구성하는 기본 원리의 파악 및 J2EE 디자인 패턴, Java 디자인 패턴의 학습
2007년 8월 현재 1.3.X 버전과 같이 2.x버전 동시에 진행중인 상황 Struts install http://struts.apache.org 2007년 8월 현재 1.3.X 버전과 같이 2.x버전 동시에 진행중인 상황 2.0 이후의 기능은 WebWork 프레임웍과 통합되어 실질적으로는 새로운 기능으로 보는 의견이 많음 현재까지의 개발은 주로 1.1 , 1.2 버전으로 개발이 많이 진행되었음 다운로드의 예제와 문서 활용 apps struts-blank: 실무에서 바로 수정/적용이 가능한 스트럿츠의 기본 구조 struts-cookbook: Struts 활용하는 예제들의 집합 struts-examples: Struts를 커스터마이징해서 사용하는 예제
Struts의 설정 기본 web.xml의 설정 web.xml에서는 Struts Configuration 파일을 사용하도록 설정하는 작업(1) 과 ActionServlet 서블릿 (컨트롤러)의 설정이 가능하도록 수정해야 한다. <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.4" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <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> <param-name>debug</param-name> <param-value>3</param-value> <param-name>detail</param-name> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <url-pattern>*.do</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
Struts – Configuration 파일 struts-config.xml 파일 별도의 파일명으로 사용하여도 상관없으나, 일반적으로 기본이름을 그대로 사용한다. struts와 관련된 설정 정보를 활용한다. <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN" "http://struts.apache.org/dtds/struts-config_1_3.dtd"> <struts-config> <!– FORMS - -> <form-beans > </form-beans> <!--EXCEPTIONS --> <global-exceptions > </global-exceptions> <!-- GLOBAL FORWARDS --> <global-forwards > <forward name="welcome" path="/Welcome.do"/> </global-forwards> <action-mappings > <action path="/Welcome" forward="/intro/welcome.jsp"/> </action-mappings> </struts-config>
Struts 활용 범위 Model2의 구조를 위한 기반으로 활용하는 방법 Tiles나 Struts-EL을 이용해서 화면의 View를 구성하여 활용하는 방법 Message 기능을 이용해서 다국어의 표현 Hibernate, iBatis와 같이 연동하여 각 Layer별로 구성하는 방법 Struts 관련 Frameworks 일반적으로 Struts는 단독으로 쓰여서 전체 웹 어플리케이션의 기본구조를 활용하는 방법으로 사용되기도 하지만, 추가적인 Framework들과 결합시켜서 Layer별로 분리해서 사용하는 설계도 사용한다. 주로 같이 언급되는 FrameWorks Tiles Velocity Typestry WebWork iBatis Hibernate JSF Struts의 사용을 위해서는 별도의 복잡한 프레임웍들을 학습하고, UI부분 역시 같이 학습해야 하는 것은 아니므로, 현재 자신들의 프로젝트에 맞게 필요한 부분만 결정해서 사용한다.
특정한 URL로 접근하면 Controller를 통해서 JSP페이지의 화면을 보여주는 방식 기존의 JSP호출과 결과는 동일 특정한 페이지를 보여주는 스트럿츠설정 특정한 URL로 접근하면 Controller를 통해서 JSP페이지의 화면을 보여주는 방식 기존의 JSP호출과 결과는 동일 ForwardAction 작업순서 struts-config.xml 수정 /intro/welcome.jsp 수정 struts-config.xml <action-mappings > <action path="/Welcome" forward="/intro/welcome.jsp"/> </action-mappings>
기존의 JSP 프로그래밍 방식과 Struts 방식의 비교 기존 JSP 프로그래밍 로그인 예제로 보는 스트럿츠 기존의 JSP 프로그래밍 방식과 Struts 방식의 비교 기존 JSP 프로그래밍 로그인 정보를 입력받기 위한 화면(이하 최초 화면 요청) 최초 화면에서는 로그인을 실행할 JSP나 서블릿의 경로가 지정되어서 실행 정보를 입력하고 실행 전송되는 정보는 Bean의 형태나 자바의 객체로 변환되어서 전달 전달된 정보에서 비지니스 로직 처리를 위해서 필요한 정보 분리 비지니스 로직을 처리 화면에 결과를 출력 Struts 방식의 프로그래밍 최초 화면을 보기 위해 Controller인 ActionServlet을 통해서 요청 Controller가 최초화면 페이지로 forwarding 전송되는 정보는 지정된 설정(strtus-config.xml)에 의해서 결정 Struts의 Action을 이용해서 전송되는 정보 객체를 추출 정보를 분리해서 비지니스 로직을 처리 화면에 결과 출력 Struts 방식의 프로그래밍 순서 화면에서 전달 받을 객체를 먼저 생성 (이하 Data Transfer Object 혹은 Value Object) struts설정에 ActionForm으로 추가 로직을 처리할 객체 (이하 Business Object)를 만들때에는 반드시Action이라는 클래스를 상속받게 생성 struts설정에 Action추가
기존 방식의 구성정보 Struts 방식의 구성 정보
Struts의 실행 구조
스트럿츠의 객체 - Java Bean VS ActionForm ActionForm은 스트럿츠의 내부에서 자체적으로 사용하는 Java Bean 작성시 요구사항 반드시 ActionForm을 상속받아야 한다. 자바빈의 규칙으로 private, public을 맞추어야 한다. 검증하고 싶다면 validate()를 재정의 초기화를 위해서는 reset()을 재정의 ActionForm의 역할 필드값 수거기로서의 ActionForm 데이터 버퍼로서의 ActionForm 데이터 검증기로서의 ActionForm 타입 변환기로서의 ActionForm 객체 전달자로서의 ActionForm 생성방법 반드시 객체로 만들어야 하는 자바 빈과는 달리 다양한 방식으로 만드는 것이 가능하다(ActionForm의 종류) Struts2.0이후에서는 일반 POJO 객체를 ActionForm으로 사용할 수 있다.
ActionForm의 내부적인 실행 절차
작업순서1 - LoginForm package com.bit.strutsex.form; import javax.servlet.http.HttpServletRequest; import org.apache.struts.action.ActionErrors; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionMapping; public class LoginForm extends ActionForm { private String password; private String userId; public ActionErrors validate(ActionMapping mapping,HttpServletRequest request) { return null; } public void reset(ActionMapping mapping, HttpServletRequest request) { public String getPassword() { return password; public void setPassword(String password) { this.password = password; public String getUserId() { return userId; public void setUserId(String userId) { this.userId = userId;
MVC모델에서 Controller 역할을 담당하는 부분 Struts에서는 ActionServlet을 상속받아서 작성한다. 작업순서2 - LoginAction MVC모델에서 Controller 역할을 담당하는 부분 Struts에서는 ActionServlet을 상속받아서 작성한다. 작성 후에는 몇 가지 속성을 지정해서 struts-config.xml을 통해서 설정작업을 해야 한다. package com.bit.strutsex.action; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.Action; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import com.bit.strutsex.form.LoginForm; public class LoginAction extends Action { public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { LoginForm loginForm = (LoginForm) form; System.out.println(loginForm); System.out.println(loginForm.getUserId()); System.out.println(loginForm.getPassword()); return mapping.findForward("success"); }
작업순서3 Login 화면 - login.jsp/loginSuccess.jsp <form name='form1' action='Login.do' method='post'> <table width='300' border='1'> <tr> <td width='20%'> ID</td> <td width='80%'><input type='text' name='userId' value='1111'></td> </tr> <td width='20%'> PW</td> <td width='80%'><input type='password' name='password' value='1111'></td> <td width='20%'> 로그인 실행 </td> <td width='80%'><input type='submit' value='로그인'></td> </table> </form> loginSuccess.jsp 소스 <body> 로그인에 성공하셨습니다.<br> </body>
작업순서4 – struts-config 설정 위에서 만든 각각의 코드들을 엮어 만드는 작업 별도의 프로그램을 이용해서 작업하거나, Ant, XDoclet을 활용해서 작업하기도 한다. <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN" "http://struts.apache.org/dtds/struts-config_1_3.dtd"> <struts-config> <form-beans > <form-bean name="loginForm" type="com.bit.strutsex.form.LoginForm" /> </form-beans> <!--EXCEPTIONS --> <global-exceptions > </global-exceptions> <!-- GLOBAL FORWARDS --> <global-forwards > <forward name="welcome" path="/Welcome.do"/> </global-forwards> <action-mappings > <action path="/Welcome" forward="/intro/welcome.jsp"/> <action path="/UserLogin" forward="/intro/login.jsp"/> <action attribute="loginForm" input="/intro/login.jsp" name="loginForm" path="/Login" scope="request" type="com.bit.strutsex.action.LoginAction"> <forward name="success" path="/intro/loginSuccess.jsp" /> </action> </action-mappings> </struts-config>
Struts를 구성하는 기본 원리의 파악 및 J2EE 디자인 패턴, Java 디자인 패턴의 학습
Struts는 기본적으로 한글 문자셋을 지원하지 않기 때문에 다음과 같은 방법 중에 하나를 선택해야 한다. RequestProcessor를 확장해서 처리하는 방식 Filter를 이용해서 처리하는 방식 필요한 경우에만 한글로 파라미터 데이터 변환 방식 UTF-8 문자열로 통일하는 방법
RequestProcessor를 상속해서 만드는 방법 서블릿 스펙 2.3버전 이전의 컨테이너에서 사용할 수 있는 방법 struts-config.xml에 <controller>를 이용해서 수정 package com.study; import javax.servlet.http.*; import org.apache.struts.action.RequestProcessor; public class HangulRequestProcessor extends RequestProcessor { protected boolean processPreprocess(HttpServletRequest request, HttpServletResponse response){ try{ request.setCharacterEncoding("EUC-KR"); return true; }catch(Exception e){ return false; } <controller contentType="text/html;charset=euc-kr" locale="true" nocache="true" processorClass="com.study.HangulRequestProcessor"/>ㅎ
파라미터의 데이터를 사용하기 전에 setCharacterEncoding()을 적용한다. web.xml에 필터 적용 Filter를 이용하는 방식 Filter를 전체가 영향받도록 설정한다. 파라미터의 데이터를 사용하기 전에 setCharacterEncoding()을 적용한다. web.xml에 필터 적용 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { request.setCharacterEncoding("EUC-KR"); Enumeration paramNames = request.getParameterNames(); System.out.println("-------------------------------------"); while(paramNames.hasMoreElements()){ System.out.println(paramNames.nextElement()); } HttpServletRequest hrequest = (HttpServletRequest)request; System.out.println("QUERY : " + hrequest.getQueryString()); System.out.println("URL : " + hrequest.getRequestURI()); String currentPath = hrequest.getSession().getServletContext().getRealPath(""); System.out.println("DISK PATH : "+currentPath); chain.doFilter(request, response);
Struts를 구성하는 기본 원리의 파악 및 J2EE 디자인 패턴, Java 디자인 패턴의 학습 Struts FileUpload Struts를 구성하는 기본 원리의 파악 및 J2EE 디자인 패턴, Java 디자인 패턴의 학습
Struts의 파일 업로드 RequestProcessor에서 실행하는 가장 첫번째 작업은 Request정보가 MultipartRequest로 구성되어 있는지에 대한 파악이며, Struts는 기본적으로 commons-fileupload라이브러리를 활용해 파일을 처리한다. public class UploadForm extends ActionForm { /** text1 property */ private String text1; /** file1 property */ private FormFile file1; /** file2 property */ private FormFile file2; public void setFile1(FormFile file1) { this.file1 = file1; } ---이하 생략 --- public FormFile getFile1() { return file1;
업로드를 입력하는 페이지 <html:form action="upload 업로드를 입력하는 페이지 <html:form action="upload.do" enctype="multipart/form-data"> <table> <tr> <td> 텍스트 </td> <input type='text' name='text1'> </tr> 파일1 <input type='file' name='file1'> 파일2 <input type='file' name='file2'> <td>전송</td> <td><html:submit></html:submit></td> </table> </html:form>
UploadAction의 소스 부분 public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { UploadForm uploadForm = (UploadForm) form;// TODO Auto-generated method stub String text1 = uploadForm.getText1(); System.out.println("Text : " + text1); FormFile file1 = uploadForm.getFile1(); InputStream in = null;
Struts 모듈설정
일반 <a>태그를 이용하는 방법과 <html:link>태그를 이용하는 경우에 설정하는 방법이 다르다. 모듈간의 페이지 이동 일반 <a>태그를 이용하는 방법과 <html:link>태그를 이용하는 경우에 설정하는 방법이 다르다. <a href="indexMember2.do">indexMember2 페이지로 이동합니다.</a> <br> <html:link page="/indexMember2.do"> indexMember2 이동합니다.</html:link> <a>를 이용하는 경우에는 페이지가 있는 경로를 기준으로 삼기 때문에 절대경로 혹은 상대 경로를 통해서만 지정해야 한다 <html:link>를 이용하는 경우에는 태그의 정보 안에 현재 모듈의 정보가 기본적으로 로딩되어 사용되므로 / 처리만 해주면 자동적으로 현재 모듈 설정의 같은 내용을 사용하게 된다.
다른 모듈로의 페이지 이동 Struts 1.1 방식 Struts1.2 방식 HTML태그와의 비교 별도의 SwitchAction을 이용해서 처리 <action path="/ChangeModuleTest" type="org.apache.struts.actions.SwitchAction"/> Struts1.2 방식 <html:link> 태그의 module 속성을 이용해서 처리 <html:link module="/product" page="/indexProduct.do“>와 같은 방식으로 처리한다. HTML태그와의 비교 <html:link> 이용시 <html:link module="/product" page="/indexProduct.do"> 프로덕트의 index페이지로 이동합니다.</html:link> 일반 <a>태그 이용시 <a href="../product/indexProduct.do"> 프로덕트의 index페이지로 이동합니다.</a>
Struts를 구성하는 기본 원리의 파악 및 J2EE 디자인 패턴, Java 디자인 패턴의 학습 Struts ActionForm Struts를 구성하는 기본 원리의 파악 및 J2EE 디자인 패턴, Java 디자인 패턴의 학습
org.apache.struts.action.ActionForm을 상속 주로 데이터를 담는 역할을 하며, setter/getter 이외에는 별도의 비즈니스 처리는 하지 않도록 선언한다. Scope 속성을 이용해서 Application, Session, Request, Page 내에서 데이터를 유지할 수 있다. 가장 기본적인 형태는 JavaBean의 형태를 사용한다. reset(): 필요한 경우에는 스코프 내에서 재 사용될 가능성이 있는 경우에 reset()을 이용해서 처리할 수 있다. validate(): 현재 들어온 값들에 대한 검증 작업을 처리할 수 있다. validate()는 각 입력값들에 대한 검사 작업을 수행할 수 있으나 실제로는 프레임웍으로 처리하는 경우가 많다. 주의 사항 ActionForm은 주로 화면에서 입력되는 데이터를 유지하기 위해서 사용하는 일종의 Data Transfer Object이다. 때문에 비즈니스에서 처리해야 하는 Value Object나 Business Object 사이에서 넘겨주는 방식의 코딩을 적절하지 않다. Scope를 별도로 지정하지 않으면 Session스코프로 사용된다.
struts-config.xml내에서 설정 <form-beans>태그내에 <form-bean> 태그 사용 ActionForm의 설정 struts-config.xml내에서 설정 <form-beans>태그내에 <form-bean> 태그 사용 가장 기본설정은 이름과 타입(클래스)만을 지정하는 설정 <form-bean name="loginForm" type="com.bit.strutsex.form.LoginForm" /> form-bean 태그의 추가적인 속성 className: 별도의 Configuration사용시에만 사용 dynamic: DynaActionForm에서만 true <!ELEMENT form-bean (icon?, display-name?, description?,set-property*, form-property*)> DynaActionForm 별도의 자바 코드 없이 XML의 설정만으로 ActionForm을 사용하는 방법 <form-property>요소들을 통해서 설정하면 자동적으로 setter,getter가 생성되는 방식 (Collections타입은 별도처리) java.math.BigDecimal java.math.BigInteger boolean and java.lang.Boolean byte and java.lang.Byte char and java.lang.Character java.lang.Class double and java.lang.Double float and java.lang.Float int and java.lang.Integer long and java.lang.Long short and java.lang.Short java.lang.String java.sql.Date java.sql.Time java.sql.Timestamp
Map-backed ActionForm 실행되는 시점에 타입이 결정되어서 사용되어야 하는 경우에 주로 사용한다. Struts에서 제공하는 클래스가 아니라 ActionForm을 접근하는 하나의 방식을 의미한다. public FooForm extends ActionForm { private final Map values = new HashMap(); public void setValue(String key, Object value) { values.put(key, value); } public Object getValue(String key) { return values.get(key); List-backed ActionForm 실행되는 시점에 타입이 결정되어서 사용되어야 하는 경우에 주로 사용한다. Struts에서 제공하는 클래스가 아니라 ActionForm을 접근하는 하나의 방식을 의미한다. public FooForm extends ActionForm { private final List values = new ArrayList(); public void setValue(int key, Object value) { values.set(key, value); } public Object getValue(int key) { return values.get(key);
Struts ActionServlet, Action
Struts의 Controller 클래스의 설계
ActionServlet 모든 요청이 거치는 서블릿 RequestProcessor를 생성한 후에 호출하는 역할 1.1버전 이후에는 ActionServlet은 설정 파일의 초기화를 수행하는 기능
RequestProcessor multi-part request의 형태인지 구분 요청 URL을 분석하여 ActionMapping의 path값 추출 Locale정보 선정 인코딩 설정 ... ActionForm 검색 및 설정 (And 검증) Action인스턴스 검색 – 최초 사용시에 생성되어 ServletContext에 저장되어 재사용한다. execute()실행 execute()실행된 결과를 ActionForward에 전달
ForwardAction 별도의 다른 동작없이 지정된 URL로 페이지를 이동하는 경우에 사용. <action path="/Welcome" forward="/intro/welcome.jsp"/> IncludeAction ForwardAction과 결과는 동일하나, JSP를 수행하고, 컨트롤이 RequestProcessor로 반환되는가의 차이만 있다. <action path="/Welcome" include="/intro/welcome.jsp"/> LocaleAction HTTP Header정보에 담겨있는 로케일의 설정을 변경하고자 할 때 사용한다. DownloadAction 1.2.6 이상의 버전에서 활용가능
DispatchAction 지정된 파라미터로 메소드를 자동적으로 분기시키는 기능을 활용 Action의 숫자를 줄이고 유지보수시에 용이함. struts-config.xml에서 form 설정시에 parameter 속성값을 활용 사용시에는 parameter의 값이 하나의 메소드로 분기되어 처리 SwitchAction Struts의 모듈을 하나 이상으로 설정해서 사용하는 경우에 모듈간의 이동 기능을 지원한다. LookupDispatchAction 프로그램상에서 코드값을 Map을 통해서 저장하고, 이를 화면에서 별도의 속성값으로 전달해 주는 방식 중간에 하나의 코드값을 더 추가해서 사용하는 형태 MappingDispatchAction 파라미터를 Action에서 활용하는 것이 아닌 config파일에서 파라미터에 맞는 경로를 따로 설정하는 방식을 의미한다. 1.2 이후에 사용 가능
Struts의 ActionForm을 비즈니스로직 처리에 반영하지 않는다 ActionForm의 위치는 View와 Controller의 사이에만 존재하는 것이 맞으며, 남용하지 않도록 한다. CRUD기능의 경우에는 주로 DispatchAction을 이용하라. CRUD(Create, Read, Update, Delete)의 기능 구현시에는 주로 하나의 파라미터를 이용해서 DispatchAction을 이용해서 처리한다. 이 경우 일정한 네이밍 룰을 가지면 더욱 편하게 사용할 수 있다. Filter의 사용의 고려하라. Filter의 기능을 활용하면 특정 폴더의 접근이나 jsp의 직접 접근을 제어할 수 있으므로 Controller 중심으로 설정하는 작업이 쉽게 가능하다. 비즈니스 로직을 처리하는 부분의 설계에 집중하라. 스트럿츠는 MVC모델에 맞게 구현할 수 있는 기반을 제공해 주긴하지만 그 자체가 MVC는 아니므로, 비즈니스 로직을 처리하는 부분은 결국 개발자들이 직접 처리해야 한다. View의 처리는 마지막에 한다. View는 주로 디자인과 관련된 작업이 많으므로 이에 대한 최종처리는 모든 비즈니스 로직의 처리를 확인한 이후에 진행한다. View를 담당하는 프레임웍을 사용하게 되면 유지보수를 고려해 최종적인 단계에서 처리한다.
Value Object / Transfer Object Value Object (이하 VO)는 하나의 도메인모델의 데이터를 표현해 주는 객체를 의미한다. 각 레이어 사이에 데이터는 이동을 담당하는 Transfer Object(TO) 를 이용한다. ActionForm을 활용하는 데 있어서 VO를 Wrapping해서 사용하는 방법을 주로 활용한다. 개발 하는 단계 ( 공지사항 ) VO 개발 (도메인 모델 선정) ActionForm 개발 Action 개발 Action 설정 화면 처리 도메인 모델 개념적 객체라는 용어와 같은 의미로 사용 화면이 아닌 실제로 처리해야 하는 의미를 가지는 객체를 칭함
Struts Exception처리
Struts의 Exception 처리 프로세스 RequestProcessor: config설정에 의한 Exception 처리 XXXAction: Action에서는 자체적으로 Exception처리를 시행하지 않고, RequestProcessor에게 pass한다. XXXClass: 실제 예외를 발생하지만 Action에서 처리하게끔 던진다. 실제로 RequestProcessor는 ExceptionHandler를 config로 부터 찾아내서 ExceptionHandler의 excute()를 실행한다. Exception설정이 별도로 준비되어 있지 않으면, 스트럿츠의 기본 Exception Handler가 예외를 처리하게 된다. Exception의 설정을 위해서는 반드시 메시지 처리 기능이 제공 되어야 한다. 기본 메시지의 처리 설정에 메시지를 추가해서 사용한다. Exception의 설정 global-exception 설정 <exception key="global.excp.DBException" path="/except/dbException.jsp" type="com.bit.strutsex.excp.DBException" /> action의 exception 태그 추가 <action attribute="productForm" input="/product/addProduct.jsp" name="productForm" path="/AddProduct" scope="request" type="com.bit.strutsex.action.AddProductAction"> key="excp.DBException“ 메시지 파일에서 설정되는 부분 </action>
Struts Validator
ActionForm으로 입력된 데이터들에 대한 검증 작업을 시행 Validator의 기능 ActionForm으로 입력된 데이터들에 대한 검증 작업을 시행 validate() 메쏘드를 구현하는 방법 Validator 프레임웍을 사용하는 방법 Validator프레임웍의 활용 – 1.1 부터 공식 지원 플러그인 등록 validator-rules.xml validation.xml 파일 추가 <plug-in className="org.apache.struts.validator.ValidatorPlugIn"> <set-property property="pathnames" value="/org/apache/struts/validator/validator-rules.xml, /WEB-INF/validation.xml"/> </plug-in>
선언된 규칙들은 여러 ActionForm에서 사용할 수 있다. validator-rules.xml 검증 규칙을 선언하는 파일 선언된 규칙들은 여러 ActionForm에서 사용할 수 있다. validator-rules.xml파일은 실제의 규칙이 적용되어야 하는 원칙만을 의미한다. 예를 들어 특정한 ActionForm에 특정 프로퍼티의 값이 반드시 필요한지, 특정한 경우에만 필요한지 설정하는 경우에 사용한다. required: 입력 값이 반드시 존재해야 한다. validWhen: 다른 필드의 값과 비교해서 유효성을 검사한다. minlength: 최소 길이 제한 maxlength: 최대 길이 제한 mask: 정규표현식에 의한 검사 byte: byte타입으로 변환할 수 있어야 한다. short integer long float double date intRange: 지정된 min,max 값 안에 범위의 수로 값을 가져야 한다 floatRange doubleRange creditRange email url 일반적으로 프로젝트 진행 시에는 위의 규칙을 제외한 새로운 규칙을 정의하지는 않고, 기존의 것을 이용해서 validation.xml만을 재정의해서 사용하는 것이 보편적이다.
validation.xml은 global요소와 formset요소로 구성된다. <constant> <constant-name>postalCode</constant-name> <constant-value>^\d{3}-\d{3}$</constant-value> </constant> global요소는 formset내에서 전역변수처럼 사용할 수 있다.
Struts에서의 View
Struts의 커스텀 태그 라이브러리 기본적으로 많이 사용하는 태그 라이브러리 기타 Struts의 태그 라이브러리 struts-html.tld struts-bean.tld struts-logic.tld struts-nested.tld 기타 Struts의 태그 라이브러리 struts-tiles.tld sql.tld web.xml (DD)의 설정방식은 주로 Servlet2.3이전에 처리했으며, 2.4이후의 web.xml은 별도의 taglib태그 추가없이 페이지내에서 태그의 설정을 따른다. <%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean"%> <%@ taglib uri="http://struts.apache.org/tags-html" prefix="html"%> <%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %> <%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
일반적으로 Struts의 태그는 자체로 작업 되기 보다는 ActionForm과 같이 작업되는 경우가 많다. Struts- html 기본 태그 일반적으로 Struts의 태그는 자체로 작업 되기 보다는 ActionForm과 같이 작업되는 경우가 많다. <html:text property="tag4“ ...>와 같이 setXXX(), getXXX()의 메쏘드를 같이 자동적으로 값을 ActionForm에 저장하고, 사용할 수 있는 기능을 제공한다. form 태그 form방식으로 전송하기 위해서 사용하며, 몇 가지 속성을 가진다. enctype: 파일 업로드 시에는 mulitpart/form-data 나머지의 경우에는 application/x-www-form-urlencoded로 간주된다. method: 기본적으로 post값을 갖는다. focus: 입력 폼이 초기화될 때 포커스를 받을 필드 명 html 태그 lang 속성: 1.2부터 지원되는 사용자의 로케일 정보를 참조해 자동적으로 HTML의 lang속성 지정한다. base태그 현재 웹 어플리케이션이 작업되고 있는 경로에 대한 설정으로, 지정하게 되면 화면 내에 모든 경로설정에 영향을 주게 한다. errors, message 태그 amount : <html:text property="amount"/><html:errors property="amount"/> errors태그를 이용해서 화면상에 출력해 주는 경우에 지정된 error메시지를 출력하게 프로그래밍 할 수 있다.
Struts-html 주로 HTML입력폼에 관련 요소 지원 base: HTML내에서 기준이 되는 경로 의미 button : 버튼 cancel : 취소버튼 checkbox : checkbox errors : ActionForm의 validate()에서 발생한 에러 메시지 file : 파일 업로드 form : HTML form태그 frame : 프레임 태그 hidden : hidden 필드 html : <html> image: image 입력필드 img : <img> javascript : ActionForm전달이전 화면에서의 자바스크립트 link : 하이퍼링크 messages : 필드 옆에서 에러 메시지를 출력할 때 사용 multibox : checkbox option : select의 <option> options optionsCollection password : 패스워드 radio rewrite select submit text textarea
<%@ page language="java" pageEncoding="EUC-KR"%> <%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean"%> <%@ taglib uri="http://struts.apache.org/tags-html" prefix="html"%> <%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %> <%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html:html lang="true"> <head> <html:base /> </head> <body> 이것은 스트럿츠의 태그 페이지 입니다. <br> <html:form action="/input1.do"> <table width="500" border="1" bgcolor="#f0f0f0" align="left"> <tbody> <tr> <td width='20%'>tag1 버튼</td> <td><html:button property="tag1" value="클릭"></html:button></td> </tr> <td>tag2 체크박스</td> <td><html:checkbox property="tag2" value="체크1" >체크1</html:checkbox></td> <td>tag3 파일</td> <td><html:file property="tag3"></html:file><td> <td>tag4 텍스트</td> <td><html:text property="tag4" value="텍스트필드" size="30" maxlength="50"></html:text></td> <td>tag5 텍스트에어리어</td> <td><html:textarea property="tag5" value="텍스트필드" rows="5" cols="10"></html:textarea></td> <td><html:reset property="tag6" value="tag6리셋"></html:reset></td> <td><html:cancel property="tag7" value="tag7취소"></html:cancel></td> <td><html:submit property="tag8" value="tag8전송"></html:submit></td> <td>AAAA</td> </tbody> </table> </html:form> </body> </html:html>
Struts-bean 태그 새로운 Beans 객체 혹은 변수 생성, 프로퍼티 출력 용도로 사용 cookie: 쿠키값에 변수 정의 difine: 지정한 빈에 변수 정의 header: 지정한 헤더에 변수 저의 include: 외부 컴포넌트 포함 message: 리소스 번들로에서 메시지 page: 페이지 스코프에서 자바빈즈 조회해 프로퍼트값에 근거해 변수를 정의한다. parameter: 지정한 요청 파라미터 값에 근거해 변수를 정의 resource: 지정한 웹 어플리케이션의 자원을 사용할 수 있도록 정의 size: Collection 또는 Map이 가지고 있는 항목의 수에 근거해 변수를 정의한다. write: 지정한 프로퍼티의 값을 출력한다.
Struts- logic 값의 비교 부분 문자열 매칭 재전송과 포워딩 반복 수행 empty: 지정된 변수가 null이거나 빈 문자열일 경우 true equal greaterEqual greaterThan lessEqual lssThan notEmpty notEqual notPresent present: 지정된 값이 검색 가능한 스코프 내에 있으면 true 부분 문자열 매칭 match notMatch 재전송과 포워딩 forward redirect 반복 수행 iterate
Struts와 Tiles의 연동
중복적인 코드를 없애고 코드의 가독성을 높인다. 필요한 레이아웃을 미리 지정해서 재활용할 수 있다. Tiles 프레임워크 기존의 include방식이 필요한 페이지를 제외한 전체를 copy$paste 하는 방식이었다면 Tiles는 전체페이지의 모양을 잡아두고 필요한 부분만 변경하는 방식으로 변화 중복적인 코드를 없애고 코드의 가독성을 높인다. 필요한 레이아웃을 미리 지정해서 재활용할 수 있다. 단순 HTML을 재 활용하는 것이 아니라 extends를 이용하는 재 활용 가능 JSP에서 설정하는 방식과 XML 설정 방식이 있으나, 주로 XML 설정 방식이 사용된다.
tile: 타일 (실제 화면에 보여지는 독립적으로 view가 가능한 단위를 구성한 것을 의미한다.) Tiles 사용을 위한 기본 개념 tile: 타일 (실제 화면에 보여지는 독립적으로 view가 가능한 단위를 구성한 것을 의미한다.) layout: 여러 개의 tile을 모아서 하나의 전체적인 모양새를 가진 것을 의미하며, template이라고도 한다. Struts에서 페이지를 지정해서 호출하는 방식이 아니라 tile로 구성된 부분을 호출한다. 개발자의 작업 순서 tiles를 위한 플러그인 설정 tiles 정의 파일 작성 필요한 tile 작업하기 레이아웃 구성하기 필요 페이지 만들기
struts-config.xml파일에 plug-in 추가 Tiles를 이용할 수 있도록 ActionServlet 설정 변경 Struts1.3 이전의 버전 Struts 1.3 이후의 버전 <plug-in className="org.apache.struts.tiles.TilesPlugin" > <set-property property="definitions-config" value="/WEB-INF/tiles-defs.xml" /> <set-property property="moduleAware" value="true" /> </plug-in> <controller processorClass="org.apache.struts.tiles.TilesRequestProcessor"> </controller> <init-param> <param-name>chainConfig</param-name> <param-value>org/apache/struts/tiles/chain-config.xml </param-value> </init-param>
Tile 만들기 & 설정 파일 작업하기 tiles-defs.xml include 방식으로 만들어서 사용하던 페이지들을 각각의 타일로 사용 필요한 레이아웃 만들기 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE tiles-definitions PUBLIC "-//Apache Software Foundation//DTD Tiles Configuration 1.1//EN" "http://jakarta.apache.org/struts/dtds/tiles-config_1_1.dtd"> <tiles-definitions> <definition name="basic" path="/WEB-INF/jsp/main.jsp"> <put name="title" value="Sample Page Title" /> <put name="header" value="/tiles/header.jsp" /> <put name="left" value="/tiles/left.jsp" /> <put name="center" value="/tiles/center.jsp" /> <put name="right" value="/tiles/right.jsp" /> <put name="footer" value="/tiles/bottom.jsp" /> </definition> </tiles-definitions>
<%@page contentType="text/html; charset=euc-kr"%> <%@ taglib prefix="tiles" uri="http://struts.apache.org/tags-tiles"%> <%@ taglib uri="http://struts.apache.org/tags-html" prefix="html"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=EUC-KR"> <title>Insert title here</title> </head> <body> <table border='1' width="1024" height="800"> <tr> <td colspan="3"><tiles:insert attribute="header"/></td> </tr> <tr height="80%"> <td width="150"><tiles:insert attribute="left"/></td> <td ><tiles:insert attribute="center"/></td> <td width="50"><tiles:insert attribute="right"/></td> <td colspan="3"><tiles:insert attribute="footer"/></td> </table> </body> </html>
Tiles를 사용하지 않는 액션의 forward의 경로는 반드시 ‘/’로 시작해야 한다. Action 설정 및 페이지 사용하기 Tiles를 사용하지 않는 액션의 forward의 경로는 반드시 ‘/’로 시작해야 한다. Tiles를 이용하는 경우에는 ‘/’를 사용할 필요 없음 Action에서 보여지는 페이지를 작업하는 순서 1.실제 변경되는 페이지의 작업 2.타일즈 설정 파일을 통해서 나머지 페이지와 레이아웃 결정 3.Action에서 페이지의 경로를 tiles의 설정으로 설정 <definition name="bbs.main" extends="basic"> <put name="center" value="/WEB-INF/jsp/bbs/list.jsp" /> </definition> <action path="/bbsMain" forward="bbs.main"/>