670 likes | 860 Views
2008.11.02. 오픈 소스 기반 웹 어플리케이션 개발 가이드. Version 0.1. Agenda. Standard Annotations What is Good? What is better? Open Source Framework architecture WAS startup process Web Application configuration files Service flow overview Struts 2 & Spring 2 service flow
E N D
2008.11.02 오픈 소스 기반 웹 어플리케이션 개발 가이드 Version 0.1
Agenda • Standard Annotations • What is Good? What is better? • Open Source Framework architecture • WAS startup process • Web Application configuration files • Service flow overview • Struts 2 & Spring 2 service flow • How to make custom components • How to make AJAX call • How to make struts actions • Messaging service • ORWrapper • Build common modules • Deploy to server
Component Component Component Module Module Module Standard Annotations [ 네트워크 및 서비스 흐름 ] [ 서비스 분할 ] [ 컴포넌트 유형 ] 업무 묶음혹은 서버 솔루션 컴포넌트 Framework 컴포넌트 新 컴포넌트 네트워크 어댑터 솔루션 모듈 Framework 모듈 新 모듈 데이터 통신 서비스 호출 업무 구분 (영역) [ 서버 및 저장소 ] 소프트웨어 컴포넌트 블럭 Database or Repository 서버
What is Good ? What’s Good, What is Better Solution?
What is Good? – 좋은 시스템의 요건 생산성 신뢰성 성능 및 안정성
What is Good? – 관습적 개발 방식의 문제점들 • Copy & Paste !!! • - 소스 코드의 반복 • - 모든 페이지에 반복적인 소스 코드 삽입 뉴스 게시판 공지사항 게시판 소스분량 및 작업시간 증가 유지보수의 어려움
What is Good? – 기존 개발 방식의 문제점들 개발자의 어쩔 수 없는 실수 유발 - 인간이기 때문에… - 복사하면서 누락하거나, 개선된 사항을 과거의 코드에 반영하지 못하거나... 밤샘을 하던가… 코드 불일치 [ 잘못된 소스 ] [ 정확한 소스 ] 코드 누락 시 문제 발생 System Down !!!
Servlet, JSP request response 기존 웹 프레임 워크(MVC) 서비스 요청 What is Good? – 기존 개발 방식의 문제점들 특정 환경에 종속적인 구조 설계 - 하지만, 서비스 플랫폼은 끓임 없이 변화하고 -동일한 서비스 혹은 비즈니스인데도 불구하고 다시 개발하는 불상사 발생 WEB PDA 자동화기기 타 채널 적용 불가 Web 종속 서비스 다양화를 위한 인력, 시간, 비용 증가
회원 게시판 LINK 게시판 일반 게시판 What is Good? – 기존 개발 방식의 문제점들 똑같은 작업의 무한 반복 - 프로젝트가 진행되고, 서비스가 성공할 수록 오히려 해야 할 일들은 증가… • 생산성은 오히려 떨어지고 … 몇 년 후에는 아예 다시 설계하게 되고 … • 그리고, 상사의 질책과 야근은 늘어가고… 엄마가 보고 싶을 뿐이고… (왜 낳으셨나요?) • 코드의 증가로 인한 자원 낭비 • 개발자의 작업량 증가로 생산성 저하 및 개발 시간 연장
오픈소스 Framework SI Framework 상용 Framework 실제 프로젝트에서 생산성이 검증된 개발도구 지원 플랫폼 독립적이고 Layer의 구분이 명확한 아키텍처 표준기술 준수로 각종 솔루션 및 업무 시스템과의 유연한 연계 Framework 구성 요건 What is Good? – Open source framework Reasonable Proof
What is Good? – Struts 2 Simple view vs Detail View • Struts 2는 MVC(Model View Controller) 모델을 구현하는 프레임워크. • 내부적으로 WebWork 2 의 아키텍처를 수용하여 견고하고확장성이 높은 구조로 설계되어 있다.
What is Good? – Struts 2 • Interceptor 설정을 통해 기존의 반복된 소스 코드 작성을 대체한다. Struts2 based Project 관습적인 MVC Project 서비스 전,후에 실행되므로 각 페이지에 반복된 소스 삽입 불필요 설정파일이 제공되므로, 유지보수 및 개발의 편의성 제공 설정파일이 제공되므로, 유지보수 및 개발의 편의성 제공
DAO Spring JDBC Transaction management ORM Hibernate JPA TopLink JDO OJB iBatis JEE JMX JMS JCA Remoting EJBs Email Web Spring Web MVC Framework Integration WebWork Tapestry JSF Rich View Support JSPs Velocity FreeMarker PDF Jasfer Reports Excel Spring Portlet MVC AOP Spring AOP AspectJ integration Core The IoC container What is Good? – Spring 2 • Lightweight - 적은 시스템 자원 소모 (1MB 정도의 적은 JAR 크기) - 무시해도 되는 수준의 성능 부하- 어플리케이션이 프레임워크에 종속되지 않음. (침입적이지 않은 아키텍쳐) • IoC (Inversion of Control) - 제어 역행 기법을 통해 컴포넌트 간의 느슨한 결합(loosely couple component) 구현 • AOP (Aspect Oriented Programming) - 관점 지향 개발을 통해 비즈니스 로직 구현에 집중 가능- 서비스 실행 시 필요한 부가 기능을 설정 파일로 추가. (로그 생성, 프로파일링 기능 적용 용이) • Container - 객체의 생명 주기와 객체들 간의 관계를 제어- XML 설정 파일을 통해 선언적으로 컴포넌트 구성
What is Good? – Spring 2 • Spring Framework를 활용하여 타 채널(Mobile, PDA….)에서 • 재사용 가능한 컴포넌트 구현 가능 기존 웹 프레임 워크(MVC) Struts2 + Spring2 프레임워크 Presentation Layer System Servlet, JSP WEB Service Action Service Handler response request Struts Framework Spring Framework PDA Application Server 서비스 요청 Mobile 가능 개발 시간 단축 및 개발 생산성, 효율성 제공 불가능
What is Good? – Struts 2 + Spring 2 • 동일한 패턴의 반복적인 코드들을 하나의 모듈로 통합 Struts2 + Spring2 Project MVC Project Interceptor(s) Web Request Action (injected) Result 자원 낭비 감소, 유지보수 편리성, 개발 작업량 감소
프레임워크 설계 시에도 낮은 결합도 추구 은 탄환(silver bullet)은 없다. 완벽한 프레임워크도 없다. UI, business, repository 등 계층 별로 적절한 프레임워크 선정 재사용성을 극대화하고, 가시성을 높일 수 있다. 설계 및 교육에 따르는 비용 증가 지나치면 모자라는 것보다 못함 Framework 설계 요건 What is Good? – Struts 2 + Spring 2 + iBatis • 왜 2가지 이상의 프레임워크를 함께 사용하는가? Struts 2 Framework Spring Framework iBatis Framework
build components (dependency injection) 2.Get Instance 1.request Spring Container 3.request Service Component Struts dispatcher 5.response JSP 4.1 Call function Struts Action JSP JSP JSP Bean DB DB What is Good? – Struts 2 + Spring 2 Struts2 + Spring2 Project MVC Project 4.2 query
System Architecture Open Source Framework based System Architecture
Biz. 컴포넌트 서비스 실행 회원정보 조회 로그인 체크 예외처리 다국어 로그 메시지 JDBC Routing 웹 어플리케이션 구성도 서비스 클라이언트 웹 어플리케이션시스템 Legacy Systems 비즈니스 컴포넌트 Pool Request XML XML Parser PC RMI/IIOP Request Data Object TCP/IP PDA Service Dispatcher TCP/IP 서비스 DB XML Service Controller XML Mobile Response XML J2EE Framework 공통 컴포넌트 TV 메신저
웹 어플리케이션 구성도 (RMI based system example) IP : 192.17.10.49 IP : 19217.10.50 Dynamic Delivery Server Dynamic Contents Delivery Server RMI, 9004 port Relay Server Spring 2 & iBatis Framework Relay Server (Web Application Server) Apache Tomcat Server HTTP, 80 port Billing Manager (HTTP client) Request Parser (HTTP client) Admin Center Server Action (RMI client) Content Provider (RMI server) Admin Center (Web Application Server) RMI, 9001 port Query Handler (DB client) Remote File Server IP 192.17.10.51 RMI, 9003 port Contents Provider Gateway JDBC, 1521 port Contents Publisher (RMI Client) Oracle Database Contents & Profile Database CP Gateway (Web Application Server)
Service flow overview form submit or Ajax call 사용자 Web Application Server 방화벽 Internet Explorer or Firefox build components (dependency injection) Struts 2 Action Value Object Spring Container Service Provider Remote Call Struts dispatcher Business Service Component Persistence Layer Legacy Systems
UI Layer Service (Biz.) Layer JSP 2.0 (EL) JSTL 1.1 Custom Tags Ajax POJO Spring Bean Web Common Framework (Biz Components) Message Handling Constants & Configuration Session Management Security Utilities (String, Date) Exception Handling Logging (Infrastructure) UI Framework (Struts 2) Service Framework (Spring 2.0) Interceptors Action Dependency Injection Result Struts Tags Bean Management Web Application Server (JEUS, Web Logic, ETC) J2EE 6 J2SE 6.0 (SUN JDK 1.6) Open Source Framework architecture
Struts 2 & Spring 2 service flow Form submit or Ajax call Load Injected Action & components Struts 2 default & Custom interceptor Struts 2 Dipatcher Interceptor(s) Action (injected) Messaging Service Web Request HTML, Excel or JSON formatted data struts.xml Result Render JSP or JSON ORWrapper Execute Query Spring Context Loader Execute Dependency Injection Database applicationContext.xml
Framework library configuration – Log4j • <?xml version="1.0" encoding="UTF-8" ?> • <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"> • <appender name="CONSOLEAPPENDER" class="org.apache.log4j.ConsoleAppender"> • <layout class="org.apache.log4j.PatternLayout"> • <param name="ConversionPattern" • value="[%d{yyyy-MM-ddHH:mm:ss}] %-5p %C.%M(%L) - %m%n" /> • </layout> • </appender> • <appender name="FILEAPPENDER" • class="org.apache.log4j.RollingFileAppender"> • <param name="append" value="false" /> • <param name="file" value="/tmp/contents-adm.log" /> • <param name="maxFileSize" value="10MB" /> • <param name="maxBackupIndex" value="10" /> • <layout class="org.apache.log4j.PatternLayout"> • <param name="ConversionPattern" • value="[%d{yyyy-MM-ddHH:mm:ss}] %-5p %C.%M(%L) - %m%n" /> • </layout> • </appender> • <logger name="org.apache.struts2"> • <level value="WARN" /> • </logger> • <logger name="com.opensymphony.xwork2"> • <level value="WARN" /> • </logger> • <logger name="com.acme"> • <level value="DEBUG" /> • </logger> • <root> • <level value="DEBUG" /> • <appender-ref ref="FILEAPPENDER" /> • </root> • </log4j:configuration> {PROJECT-HOME}/src/log4j.xml 로그 파일 저장 경로 및 파일 명칭 지정 로그 파일 크기는 10MB로 지정하였으며, 변경 가능 최대 백업 횟수는 10회 com.acme패키지 및 하위 패키지에 포함된 클래스에서 생성되는 로그는 DEBUG 레벨까지 기록
Framework library configuration – Java Cache System JCS(Java Cache System) 라이브러리를 위한 설정 파일이다. 최대 2000개의 객체를 캐시(cache) 내에 저장하며, LRU(Lead Recently Used) 메모리 캐시 알고리즘을 사용한다. 디스크 등 외부 캐시를 사용하지 않고, 캐시에 저장된 객체의 유효 기간(생명 주기)는 5분으로 설정하였다. {PROJECT_HOME}/src/cache.ccf jcs.default= jcs.default.cacheattributes=org.apache.jcs.engine.CompositeCacheAttributes jcs.default.cacheattributes.MaxObjects=2000 jcs.default.cacheattributes.MemoryCacheName=org.apache.jcs.engine.memory.lru.LRUMemoryCache jcs.default.elementattributes=org.apache.jcs.engine.ElementAttributes jcs.default.elementattributes.IsEternal=false jcs.default.elementattributes.MaxLifeSeconds=300
Framework library configuration – iBatis 시스템에서 데이터베이스에 접근하기 위해 iBatis프레임워크를 사용한다. 데이터베이스 접근을 공통화 하기 위해 DB 연결을 위한 설정 파일은 공통(common) 프로젝트에 포함시켰으며, 개별 프로젝트에서 사용하는 쿼리는 프로젝트 별로 설정 파일을 작성한다. {PROJECT_HOME}/src/sqlmap-config.properties driver=oracle.jdbc.driver.OracleDriver url=jdbc:oracle:thin:@128.13.223.13:1521:MPDB username=DBUSER password=DBUSER
Framework library configuration – iBatis (continue) {PROJECT_HOME}/src/config/sql-map/sqlmap-config.xml <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE sqlMapConfig PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN" "http://www.ibatis.com/dtd/sql-map-config-2.dtd"> <sqlMapConfig> <properties resource="properties/sqlmap-config.properties"/> <settings cacheModelsEnabled="true" enhancementEnabled="true" lazyLoadingEnabled="true" maxRequests="32" maxSessions="10" maxTransactions="5" useStatementNamespaces="false" /> <transactionManager type="JDBC"> <dataSource type="DBCP"> <property name="driverClassName" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> <property name="maxActive" value="20"/> <property name="initialSize" value="5"/> </dataSource> </transactionManager> <sqlMap resource="config/sqlmap/board-sqlmap.xml"/> <sqlMap resource="config/sqlmap/member-sqlmap.xml"/> <sqlMap resource="config/sqlmap/file-sqlmap.xml"/> <sqlMap resource="config/sqlmap/device-sqlmap.xml"/> <sqlMap resource="config/sqlmap/bill-sqlmap.xml"/> </sqlMapConfig> 데이터베이스 접근을 위한 계정 및 암호는 공통 설정 파일을 참조한다. 쿼리를 포함하는 설정 파일을 기능 단위 별로 작성하며, sqlmap-config.xml 파일에서 참조 (include) 한다.
Struts dispatcher Spring Container Tiles setting listener WAS startup process 1) WebLogic Startup 3) Initialize Struts 2 framework <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class> </filter> 4) Initialize Spring 2 framework <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> WEB-INF/web.xml 2) Read web.xml 5) Initialize Tiles framework <listener> <listener-class>org.apache.tiles.web.startup.TilesListener</listener-class> </listener> 6) Initialize listener <listener> <listener-class>com.acmeweb.listener.CustomSessionListener</listener-class> </listener>
Web Application Configuration files ① 프로젝트 홈 디렉토리 ② 자바 소스 디렉토리 ③ 스프링 설정 디렉토리 ④ 스트럿츠 & 타일즈 설정 디렉토리 ⑤웹 어플리케이션 설정 디렉토리
Web Application Configuration files (Struts 2) Struts 2 Configuration <!-- 공통 설정 --> <include file="/config/struts/hana-struts-default.xml"/> <!-- 대메뉴별 메뉴 설정 --> <include file="/config/struts/struts-pbk-banka.xml"/> <include file="/config/struts/struts-pbk-card.xml"/> {PROJECT_HOME}/src/struts.xml root config file {PROJECT_HOME}/src/config/struts/struts-pbk-banka.xml {PRJOECT_HOME}/src/config/struts/struts-pbk-card.xml include sub-menu config files • {PRJ_HOME}/src/struts.xml 파일은 ‘스트럿츠 루트 설정’파일이며, 가장 먼저 로딩된다. (스트럿츠 프레임워크는 CLASS_PATH에 등록된 경로를 스캔하여, struts.xml 파일을 찾는다.) • 공통(global) 설정 항목은 ‘/config/struts/hana-struts-default.xml’파일에 정의한다. • 각 메뉴(혹은 서비스) 별 액션 설정은 대메뉴별로 구분하여 설정 디렉토리에 등록하며, struts.xml 설정 파일에서 포함(include) 시킨다.
Web Application Configuration files (Tiles) Tiles Configuration <context-param> <param-name>org.apache.tiles.impl.BasicTilesContainer.DEFINITIONS_CONFIG</param-name> <param-value>/WEB-INF/classes/config/struts/tiles-pbk.xml</param-value> </context-param> WEB-INF/web.xml declare spring config location {PRJECT_HOME}/src/config/struts/tiles-pbk.xml set configuration files location • Tiles 설정 파일 위치는 ‘WEB-INF/web.xml’파일에서 선언한다.
Web Application configuration files (Spring 2) Spring 2 Configuration <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:config/spring/applicationContext-*.xml</param-value> </context-param> WEB-INF/web.xml declare spring config location {PRJECT_HOME}/src/config/spring/applicationContext-rule.xml {PRJECT_HOME}/src/config/spring/applicationContext-service.xml set configuration files location {PRJECT_HOME}/src/config/spring/applicationContext-struts.xml • 스프링 설정 파일 위치는 ‘WEB-INF/web.xml’파일에서 선언한다. • 스프링 설정 파일은 3개의 영역으로 분리하여 작성한다. applicationContext-rule.xml : 입력 전문 빈(도메인 객체)을 설정한다. applicationContext-service.xml : 전문(message) 송수신을 처리하는 서비스 빈(컴포넌트)을 설정한다. applicationContext-struts.xml : 스트럿츠 액션 빈(컴포넌트)을 설정한다.
System Architecture Workspace, Project, Build & Deploy
Workspace & projects contents 공통 라이브러리 RMI File Transfer Library contents-RFS contents-DYN contents-CTS contents-RLY contents-ADM contents-COM contents-GW Contents Delivery Server Dynamic Delivery Server Gateway Server contents-RMIIO Admin Server Remote File Server Relay Server
Common project root Project Root
Deploy common module {WORKSPACE}/{COMMON}/build.xml contents-CTS contents-RLY contents-RFS <project name=“Project common library“ basedir="." default=“all"> <property name="java.dir" value="${basedir}/src" /> <property name="jar.file.path" value="${basedir}/contents-common.jar" /> <target name="deploy"> <jar destfile="${jar.file.path}"> <fileset dir="${classes.dir}"/> </jar> <copy file="${jar.file.path}" todir="${basedir}/../contents-CTS/lib"/> …… 생략 …… <copy file="${jar.file.path}" todir="${basedir}/../contents-RLY/lib"/> <delete file="${jar.file.path}"/> </target> </project> contents-GW contents-DYN contents-ADM execute ANT build script (delpoy jar file) 프로젝트 공통 라이브러리 utilities file I/O constants SQL map client load configuration • 시스템의 공통 라이브러리는 PRJ-COM 프로젝트에서 관리되며, 각 프로젝트에서 사용하기 위해서는 배포(deploy) 작업이 필요하다. • 공통 라이브러리에 추가, 변경 사항이 발생할 경우 ANT 빌드(build)를 수행하여 각 단위 프로젝트에 적용하는 작업을 수행해야 한다.
Deploy project 1. 최신 작업 파일 업데이트 {WORKSPACE}/scripts/build.xml ant build-all : 전체 프로젝트를 빌드(build)한다. ant clean : 모든 목적 파일(object files)을 삭제한다. ant backup : clean 태스크를 실행한 후,워크스페이스 전체를 zip으로 압축한다. [ant deploy] or [ant] : 전체 프로젝트를 빌드(build)한 후,개발 서버로 배포한다. (기본) ant javadoc : javadoc help 파일을 작성한다. 개발자 PC CVS 서버 2. 완성도 검사 컴파일 오류 확인. 3. 배포 실행 자원(resource) 업로드 개발 서버 4. 정상 동작 확인 Web Server & Daemon 재기동 각종 기능 오동작 여부 확인 로그 파일 점검 배포자
System Architecture Make Common Components
Prepared Actions (HanaAction) • HanaAction은 struts frameworkActionSupport를 상속하는 하나은행 인터넷뱅킹 시스템 내의 최상위 액션(action) 클래스이다. • 추상 클래스이며, 모든 구현 액션 클래스(concrete action class)는 HanaAction 클래스로부터 상속 되어야 한다. • ServletRequestAware, SessionAware 인터페이스를 구현했기 때문에 인터셉터(interceptor)에 의해 session, request 속성이 자동으로 설정된다. • 액션 실행 시 발생한 오류 목록은 actionErrorList, 결과(result)로 전송해야 할 데이터는 actionMap속성에 기록한다. • 하위 클래스에서 비즈니스 로직(business logic)을 구현하기 위해서는 service()추상 메소드를 구현해야 한다.
Prepared Actions (HanaBizAction) • HanaBizAction은 전문 거래 서비스를 실행하는 클래스들을 위한 추상 클래스이다. • 모든 전문 거래 클래스(message transaction class)는 HanaBizAction 클래스로부터 상속 되어야 한다. • Preparable, Completable 인터페이스를 구현했기 때문에 인터셉터(interceptor)에 의해 prepare(), comple() 메소드가 호출된다. • ModelDriven 인터페이스를 구현했기 때문에 인터셉터에 의해 request 인자를 inputMsg 멤버 속성에 자동으로 설정(mapping) 한다. • HanaActionWiring 인터페이스를 구현했기 때문에 인터셉터에 의해 서비스 객체가 자동 설정된다. • 전문 호출을 위해 service 객체와 service ID를 입력 받아야 한다. (struts.xml에 action 추가 시 인자로 설정) • 액션 설정 시 ‘echo = true’로 설정할 경우, 전문 거래를 수행하지 않고 echo 전문을 반환한다. • 하위 클래스에서 비즈니스 로직(business logic)을 추가하기 위해서는 service() 메소드를 재선언(override) 해야 한다.
Prepared Actions (HanaNormalAction) • HanaNormalAction은 전문 거래 서비스를 실행하지 않는클래스들을 구현하기 위한 추상 클래스이다. • 모든 비 전문거래 클래스(non message-transaction class)는 HanaNormalAction 클래스로부터 상속 되어야 한다. • 하위 클래스에서 비즈니스 로직(business logic)을 추가하기 위해서는 service() 추상 메소드를 구현해야 한다.
Prepared Actions (DefaultBizAction) • DefaultBizAction은 전문 거래 서비스 중 by-pass 패턴 전문을 처리하기 위한 구현 클래스(concrete class) 이다. • 비즈니스 로직을 구현할 필요한 없는 전문인 경우, DefaultBizAction 컴포넌트를 호출해야 한다.
Prepared Actions (Actions overview) • Struts 2 Action을 응용하는 방법은 3가지로 분류된다. • 첫째, 전문 거래를 포함하지 않는 서비스인 경우HanaNormalAction 클래스를 상속한 클래스를 구현한다. • 둘째, 전문 거래를 실행하되, by-pass 성격인 경우DefaultBizAction 클래스를 사용한다. • 셋째, 전문 거래를 실행하며, 전문 입출력 처리 중 부가적인 비즈니스 로직을 구현해야 할 경우HanaBizAction 클래스를 상속한 클래스를 구현한다.
Prepared Interceptors Strutscomponents HanaBank interceptors • 하나은행 웹 서비스의 전처리(pre-processing)를 위해 스트럿츠 인터셉터를 확장(상속)한 인터셉터들을 구현한다. • 서비스 구현 시 스트럿츠 기본 인터셉터 스택(default stack)과 함께 사용된다.
Prepared Interceptors (description) • HanaInterceptor- 하나은행 인터셉터 구현을 위한 추상 클래스. 구현 클래스에서 필요한 유틸리티 메소드를 정의한다. • HanaTokenInterceptor - 이중 거래 방지를 위한 토큰 처리를 수행하는 인터셉터 • CertInterceptor - 공인인증서 처리를 수행하는 인터셉터 • HanaActionWiringInterceptor - Struts Action 컴포넌트에 service 컴포넌트를 삽입하는 인터셉터 • TimeAcceptInterceptor - 거래 시간 제한을 수행하는 인터셉터. 허용된 거래 시간 외에 접속할 경우, REJECT_TIME 반환. • RequiredLoginInterceptor - 로그인 여부를 검사하는 인터셉터. 세션에 로그인 정보가 포함되어 있는지 검사한다. • RequiredTransferInterceptor - 거래 가능 여부를 검사하는 인터셉터. 세션에 저장된 거래 가능 상태를 확인한다. • CompleteInterceptor - 후처리(post processing) 인터셉터. 개별 action 클래스에 구현된 complete() 메소드를 호출한다.
Prepared Interceptors (configuration) Struts 2 Configuration <!-- 공통 설정 --> <include file="/config/struts/hana-struts-default.xml"/> {PRJ_HOME}/src/struts.xml <interceptors> <interceptor name="timeAccept" class="com.hanabank….TimeAcceptInterceptor"> <param name="timeResource">accepttime-pbk.properties</param> </interceptor> …. root config file define interceptors & interceptor stack • 인터셉터 목록 및 인터셉터 스택은 ‘{PRJ_HOME}src/config/struts/hana-struts-default.xml’파일에 정의한다.