contextConfigLocation

2012. 7. 4. 12:44

스프링에서는 설정파일에서 모든 것을 명시해주기 때문에 설정파일이 중요한데
설정파일 안에는 dataSource, bean(dao, service) 등 필요한 모든 객체가 다 들어있다.
그럼 이 설정파일들은 어떻게 해서 컨테이너 안에서 동작을 하는지? 어떻게 xml 설정파일을 읽는지 
스프링 프레임웍이 어떻게 동작하는지 궁금하다.

가장 기본은 web.xml 파일에 스프링 설정 파일을 명시해주면 된다는 것.
스프링 설정파일을 읽어 들이기 위해서 org.springframework.web.context.ContextLoaderListener 가
필요하다. 이 리스너가 동작해야 설정파일을 읽어들이고 필요한 객체들을 등록하고 만드는 것이다.
그럼 리스너는 동작을 하는데 설정파일의 위치를 알려주어야 할 것이 아닌가 그래서
<context-param> 안에 contextConfigLocation 이라고 해서 위치를 지정해 주는 것이다.
하나의 파일이든 여러개든 명시해서 읽어올 수 가 있다.


그럼 이제 그 방법을 자세히 보자.
                                                                               출처 : 
http://mars0717.egloos.com/1326159

계층별로 나눈 xml 설정파일이 있다고 가정할 때,
web.xml에서 모두 load되도록 등록할 때 사용.
서블릿이전에 서블릿 초기화하는 용도록 쓰이며, 
contextConfigLocation라는 파라미터를 쓰면, 
Context Loader가 load할 수 있는 설정파일을 여거개 쓸 수 있다.

web.xml에 저 문장이 빠지게 되면 default로,
/WEB-INF/applicationContext.xml (spring 설정파일) 을 쓰게 된다.

[web.xml]

<context-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>
           /WEB-INF/mars-ibatis.xml 
           /WEB-INF/mars-service.xml 
      </param-value>
</context-param>

<listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

'스프링3.0' 카테고리의 다른 글

MyBatis  (0) 2012.07.03
스프링 3.0 + ibatise  (0) 2012.07.03
Srping 3.0 sqlSession+DataSource 구현 하기. (Spring+mybatise0  (0) 2012.05.19
web.xml 구현부 encoder  (0) 2012.05.19
Spring 개발 환경 .  (0) 2012.05.19
Posted by 사라링

MyBatis

2012. 7. 3. 14:20

Deprecated. (구버전, 교체됨)

Version 3를 사용하세요~

 

MyBatis에서 특정 테이블의 컬럼목록 가져오기

가끔 특정 테이블의 컬럼의 목록을 구할 필요가 있을 때가 있다. DBMS에서 테이블의 정보를 구해오는 것은 각각의 DB마다 상이하다. (예. 오라클의 경우는 딕셔너리 테이블에서 가져올 수 있다) JDBC의 메타데이터를 이용하면 쉽게 가져올 수 있다.

참고 : Get column names of a table using ResultSetMetaData

그럼 MyBatis를 사용해서 DB Mapper를 사용하는 경우 별도의 JDBC 연결 설정을 만들어서 이용해야 하나?

그러면 DB 접속 환경이 한군데가 변하게 되면 MyBatis 및 JDBC 모두 변경을 해야 한다. 이것은 중복이다. DRY원칙 위반이다. 설정값을 하나로 이용하는 방법도 있지만 이것 역시 귀찮다.

 

쉬운방법으로는 SqlSessionFactory에서 openSession() 메소드를 통해 세션을 연 다음 SqlSession 인터페이스에서

getConnection() 메소드를 이용하여 java.sql.Connection을 가져오면 JDBC의 기능을 온전히 이용할 수 있다.

말로만 설명하면 어려우니 예제를 보여주겠습니다.

  1. SqlSession session = sqlMapper.openSession();   // sqlMapper는 SqlSessionFactory 타입입니다.
  2. try {
  3. Statement statement = session.getConnection().createStatement();
    ResultSet resultSet = statement.executeQuery("SELECT * FROM someTabe WHERE 0=1");
    ResultSetMetaData metadata = resultSet.getMetaData();
    int columnCount = metadata.getColumnCount();
  4. ArrayList<String> columns = new ArrayList<String>();
    for (int i = 1; i < columnCount; i++) {
     String columnName = metadata.getColumnName(i);
     columns.add(columnName);
    }
  5. } finally {

    session.close();

    }

위에서 보면 columns라는 ArrayList타입의 리스트에 컬럼명을 넣습니다.

executeQuery에서 'WHERE 0=1'로 거짓조건을 주는 이유는 데이터를 가져오지 않게 하기 위함입니다.

columns를 이용해서 컬럼 목록을 이용하면 됩니다. 

이름의 변경

SQL 매핑 프레임워크 iBATIS가 이름이 MyBatis로 바뀌었다.

클린턴 비긴이 처음 개발했던 아이바티스는 아파치 프로젝트로 들어갔다가 2010년 6월 16일 은퇴(retire)하고 구글 코드쪽에서mybatis라는 이름으로 이동했다. 지금 시점(2010 12월)에서는 MyBatis 3.0.3 버전이 릴리즈 되어 있다.

SQL 주입(injection)에 대한 기사

“카드 정보 1억 3,000만 건 도난”, 주범은 SQL 인젝션

 

iBatis 사용시 XML상의 reference 관련 error시

이클립스에서 느낌표가 나오면 왠지 모르게 짜증이 난다

error.png

[기존]

  1. <!DOCTYPE sqlMapConfig PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN"
    "http://www.ibatis.com/dtd/sql-map-config-2.dtd">

[수정]

  1. <!DOCTYPE sqlMapConfig PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">

주소가 수정되었나보다. 브라우저에서 주소창에 치면 이전 것도 다운로드 되는데 이클립스에서는 왜 안되지?

다른 sql-map, dao도 올려놓자

  1. <!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd">
    <!DOCTYPE dao PUBLIC "-//ibatis.apache.org//DTD DAO Configuration 2.0//EN" "http://ibatis.apache.org/dtd/dao-2.dtd">

아놔~ 그 문제인줄 알았는데,

회사에서는 외부 인터넷에 연결하기 위해서 프록시 서버를 연결해야 하는데 이클립스에 세팅을 해줘야 하기 때문이었다.

네트워크 연결이 안되니 dtd 파일을 다운받을 수 없고 xml validation도 할 수 없는 것이 었다.

conn.png

 

 iBATIS in Action
(쉽고 강력한 SQL 매핑 프레임워크 아이바티스)

위 책의 필요한 사전 배경지식: Java, JDBC(매핑+), SQL, XML

외부 링크 : 아이바티스 커뮤니티(http://ibatis.apache.org)

SVN : Subversion Source Control

JIRA: for 이슈 트래킹(아틀라시안)

Confluence : wiki 문서 작성

 소스 코드 : 매닝 출판사 웹 사이트(www.manning.com/begin)
                 위키북스 오픈소스 & 웹 시리즈 에디터 일래스틱 온라인(http://web2.0business.or.kr/)

 

  • 머리말

    • 프레임워크 - 사전적 의미(뼈대, 틀, 골자)
    • 향상 : 가독성, 유지보수성, 생산성
    • 퍼시스턴스 계층에 적용할 프레임워크

      • 아이바티스 - JDBC
      • 객체 관계 매핑 툴(ORM) -  하이버네이트 / TopLink
    •  iBATIS : 더 빠른 JDBC 코딩을 위한 일반화된 프레임워크

      • SQL 매퍼 + DAO 프레임워크

 

 요약 (iBATIS)

  • SQL 매핑으로 객체를 관계형 데이터베이스에 저장
  • 애플리케이션이 퍼시스턴스 계층에 일관성있게 접근하는 것을 도와줌
  • 전사적인 수준의 퍼스스턴스 계층에 보다 적함(소규모 시스템에 비교하여)
  • 특징

    • 간단함 - 간단한 퍼시스턴스 프레임워크
    • 생산성 - 62%정도 줄어드는 코드(JDBC와 비교하여), 간단한 설정(근거: 이탈리안 자바 사용자 그룹의 연구)
    • 성능 - 구조적 강점(데이터 접근 속도 높여주는 JOIN매핑)

      • 여러가지 방식의 데이터 가져오기 전략(가져오기 미루기, SQL 줄이기 기법)
    • 관심사의 분리 - 설계를 향상(차후 유지보수성 위해)

      • 리소스를 관리하여 계층화를 지원(커넥션, PreparedStatement, 결과셋)
    • 작업의 분배 - 팀을 세분화하는 것을 도움

      • SQL 문이 애플리케이션 소스 코드로부터 완전히 분리
    • 이식성 - 어떤 프로그래밍언어로도 구현 가능

      • 예) 자바, C#(iBATIS.NET), Ruby(RBATIS)
    • 오픈소스 - 무료+ 커뮤니티티
  • 언제 사용하지 말아야 하나?

    • 개발자가 모든 것에 대해 영원한 결정권 소유

      • 애플리케이션 설계와 데이터베이스 설계에 대한 모든 결정권 보유
      • iBATIS는 관계형 데이터베이스를 위해 설계
      • => 관계 매핑 솔루션(ORM;하이버네이트..) 사용 - 설계시 이점, 생산성 향상
        예) JIRA(이슈 트래킹 패키지 소프트웨어 제품)
    • 완전히 동적인 SQL을 요구시

      • 애플리케이션의 핵심 기능 : SQL을 동적으로 생성일 경우
      • iBATIS의 사용이유: 수작업 SQL 구문 작성, 관리
      • 애플리케이션 -> 대부분의 SQL 구문이 SQL 자동 생성 클래스 로부터 동적으로 생성시 위의 장점은 무의미
    • 비 관계형 데이터베이스 사용

      • 파일, 엑셀, XML
      • => 순수한 JDBC, 저수준 파일 입출력 API 권장장
    • 요구사항과 상반되는 개발 방향, 설계지침 - 복잡도 증가, 프레임워크 자체의 역할 범위 넘어서는 것
  • (주로)관계형 데이터베이스를 위해 설계

    • 비-관계형 기술(일반적 파일, XML, 엑셀 스프레드 시트)사용시 타 API 이용이 효과적
  • 객체 관계 매퍼(ORM) - 애플리케이션~데이터베이스에 대한 결정권 보유
  • JDBC - 주로 동적으로 생성되는 SQL 코드로 작업하는 애플리케이션

 

x설치와 설정 (iBATIS)

  • 배포판 얻기

    1. 바이너리 배포판: 가장 빠르고 쉬운 방법

      • 컴파일된 상태 -> 다운받아 압축을 풀고 사용
    2. 소스로부터 빌드하기

      • 프레임워크를 확장, 버그 수정
      • 소스코드를 직접 컴파일 결과 확인시
    • 배포판의 구조

      • ibatis-2.3.0.677.png
      • 2.3.0.677에서는 jar 파일들(/lib 디렉토리내)가 ibatis-2.3.0.677.jar로 하나로 통합되었다.
      • /doc

        • user-javadoc.zip : for iBATIS 프레임워크를 사용해서 개발을 하는 사용자들
        • dev-javadoc.zip : for iBATIS 프로젝트의 모든 JavaDoc 문서를 포함하고 있는 파일
      • /lib

        • ibatis-common-2.jar : SQL Maps와 DAO 프레임워크 모두가 사용하는 공통 컴포넌트 포함
        • ibatis-sqlmap-2.jar : SQL Maps 프레임워크의 컴포넌트들을 포함하고 있는 파일
        • ibatis-dao-2.jar : DAO 프레임워크 컴포넌트들을 포함하고 있는 파일
      • /src

        • ibatis-src.zip : 프레임워크의 JAR파일을 빌드하는데 사용된 전체 소스를 포함하고 있는 파일
  • 애플리케이션에 iBATIS 붙이기

    • 클래스패스 추가(iBATIS 파일 경로 컴파일시, 실행시)

      • 단독 실행 애플리케이션

        • 클래스패스 옵션 추가

          1. java -cp ibatis-sqlmap-2.jar:ibatis-common-2.jar:. MyMainClass
      • 웹 애플리케이션

        • iBATIS의 jar 파일들을 WEB-INF/lib 디렉토리에 둔다
    • JRE 공유 디렉토리(lib/ext 디렉토리)에 올려서 사용가능하지만 가급적 피할 것

      1. 애플리케이션 변경되어 파일 수정시 공유하고 잇는 파일을 참조하는 모든 애플리케이션을 테스트 필요
      2. 클래스로더 문제((두 개의 서로 다른 클래스로더가 읽으면 서로 다른 클래스로 간주: 정적변수 공유 X)

 

  • SQL Maps 설정 파일

    • <SqlMapConfig.xml>

      1. <!SqlMapConfig.xml SQL Map configuration file-->

        <?xml version="1.0" encoding="UTF-8"?>
        <!-- 유효성 체크를 위한 DOCTYPE과 DTD를 적는다 -->
        <!DOCTYPE sql-map-config
            PUBLIC "-//iBATIS.com//DTD SQL Map Config 1.0//EN"
           "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">
        <sql-map-config>
            <properties resource="db.properties" />
        <!-- 전체 설정 옵션 -->
            <settings
                useStatementNamespaces='false'
                cacheModelsEnabled='true'
                enhancementEnabled='true'
                lazyLoadingEnabled='true'
                maxRequests="32"
                maxSessions="10"
                maxTransactions="5"
                />
        <!-- 트랜잭션 매니저 -->
            <transactionManager type="JDBC" >
                <dataSource type="SIMPLE">
                    <property name="JDBC.Driver" value="${driver}"/>
                    <property name="JDBC.ConnectionURL" value="${url}"/>
                    <property name="JDBC.Username" value="${user}"/>
                    <property name="JDBC.Password" value="${pword}"/>
                </dataSource>
            </transactionManager>
        <!-- SQL Map을 기술 -->
            <sql-map resource="sqlMap.xml" />
         
        </sql-map-config>
    • <properties> 요소 - 외부에서 이름/값 쌍의 리스트를 제공

      • 장점 : 공통 설정 부분은 모두 한 곳에 두고 각 환경별로 다른 값들을 properties 파일에 독립 가능
      • 속성

        • resource - 클래스 패스상에 있는 리소스(or 파일)

          • 클래스 로더가 애플리케이션의 클래스패스에서 그 리소스를 찾으려는 시도 함
          • 소스(db.properties)

            • driver=oracle.jdbc.driver.OracleDriver
              url=jdbc:oracle:thin:@localhost:1521:orcl
              user=scott
              pword=tiger
        • url - URL, java.net.URL에 의해 처리
    • <setting> 요소

      • useStatementNamespaces - 매핑 구문이 적절한 이름을 가지고 있어야 iBATIS가 실행 가능하도록 하는 옵션, 값(true/false)
      • cacheModelsEnabled - 캐시(차후 참조 가정->메모리 계속 저장), 값(true/false)
      • enhancementEnabled - CGLIB(실행 시간에 코드를 생성하는 라이브러리)에 최적화된 클래스-> 적재 지연 성능 향상 여부 지정, 값(true/false)
      • lazyLoadingEnabled - 적재 지연(필요할 때만 정보를 읽어들이는 기술), 값(true/false)
      • maxRequests - SQL작업(입력/수정/삭제/저장 프로시저 호출)의 한번에 수행가능한 개수, 기본값: 512
      • maxSessions - 세션(스레드, 관련되어 있는 트랜잭션과 요청의 묶음에 대한 정보 추적 사용), 기본값: 128
      • maxTransactions - 데이터 트랜잭션의 개수, 기본값: 32
    • <typeAlias> 요소 - FQCN(완전한 형태의 클래스 이름, Fully Qualified Class Name) 대신 별칭을 붙임

      • 예)

        • <typeAlias alias="Account"
                type="org.apache.ibatis.jgamestore.domain.Account" />
      • 기본 내장 별칭들

        • 트랜잭션 매니저의 별칭

          • JDBC <- com.ibatis.sqlmap.engine.transaction.jdbc.JdbcTransactionConfig
          • JTA <- com.ibatis.sqlmap.engine.transaction.jta.JtaTransactionConfig
          • EXTERNAL <- com.ibatis.sqlmap.engine.transaction.external.ExternalTransactionConfig
        • 데이터 타입

          • string <- java.lang.String
          • byte <- java.lang.Byte
          • long <- java.lang.Long
          • short <- java.lang.Short
          • int <- java.lang.Integer
          • integer <- java.lang.Integer
          • double <- java.lang.Double
          • float <- java.lang.Float
          • boolean <- java.lang.Boolean
          • decimal <- java.math.BigDecimal
          • object <- java.lang.Object
          • map <- java.util.Map
          • hashmap <- java.util.HashMap
          • list <- java.util.List
          • arraylist <- java.util.ArrayList
          • collection <- java.util.Collection
          • iterator <- java.util.Iterator
        • 데이터 소스 팩토리 타입

          • SIMPLE <- com.ibatis.sqlmap.engine.datasource.SimpleDataSourceFactory
          • DBCP <- com.ibatis.sqlmap.engine.datasource.DbcpDataSourceFactory
          • JNDI <- com.ibatis.sqlmap.engine.datasource.JndiDataSourceFactory
        • 캐시 컨트롤러 타입

          • FIFO <- com.ibatis.sqlmap.engine.cache.fifo.FifoCacheController
          • LRU <- com.ibatis.sqlmap.engine.cache.Iru.LruCacheController
          • MEMORY <- com.ibatis.sqlmap.engine.cache.memory.MemoryCacheController
          • OSCACHE <- com.ibatis.sqlmap.engine.cache.OSCacheController
        • XML 결과 타입

          • Dom <- com.ibatis.sqlmap.engine.type.DomTypeMarker
          • domCollection <- com.ibatis.sqlmap.engine.type.DomCollectionTypeMarker
          • Xml <- com.ibatis.sqlmap.engine.type.XmlTypeMarker
          • XmlCollection <- com.ibatis.sqlmap.engine.type.XmlCollectionTypeMarker
    • <transactionManager> 요소

      • type - 어떤 트랜잭션 관리자르 사용할지 결정

        • JDBC : 간단한 JDBC 기반 트랜잭션 관리 기능 제공
        • JTA : 컨테이너 기반한 트랜잭션 관리 기능 제공
        • EXTERNAL : 트랜잭션 관리자를 제공하지 않고 iBATIS 대신 애플리케이션이 직접 트랜잭션을 관리한다고 가정
      • commitRequired - 커넥션을 닫기 전에 commit/rollback 제어시, 기본값: false
      • <property> 요소 - 각 트랜잭션 관리자 서로 다른 설정 옵션 가능
      • <dataSource> 요소 - javax.sql.DataSource 객체를 사용 -> 커넥션 풀 작업을 표준화
      • type 속성 - 어떤 클래스의 객체를 생성해서 데이터 소스 팩토리를 얻어올지를 정하는 속성

        • SIMPLE - 간단한 커넥션 풀을 내장한 데이터 소스를 설정하고자 할 때(JDBC 드라이버만 빼고 데이터 소스에 필요한 모든 것을 자체 내장)
        • DBCLP - Jakarta Commons Database Connection Pool 구현을 제공
        • JNDI - JNDI(Java Naming and Directory Interface)를 통해 할당된 컨테이너 기반의 데이터 소스를 공유하도록 사용
      • <typeHandler>

        • 타입 핸들러 이용: JDBC 데이터베이스 전용 데이터형 -> 애플리케이션의 데이터형 변환(번역기)
    • <sqlMap> 요소

      • resource - SQL Map 파일을 자바 클래스패스에 두고 리소스로서 참조
      • url - java.net.URL 클래스가 인식하는 임의의 URL 값 이용

 

  • SQL Map API

    • SqlMapClient 인터페이스

      • queryForObject() - 데이터베이스로부터 한 개의 레코드를 가져다가 자바 객체에 저장

        • Object queryForObject(String id, Object parameter) throws SQLException;

          • 디폴트 생성자를 가진 객체를 생성(보편적 방법)
          • 디폴트 생성자가 없으면 throws "런타임 예외"
        • Object queryForObject(String id, Object parameter, Object result) throws SQLException;

          • 반환하는 값으로 사용될 객체를 받음
          • 결과값 -> 파라미터의 형태로 객체에 지정
          • 생성자가 protected / 디폴트 생성자가 없어서 객체를 쉽게 생성할 수 없을 때 유용
      • queryForList() - 한 개 이상의 레코드를 가져와서 자바 객체의 List를 만드는 데 사용

        • List queryForList(String id, Object parameter) throws SQLException;

          • 매핑 구문이 반환하는 모든 객체를 반환
        • List queryForList(String id, Object parameter, int skip, int max) throws SQLException;

          • 전체 결과의 일부만을 반환
          • skip : 지정된 개수만큼 건너뛰고
          • max : 지정된 개수의 레코드만 반환
          • 2.3버전부터 비권장
      • queryForMap() - 데이터베이스로부터 한 개 혹은 그 이상의 레코드를 가져올 때 자바 객체의 Map을 반환

        • Map queryForMap(String id, Object parameter, String key) throws SQLException;

          • 퀴리 실행후 Map 객체를 생성하여 반환
          • key : 결과 객체를 가리키는 키, -> 지정된 프로퍼티의 값

            • Map accountMap = sqlMap.queryForMap(
                 "Account.getAll", null, "accountId");
              System.out.println(accountMap);
        • Map queryForMap(String id, Object parameter, String key, String value) throws SQLException;

          • 결과값 객체 -> value 파라미터에 지정된 프로퍼티 값이 됨

            • accountMap = sqlMap.queryForMap(
                 "Account.getAll", null, "accountId", "username");
              System.out.println(accountMap);
  • non-query 구문

    • 데이터 갱신

      • insert 메소드

        • Object inser(String id, Object parameterObject) throws SQLException;

          • 파라미터 : 실행할 매핑 구문의 이름, 파라미터 객체(데이터베이스에 데이터 삽입하는 데 사용)
          • 반환 : 객체
      • update 메소드

        • int update(String id, Object parameterObject) throws SQLException;

          • 파라미터: 실행할 매핑 구문의 이름, 값을 제공하는 데 사용할 파라미터 객체
          • 반환: update 구문에 의해 영향을 받은 레코드의 개수
      • delete 메소드

        • int delete(String id, Object parameterObject) throws SQLException;

          • 파라미터: 실행할 매핑 구문의 이름, 값을 제공하는 데 사용할 파라미터 객체
          • 반환: 삭제된 레코드의 개수
    • 매핑 구문

      • <insert> | id, parameterClass, parameterMap

        1. <parameterMap id="fullParameterMapExample" class="Account">
              <parameter property="accountId" jdbcType="NUMBER" />
              <parameter property="username" jdbcType="VARCHAR" />
              ...
          </parameterMap>

          <insert id="insertWithExternalInfo"
              parameterMap="fullParameterMapExample">
              insert into account (
                  account Id,
                  username, ...
              ) values (
                  ?, ? , ...
              )
          </insert>
        2. in Java 사용
          sqlMap.insert("Account.insertWithExternalInfo", account);
      • <update> | id, parameterClass, parameterMap
      • <delete> | id, parameterClass, parameterMap
      • <procedure> | id, parameterClass, resultClass, parameterMap, resultMap, xmlResultName
      • <sql> | id

        • 매핑 구문은 아니지만, 매핑 구문 내에서 사용될 수 있는 컴포넌트를 만들기 위해
      • <include> | refid

        • 매핑 구문은 아니지만, 매핑 구문에 <sql>타입으로 생성된 컴포넌트를 삽입하기 위해
  • iBATIS에서 XML 사용

    • XML 파라미터

      • <select id="getByXmlId" resultClass="Account" parameterClass="xml">
           ...
    • XML로 결과 생성

      • <select id="getByValueXml" resultClass=""xmlxmlResultName="account">
              ...

MVC 모델

  • Hierachy.png
  • 비지니스 객체 모델(도메인 클래스) : 처리할 도메인을 객체 지향적으로 묘사

    • 특정 비지니스 로직의 기능을 수행하기 위해 사용
    • 명사 -> 이름 -> 클래스
    • 약간의 로직 포함 가능(다른 계층에 접근하는 코드 금지)
    • 퍼시스턴스 계층의 메소드들의 파라미터의 반환값
  • 프리젠테이션 계층 : 출력(애플리케이션의 데이터/제어화면)하는 역할

    • 모든 정보의 레이아웃, 출력 형식을 정의
    • 예. HTML + JavaScript
    • 웹 애플리케이션

      • 장점: 플래폼에 독립적, 배포와 확장이 쉬움
      • 단점: 높은 수준의 사용자 제어 방식, 복잡한 데이터 처리 어려움

        • => 운영 시스템 위젯 사용하는 리치 클라이언트 방식(탭, 표, 트리, 내장 객체)
    • 리치 클라이언트 방식

      • 장점: 강력한 사용자 인터페이스
      • 단점: 배포의 어려움, 성능, 보안에 손이감
      • 예> Swing(자바), WinForms(.NET)
    • 복합적 리치 클라이언트(웹 애플리케이션 + 리치 클라이언트 방식)

      • 웹 서비스 <= 겉 모양, 비지니스 기능
      • XML <= 리치 클라이언트와 서버 간의 매개체
      • 단점: 애플리케이션의 개발과 배치에 더 많은 소프트웨어 필요

        • 예) Flex(매크로미디어), Flash 브라우저 플러그인(Laszlo시스템), Ajax(Asynchoronous JavaScript And XML)
  • 비지니스 로직 계층(서비스 클래스) - 애플리케이션이 제공하는 포괄적인 서비스들을 표현

    • 큰 덩어리 비지니스 기능을 관련된 비지니스 객체 모델에서 분리
    • 명사-동사 분리(예. 계좌(도메인) 메소드 분리 -> 은행서비스(비지니스 로직-계좌를 개설하다)
    • 서비스를 열어준다는 것은 클래스의 메소드를 사용할 수 있게 권한을 부여한다는 의미가 될 수 있음
  • 퍼시스턴스 계층 - 객체에 저장된 데이터(저장소, 객체 가져오기)

    • 데이터 저장 방식은 다양(관계형 데이터베이스 스스템, 쉼표로 분리된 텍스트, XML 등)
    • 추상화 필요 - 세부사항(데이터가 어떻게 저장/전송) 숨김
    • 내부 계층

      • 추상 계층 : 퍼스스턴스 계층에 일관성 있고 의미 있는 인터페이스 제공

        • 클래스와 메소드의 집합
        • 세부 구현 사항은 감싸서 꾸며줌
        • 적절히 추상 계층 구현을 도와주는 패턴 존재 : 예) 데이터 접근 객체(DAO;Data Access Object)
      • 퍼시스턴스 프레임워크 : 드라이버(or 인터페이스)와 소통하는 책임

        • 데이터 저장/가져옴/수정/검색/관리 메소드들 제공
        • 기반 저장소 클래스에 종속적
        • 표준API - 반복적이고 부차적인 코드가 필요

          • JDBC(자바 애플리케이션 -데이터베이스에 접근~표준 프레임워크)
          • ADO.NET(.NET 애플리케이션을 위한 표준 데이터베이스 퍼시스턴스 프레임워크)
      • 드라이버 / 인터페이스

        • 기반 저장소는 종류 다양(구현, 규모, 행동 상이) -> 소프트웨어 드라이버 사용
        • 드라이버와 통신하여 차이점들을 최소화 간소화하는 역할

 

데이터베이스

  • 관계형 데이터베이스의 사용 이유? - 무결성, 성능, 보안

    • 무결성 - 데이터의 일관성, 신뢰, 값의 정확성 보장

      • VARCHAR(25) NOT NULL
      • 데이터 타입 엄격히 준수 - 예) 값이 문자열 데이터, 길이가 25이하
      • 제약조건 엄수 - 예) UNIQUE
      • 트랜잭션 사용 - 연관(관련)된 데이터들의 일관성 있는 수정 방식(여러 사용자)
    • 성능 - 설계, 소프트웨어 튜닝, 하드웨어

      • 설계: 최고 중요!!!
      • 튜닝 고려사항: 캐시, 파일 관리자, 인덱스 알고리즘, 운영체제 등
      • 하드웨어 고려사항: 고속 디스크 어레이, 고속I/O 컨트롤러, 고속 하드웨어 캐시, 네트워크 인터페이스
    • 보안 - 기밀 데이터 유지
  • 데이터베이스 형태(4가지)

    • 애플리케이션 데이터베이스 - 작고 단순한 형태, 외부 영향 적음

      • 해당 프로젝트의 일보로 애플리케이션과 나란히 설계/구현
      • 예) 웹 애프리케이션 -> 데이터베이스(MySQL,PostgreSQL) -> 리포팅 툴(크리스탈 리포트)
    • 기업용 데이터베이스 - 큰 규모, 외부의 영향 큼

      • 통합 데이터베이스 - 트랜잭션처리 데이터베이스 - 리포팅 데이터베이스
    • 독점적 데이터베이스 - 직접 제작 vs 구입(패키지 소프트웨어)
    • 레거시 데이터베이스 - 오래된 데이터베이스(보잡성, 뒤죽박죽 설계, 의존성. age)

      • 수년간에 걸친 수정, 긴급한 수리 작업, 오류 은폐작업, 오류 피해가기, 땜질식 문제 해결, 기술적 제약 극복 패치..

 

iBATIS

  • iBATIS - 데이터 매퍼

    • 매퍼계층: 객체와 데이터베이스 그리고 매퍼 자체를 독립적으로 유지 + 객체와 데이터베이스 간에 데이터를 이동

      • SQL 구문의 파라미터와 결과(입력/출력)를 클래스에 매핑
    • 매핑방법

      • SQL 구문 - 입력과 출력으로 구분

        • 예) 입력 first_name, last_name / 출력 1234

          1. select first_namelast_name
            from employee
            where employee_number=1234;
        • XML 서술 파일 : SQL 구문의 입력과 출력을 매핑

          1. <select id="getAddress" parameterClass="int" resultClass="Address">
          2. select
          3. ADR_ID   as id,
          4. ADR_DESCRIPTION as description,
          5. ADR_STREET as street,
          6. ADR_CITY as city
          7. from address
          8. where ADR_ID = #id#
          9. </select>
          • 별칭 idsms id라고 불리는 Address 클래스의 프로퍼티에 매핑
          • #id# - 파라미터(Integer 형)
          • 위 코드를 수행하는 자바 코드

            1. Address addr = (Address) sqlMap.queryForObject("getAddress", new Integer(5));
          • 위 코드를 수행하는 C# 코드

            1. Address addr = (Address) sqlMap.queryForObject("getAddress", 5);
      • JDBC, ADO.NET 코드 작성 대신

        • 예) JDBC vs iBATIS

          • JDBC

            1. public Employee getEmployee (int id) throws SQLException {
                  Employee employee = null;
                  String sql = "SELECT * from employee " +
                          "where employee_number = ?";
                  Connection conn = null;
                  PreparedStatemnent ps = null;
                  ResultSet rs = null;
                  try {
                      conn = datasource.getConnection();
                      ps = conn.prepareStatement(sql);
                      ps.setInt(1, id);
                      rs = ps.executeQuery();
                      while (rs.next()) {
                          employee = new Employee();
                          employee.setId(rs.getInt("ID"));
                          employee.setEmployeeNumber(rs.getInt("EMPLOYEE_NUMBER"));
                          employee.setFirstName(rs.getString("FIRST_NAME"));
                          employee.setLastName(rs.getString("LAST_NAME"));
                          employee.setTitle(rs.getString("TITLE"));
                      }
                  } finally {
                      try {
                          if(rs != null) rs.close();
                      } filnally {
                          try {
                              if (ps != null) ps.close();
                          } filnally {
                              if (conn != null) conn.close();
                          }
                      }
                  }
                  return employee;
              }
          • iBATIS

            1. <select id="getEmployee" parameterClass="java.lang.Integer" resultClass="Employee">
            2. select
            3. ID               as id,
            4. EMPLOYEE_NUMBER   as description,
            5. FIRST_NAME   as street,
            6. LAST_NAME    as city
            7. TITLE         as title
            8. from employee
            9. where EMPLOYEE_NUMBER = #empNum#
            10. </select>
            • 실행 코드

              1. Employee emp = (Employee) sqlMap.queryForObject("getEmployee", new Integer(5));
  • (추가내용)

SQLMap.png

자바빈즈를 PreparedStatement 파라미터와 ResultSet으로 맵핑시켜주는 기능을 담당

 

  • 디미터 법칙(Law of Demeter) "각 계층은 다른 계층에 대해 오직 제한된 정보만을 가질 수 있다: 오직 현재 계층에 인접한 계층에 대해서만."

    • 각 계층이 오직 자기 바로 아래 계층과만 소통 가능
    • 의존성이 한 방향으로만 흐르는 것을 조장(스파게티 코드 피하기)
    • iBATIS는 퍼시스턴스 계층 프레임워크(위: 비지니스 로직 / 아래: 데이터베이스)

Spring과 iBATIS

  • 왜 iBATIS대신에 Spring을 사용할까?

    • iBATIS DAO 계층

      • 장점: 빠르고 쉬운 솔루션
      • BATIS SQL Maps / iBATIS DAO 계층 분리(2.3~)
      • 요구사항: 트랜잭션/커넥션 관리 -> Spring보다 훨씬 간단하게 사용가능한 프레임워크
      • 단점: 간결함
      • DAO 패턴을 사용: 결함도가 낮아짐(decoupling) -> 테스트하기 쉽다

        • Action에서 필요한 코드의 구현을 알 필요 없이 오직 필요한 인터페이스만 알면 됨.
        • 구현체는 설정을 통해 기워 넣게 됨
    • Spring : 커넥션과 트랜잭션 관리, 애플리케이션의 모든 부분에 적용(iBATIS DAO는DAO계층에만 적용)
  • 효율적인 DAO 계층

    • 구현체에서 인터페이스 분리

      • 이유

        1. 구현체 바꿔 치기가 가능(다른 형태의 데이터 접근 지원 가능)
        2. 테스트가 쉽고 빨리짐(실제 DB에 접근하는 객체 대신 가상의 DAO 객체를 끼워 넣을 수 있으므로)
      • IDE : 분리 과정 쉽게 처리 가능

        • 리팩토링 툴(클래스에서 인터페이스를 분리 가능)
        • 인터페이스를 만들 때 구현 클래스를 어떤 다른 데잍터베이스를 다루는 툴에 종속적인 부분에 노출 가능성 높음

          • 노출: DAO가 아닌 데이터 접근 구현체에 애플리케이션을 묶어버림

            • 예) 'Fast Lane Reader'패턴을 사용하는 웹 애플리케이션 - JDBC 코드가 뷰 계층과 직접 소통 (테스트 어려워짐)

              • -> 콜백을 사용해서 코드를 작성(뷰가 요청한 데이터를 처리하는 RowHanlder 같은 것)
          • SQL Maps API를 직접 사용하는 애플리케이션 -> 캡슐화된 API

            • 예) sqlMapClient 객체의 queryForList() 메소드를 호출하는 클래스 - > 작성한 DAO 클래스를 호출하게 리팩토링, 클래스의 메소드에서는 List 객체를 반환

              • 데이터 사용자 - 작성한 DAO하고만 소통 가능
    • 외부에서 설정된 팩토리(factory)를 사용하여 구현체의 결합도 낮추기

      • 인터페이스와 구현체 둘 다 DAO를 사용하는 클래스에 노출(인터페이스에 대한 의존성을 DAO를 사용하는 클래스에 추가한 셈)시키면 안됨

        • [구현체]-[DAO]-[interface]-> 구현체를 어떻게 사용할 수 있을 것인가?

          1. AccountDao accountDao = new AccountDaoImpl();   // DAO를 구현에서 분리, 구현체를 직접 참조하고 있음
          2. AccountDao accountDao = (AccountDao)DaoFactory.get(AccoutDao.class);   // 초점: DaoFacotry가 AccountDao 인테페이스를 구현한 객체를 반환
          • DAO factory

            • public인테피이스는 getInstance()와 getDao() 두개의 메소드로 이루어져 있음

              1. public class DaoFactory {
              2. private static DaoFatory instance = new DaoFactory();
              3. private final String defaultConfigLocation = "DaoFactory.properties";   // 프로퍼티 화일(인터페이스, 구현체 이름)
              4. private Properties daoMap;
              5. private Properties instanceMap;
              6. private String configLocation = System.getProperty(
              7. "dao.factory.config",

                defaultConfigLocation

                );

              8. private DaoFactory() {   // 1. private 생성자 선언(single tone; 오직 단 한 개의객체만 생성할 수 있는 클래스)
              9. daoMap = new Properties();
              10. instanceMap = new Properties();
              11. try {
              12. daoMap.load(getInputStream(configLocation));
              13. } catch (IOException e) {
              14. throw new RuntimeException(e);
              15. }
              16. private InputStream getInputStrream(String configLocation)
              17. {
              18. return Thread
              19. .currentThread()
              20. .getContextClassLoader()
              21. .getResourceAsStream(configLocation);
              22. }
              23. public static DaoFactory getInstance() {   // 2. 간단한 팩토리 메소드를 선언 (이 클래스의 유일한 인스턴스 반환)
              24. return instance;
              25. }
              26. public Object getDao(Class daoInterface) {   // 3. DAO를 가져온다 (인터페이스의 구현체를 반환)
              27. if (instanceMap.containsKey(daoInterface)) {
              28. return instanceMap.get(daoInterface);
              29. }
              30. return createDao(daoInterface);
              31. }
              32. private synchoronized Object createDao (Class daoInterface) {   // 4. 타입 별로 단 하나의 DAO만 생성함을 보장
              33. Class implementationClass;
              34. try {
              35. implementationClass = Class.forName((String)daoMap.get(daoInterface));
              36. Object implementation = implementationClass.newInstance();
              37. instanceMap.put(implementationClass, implementation);
              38. } catch (Exception e) {
              39. throw new RuntimeException(e);
              40. }
              41. return instanceMap.get(daoInterface);         // DAO에 대한 실제 요청이 발생할 때에 생성
              42. }
              43. }

               

               
          •  
    • 트랜잭션과 커넥션 관리기능 제공(chap. 7)
  • 스프링: 데이터 매퍼의 두 가지 버전(1.3, 2.0)을 지원

    • 버전 1.3 : SqlMapXxx (SqlMapTemplate 클래스 사용)
    • 버전 2.0 : SqlMapClientXxx (SqlMapClientTemplate 클래스 사용: 내부적으로 iBATIS의 SqlMapClient 사용)

      • SqlMapClient를 스프링 빈으로 설정 : SqlMapClientFactoryBean 클래스 이용

        1. <bean id="sqlMapClinet" class="org.springframework.orm.ibatis.SqlMapClinetFactoryBean"

          • p:dataSource-fef="dataSource"
          • p:configLocation="WEB-INF/sqlMap/sqlMapConfig.xml">
        2. </bean>
      • sqlMapConfig.xml

        1. <?xml version="1.0" encoding="UTF-8" ?>
        2. <!DOCTYPE sqlMapConfig PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"
        3. "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">
        4. <sqlMapConifg>
        5. <sqlMap resource="GuestBook.xml" />
        6. </sqlMapConifg>
      • GuestBook.xml

        1. <?xml version="1.0" encoding="UTF-8" ?>
        2. <!DOCTYPE sqlMap
        3. PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
        4. "http://ibatis.apache.org/dtd/sql-map-2.dtd">
        5. <sqlMap namespace="Guestbook">
        6. <typeAlias alias="Message" type="kame.spring.questbook.service.Message" />

          <parameterMap id="messageParamMap" class="Message">

        7. <parameter property="guestName" />
        8. </parameterMap>
        9. <resultMap id="messageResultMap" class="Message">
        10. <result property="id" column="GUESTBOOK_MESSAGE_ID" />
        11. <result property="guestName" column="GUEST_NAME" />
        12. <result property="content" column="CONTENT" />
        13. </reslutMap>
        14. ..
        15. <select id="selectList" resultMap="messageReusltMap" resultClass="Message" parameterCalss="map">
        16. select * from GUESTBOOK_MESSAGE order by GUESTBOOK_MESSAGE_ID desc limit #startRow#, #fetchSize#
        17. </select>
        18. </sqlMap>
      • limit 는 mySql에 있다.

 

바깥고리

자바 프레임워크 활용 전략


JDeveloper에서 iBATIS 실행하기

자동으로 클래스패스를 잡아주니 라이브러리에 추가만 해주면 된다.

1. Library Name에 알기 쉬운 이름을 붙여준다(iBATIS2.3.0.677)

include_lib2.png

 

include_lib.png

 


iBATIS를 통해 더 즐겁게 개발하고, 또 개발의 재미도 느끼고 야근도 덜 할 수 있기를 기원한다. - xx

불가지론자(경험해보지 않은 것은 믿을 수 없다) - xxi

"망치를 가진 사람은 모든 것을 못으로 본다" , 환경이 다양하면 다양한 도구가 필요한 법 - xxii

책을 쓰는 것은 (소프트웨어를 작성)하는 것보다 더 어렵다. - xxiv

돈을 위해 낮에는 일을 하고 명성과 영광을 얻기 위해 밤에는 오픈소스 소프트웨어(또는 책)를 작성하기 위해 시간을 보낸다.(클린턴 비긴) - xxiv

긱(geek: 학업이나 일, 컴퓨터 등에 몰두하다 보니 세상물정과는 거리가 멀어진 사람 / 특정 분야에 대해 광적인 사람), 우리는 첫 번째 컴퓨터를 가졌을때의 좋은 기억이 있고 그 컴퓨터를 사주는 투자가 나중에 좋은 결과를 낳게 된다는 것을 아는 부모님을 신뢰한다. - xxv

은 무언가를 배우는 최고의 방법, 종이책이 전자책으로 대체되거나 뒤통수에 잭을 꼽아서 몇 초안에 정보를 업로드하는 방식으로 바뀔 거라는 등 많은 억측, 나는 책을 좋아한다. 책은 편리하게 갖고 다닐 수 있고, 다루기도 쉽기 때문이다. 책에 메모를 남기고, 종이를 접고, 반으로 쪼개서 갖고 다닐 수도 있다.(클린턴 비긴) - xxvii

 사람들은 스스로 동기를 부여받아 탐구하는 동안 배운 것들을 기억(인지 과학), 인류는 행동하며(in action) 배운다. - xxxii

 

노하우

db.properties 위치

 

 

'스프링3.0' 카테고리의 다른 글

contextConfigLocation  (0) 2012.07.04
스프링 3.0 + ibatise  (0) 2012.07.03
Srping 3.0 sqlSession+DataSource 구현 하기. (Spring+mybatise0  (0) 2012.05.19
web.xml 구현부 encoder  (0) 2012.05.19
Spring 개발 환경 .  (0) 2012.05.19
Posted by 사라링

스프링 3.0 + ibatise

2012. 7. 3. 13:35

 

FOCUS : 
Eclipse + Maven + Spring Framework  개발환경 설정.

Reference :
1. http://www.oracle.com/technetwork/java/javase/downloads/index.html
2. http://www.eclipse.org/downloads
3. http://openness.tistory.com/107
4. http://tomcat.apache.org/download-70.cgi
5. http://blog.daum.net/istae0430/279
6. http://archive.apache.org/dist/tomcat/tomcat-connectors/native/
7. http://blog.doortts.com/59 
8. http://alexk.springnote.com/pages/3501753#toc_2
9. http://maven.apache.org/download.html
10. http://eclipse.org/m2e/
11. http://eclipse.org/m2e/download
12. http://stackoverflow.com/questions/2921473/m2eclipse-eclipse-is-running-in-a-jre-but-a-jdk-is-required
13. pom reference ( http://maven.apache.org/pom.html)
14. http://kongkk.springnote.com/pages/8115902
15. http://sepiroth11.tistory.com/entry/SetPropertiesRuleServerServiceEngineHostContext-Setting-property-source-to-orgeclipsejstjeeserver%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EB%AA%85-did-not-find-a-matching-property
16. http://entireboy.egloos.com/4534698

Need to known :
The APR based Apache Tomcat Native library 

Maven http://maven.apache.org/  
    1) How do i build my project http://www.avajava.com/tutorials/lessons/how-do-i-build-my-project.html

    2) build lifecycle phase :http://cvs.peopleware.be/training/maven/maven2/buildLifecyclePhases.html#site

Spring Framework http://www.springsource.org/  , 
    1)  Spring Framework module 설명  : http://blog.naver.com/gigar/60121489281 





spring Framework 개발환경 설정에 대해 정리해 본다.
개발 환경 설정 하는데, 왜 이리 걸리는게 많은지, 환경 설정 하다가 포기하겠당 ㅋㅋ
그래서 다시 한번 정리!!



- 개발환경은 아래와 같은 순서로 설정  (for windows 7)
1. java 설치
2. eclipse 설치.
3. tomcat 설치 + eclipse wts 설정
4. maven 설치 + eclipse m2eclipse 설치
5. spring Framework 설정



1. java 설치 
아래의 URL 에서 JDK 7  download
http://www.oracle.com/technetwork/java/javase/downloads/index.html

JDK7 설치 후, 윈도우 환경변수에 JAVA_HOME 설정
JAVA_HOME --> C:\Dev\Java\jdk1.7.0


2. Eclipse(Indigo SR1) 설치 
아래의 URL 에서 Eclipse IDE for Java EE Developers download 
http://www.eclipse.org/downloads/

받은파일 (eclipse-jee-indigo-SR1-win32.zip)의 압축해제로 eclipse 설치 


3. tomcat 설치 + eclipse wts 설정 ( 참고 : http://openness.tistory.com/107)
아래의 URL에서 tomcat 7.0 download
http://tomcat.apache.org/download-70.cgi

받은파일 압축해제로 tomcat 설치 
tomcat 설치 후, 윈도우 환경변수에 CATALINA_HOME 설정
CATALINA_HOME -->D:\tomcat

Eclipse 에서 New > Other > Server > Apache Tomcat v7.0 Server 선택 
 tomcat installation directory -> d:\tomcat 설정
 jre -> jre7 (C:\Dev\Java\jdk1.7.0) 설정

위와 같이 설정하면 
하단의 Servers tab 에 Tomcat v7.0 Server at localhost [Stopped, Republish] 라고 나온다.

Tomcat v7.0 Server at localhost Start 후, 웹브라우저에 http://localhost:8080 로 실행 했을때 아래와 같이 나오면 정상



tomcat 설치중 문제발생 : (참고 : http://blog.daum.net/istae0430/279)
위와 같이 tomcat 실행이 되는 건 확인 했는데 eclipse console log를 보니 아래와 같은 log가 있다. ㅜㅜ

[log]
정보: The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: C:\Dev\Java\jdk1.7.0\bin;C:\Windows\Sun\Java\bin;C:\Windows\system32;...
2월 10, 2012 3:44:47 오후 org.apache.coyote.AbstractProtocolHandler init


근데 ARP 라는 넘이 머 하는 넘인지는 모르겠는데 검색 해 보니 
http://archive.apache.org/dist/tomcat/tomcat-connectors/native/
가서  tcnative-1.dll(windows 의 경우) 을 받아 java.library.path 넣으란다. 

그래서 v 1.1.17 을 받아 C:\Dev\Java\jdk1.7.0\bin 에 넣었더니 아래의 붉은색과 같이 log가 뜬다. 닝길 ..

[log]
2월 10, 2012 3:46:36 오후 org.apache.catalina.core.AprLifecycleListener init
정보: An older version 1.1.17 of the APR based Apache Tomcat Native library is installed, while Tomcat recommends a minimum version of 1.1.20
2월 10, 2012 3:46:36 오후 org.apache.catalina.core.AprLifecycleListener init
정보: Loaded APR based Apache Tomcat Native library 1.1.17.
2월 10, 2012 3:46:36 오후 org.apache.catalina.core.AprLifecycleListener init
정보: APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true].


 다시 v1.1.20 을 받아  C:\Dev\Java\jdk1.7.0\bin 에 넣고 Server를 실행 시켜보니 아래와 같이 버전 맞지 않는 문제가 해결 되었다.   아직 ARP 가 머 하는데 쓰는 넘인지 잘 모르겠는데, 이넘이 없어도 문제없이 실행되는 거 같다. 
이 ARP라는 넘이 먼지 나중에 찾아봐야지.

[log]
2월 10, 2012 3:50:34 오후 org.apache.catalina.core.AprLifecycleListener init
정보: Loaded APR based Apache Tomcat Native library 1.1.20.
2월 10, 2012 3:50:34 오후 org.apache.catalina.core.AprLifecycleListener init
정보: APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true].



4. maven 설치 + eclipse m2eclipse 설치
 ( 참고 : http://blog.doortts.com/59 , http://alexk.springnote.com/pages/3501753#toc_2)

4.1 Maven 설치 : 아래의 URL에서 Maven download
http://maven.apache.org/download.html

받은파일 압축해제로 maven 설치 
maven 설치 후, 윈도우 환경변수에 M2_HOME 설정
M2_HOME -->C:\Dev\apache-maven-3.0.4

cmd 창에서 mvn -version 을 타이핑 해보면 아래와 같이 결과가 나온다. 

 




4.2 m2eclipse 설치  ( 참고 : http://eclipse.org/m2e/http://eclipse.org/m2e/download/)
eclipse > help > install new software 에 http://download.eclipse.org/technology/m2e/releases 
를 입력하면 m2e plugin을 다운 받을 수 있다. 

다운로드가 완료되면 아래와 같은 윈도우가 뜬다. 


Restart Now 실행 

eclipse > window > preferences  > Maven > Installations에 보면 Embedded 되어 있는 Maven 버전이 3.0.2로 
apache 에서 다운로드 받은 버전보다 더 낮아 add 해 주었다. 



m2eclipse 문제 발생시 참고 
(http://stackoverflow.com/questions/2921473/m2eclipse-eclipse-is-running-in-a-jre-but-a-jdk-is-required)

maven build 실행시 compile 문제 발생하면 참고 
http://maven.40175.n5.nabble.com/Unable-to-locate-the-Javac-Compiler-Problem-td133804.html

5. spring Framework 설정
Maven을 깔았으니 eclipse maven project로 spring Framework을 설정 해 보려한다.

5.1 project 생성
 1)eclipse > new > project > maven > maven project 선택 
 2) create a simple project (skip archetype seletion) check 
Next
 1) Group Id -> com.test2
 2) artifact id -> springTest2
 3) Packaging -> war 
Finish 

아래와 같은 모양으로 project 생성 




pom reference ( http://maven.apache.org/pom.html)
spring framework 사용을 위해 첨부 파일과  같이 pom.xml을 만든다.
pom.xml 중 spring 과 ibatis 이외의 부분은 없어도 될거 같다.

삽질 원인
 - Oracle JDBC Driver는 라이센스 문제로 인해서 Maven Central 저장소에서 로컬 저장소로 jar 파일을 정상적으로 다운로드 받지 못한다!!! (오라클이 갑자기 싫어질라고 한다.)

해결방법
 
- 방법1 : pom.xml 파일에 http://mesir.googlecode.com/svn/trunk/mavenrepo 메이븐 저장소를 추가해서 사용하는 방법
<dependencies>
        <dependency>
       <groupId>com.oracle</groupId>
     <artifactId>ojdbc14</artifactId>
     <version>10.2.0.4.0</version>
        </dependency>
<dependencies> 

 <repositories>
<repository>
<id>mesir-repo</id>
<url>http://mesir.googlecode.com/svn/trunk/mavenrepo</url>
</repository>
</repositories> 
*** 주의 사항 :  mesir-repo  저장소를 추가하지 않고 ojdbc 의존성만 추가한 후 빌드를 수행하게 되면... 로절 저장소가 더럽혀 지는 경우가 발생하는 것 같다.(아님말구!) 그런 경우 로컬 저장소에서 해당 내용을 삭제한 후 다시 시도를 해야 한다.

- 방법2 : 
직접 ojdbc?.jar 파일을 다운로드 받아서 mvn 명령어로 로컬 저장소에 추가하는 방법
  1. 
 ojdbc14.jar 파일을 다운로드 받은 후 mvn 명령을 이용하여 로컬 저장소에 ojdbc14.jar 를 추가한다. 
mvn install:install-file -Dfile=ojdbc14.jar -DgroupId=com.oracle -DartifactId=ojdbc14 -Dversion=10.0 -Dpackaging=jar -DgeneratePom=true  

  2. pom.xml 파일에 의존성 추가
<dependencies>
        <dependency>
       <groupId>com.oracle</groupId>
     <artifactId>ojdbc14</artifactId>
     <version>10.0</version>
        </dependency>
<dependencies> 
 

Oracle JDBC Driver 덕분에 maven에 대해서 좀더 알게 된것 같다. 하지만 너무 많은 시간을 삽질하는데 시간을 허비해버렸다.
Maven을  사용하면 기존의 개발환경 보다는 편리한 점이 있지만... 아직 이클립스의 maven 플러그인이 완별하지 않은 것 같고 또 maven 자체도 좀더 스마트해질 필요가 있을 것 같다. JDK 에도 node.js의 NPM과 같은 툴이 포함되었으면 하는 바램이다.











pom.xml 을 첨부된 pom.xml 과 같이 설정 후, 아래와 같은 오류가 발생했다.


 Project configuration is not up-to-date with pom.xml. Run project configuration update 라는 메세지가 있어   Project > properties > Maven > Update Project Configuration... 실행 
--> 오류 가 제거 되었다. 

그리고 아래 그림과 같이 Maven Dependencies 에 library가 추가 되었다..
예전엔 jar를 하나씩 다 복사해서 넣고 썼었는데 , library 관리가 참 편리해 졌다. ㅋㅋ



2) maven project를 tomcat 에 add
으미 생성한 Maven 프로젝트를 tomcat 에 add 하려고 Servers > add and remove 메뉴를 선택하면 add 할 resource가 없단다.. 그럼 내가 만들어 놓은 maven project는 tomcat에 add 할수 없다? 
그래서 한참을 헤멨다..그런데 ㅋㅋ ( 참고 : http://kongkk.springnote.com/pages/8115902
참고에 보면 project Facets를 찾아서 Dynamic Web Module 를 선택하면 된다다. 

Project > properties > Project Facets > Convert to faceted form > Dynamic Web Module (check)
그리고 바로 아래에 i Further configuration available.. 에서 src/main/webapp 로 Web contents 경로를 지정했다.
그러면 아래 그림과 같이 src/main/webapp/WEB-INF가 생성되고, tomcat에 publish 가능한 project가 된다.


tomcat에 project를 추가하고 tomcat을 실행시켜보니 
에고고 산넘어 산이구나 아래의 문제가 발생한다. 이건 또 머꼬?

경고: [SetPropertiesRule]{Server/Service/Engine/Host/Context} Setting property 'source' to 'org.eclipse.jst.jee.server:springTest2' did not find a matching property.
그래서 또 검색을 해 보니..다들 격고 있구나 ㅋㅋ 
(참고 : http://sepiroth11.tistory.com/entry/SetPropertiesRuleServerServiceEngineHostContext-Setting-property-source-to-orgeclipsejstjeeserver%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EB%AA%85-did-not-find-a-matching-property)

Servers tab > Tomcat v7.0 더블클릭 > Overview 하단에 Server options 에서 
Publish module contexts to separate XML files 에 check 하란다. 

그리고 다시 tomcat 실행하니, 아래와 같은 경고가 또 떴다.  
경고: [SetContextPropertiesRule]{Context} Setting property 'source' to 'org.eclipse.jst.jee.server:springTest2' did not find a matching property.

검색중 어딘가에서 살짝 본 기억이 난다. 
springTest2 바로 위의 Servers에서 server.xml 을 열어보면 하단에 
<Context docBase="springTest2" path="/springTest2" reloadable="true" source="org.eclipse.jst.jee.server:springTest2"/>
부분이 있는데 source="org.eclipse.jst.jee.server:springTest2" 형식을 tomcat이 지원하지 않아서 그런다고 한다.
더 진행해 보고, spring Framework이 동작하지 않으면 다시 이유를 찾아봐야겠다. 


3) web.xml , dispatcher-servlet.xml , controller , jsp 


 web.xml , dispatcher-servlet.xml , controller, jsp 모두 만들고 tomcat을 실행하니 또 아래와 같이 오류 발생

심각: Exception starting filter encodingFilter
java.lang.ClassNotFoundException: org.springframework.web.filter.CharacterEncodingFilter
 at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1676)
 at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1521)
 at org.apache.catalina.core.DefaultInstanceManager.loadClass(DefaultInstanceManager.java:415)
 at org.apache.catalina.core.DefaultInstanceManager.loadClassMaybePrivileged(DefaultInstanceManager.java:397)
 at org.apache.catalina.core.DefaultInstanceManager.newInstance(DefaultInstanceManager.java:118)
 at org.apache.catalina.core.ApplicationFilterConfig.getFilter(ApplicationFilterConfig.java:252)
 at org.apache.catalina.core.ApplicationFilterConfig.setFilterDef(ApplicationFilterConfig.java:372)
 at org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:98)
 at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:4562)
 at org.apache.catalina.core.StandardContext$2.call(StandardContext.java:5240)
 at org.apache.catalina.core.StandardContext$2.call(StandardContext.java:5235)
 at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
 at java.util.concurrent.FutureTask.run(FutureTask.java:166)
 at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
 at java.lang.Thread.run(Thread.java:722)

검색해 보니 결국은 spring Framework library가 WEB-INF/lib에 없어서 발생한 문제다.
(참고 : http://entireboy.egloos.com/4534698)
eclipse 설정을 통해 해결 가능한데 다음과 같이 하면 된다.

Project > properties > Deployment Assembly > add button > java Build Path Entries  선택 그리고 Next
Maven dependencies 선택 하면 아래 그림과 같이 설정된다.
Maven Dependencis -> WEB-INF/lib가 새로 생성 된것 




설정을 마치고 tomcat을 다시 실행 시켰더니 아래와 같이 log msg가 뜨지만 "INFO" Level 이라 그냥 지나갔다.

정보: validateJarFile(D:\Dev\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\springTest2\WEB-INF\lib\geronimo-servlet_2.5_spec-1.2.jar) - jar not loaded. See Servlet Spec 2.3, section 9.7.2. Offending class: javax/servlet/Servlet.class


브라우저 실행후 http://localhost:8080/springTest2/test1.do  실행 시켰더니 원하는 페이지가 떴다.
휴우~
중간 중간의 고비를 잘 넘기고 spring framework으로 만들어진 간단한 페이지가 떴다.



아직 잘못 설정되어 있는 부분이 있을 수 있지만 , spring Framework을 하나씩 더 알아가면서 바꾸면 될것 같다.
간단하게 Hello 하나 찍는 건데 꽤 긴 시간을 들였다. 에공~~
늙어도 개발을 취미삼아 조금씩 할 수 있었으면 좋겠는데 , 어째 개발 환경 설정이 점점더 복잡해 지고 있는 것 같다.

개발환경도 단순화 시킬수 없을까? 잡스흉아처럼...ㅋㅋ







spring Framework 개발환경 설정(1) 에서는 eclips Maven project 로 spring Framework 설정방법을 살펴봤다.
이번에는 이미 설정되어 있는 spring Framework에   iBatis 설정을 추가한다. 

FOCUS
spring Framework 에 iBatis 설정 하고 테스트 페이지 만들기

Reference
1. jsp taglib 사용 위해 maven 에 설정 해야 할 dependency?

   <dependency> 
    <groupId>javax.servlet</groupId> 
      <artifactId>jstl</artifactId> 
      <version>1.2</version>
 </dependency>
 
 <dependency>
   <groupId>taglibs</groupId>
   <artifactId>standard</artifactId>
   <version>1.1.2</version> 
    </dependency>

2. iBatis 설정하여 개발할때 편하게 개발 할 수 있는 순서
  1)Table  스키마 확인
  2) iBatis resultMap 작성
  3) DB Query 문 작성
  4) DAO 작성
  5) JSP 작성
  6) Service & Controller 작성
  7) 필요하면 환경설정파일 변경.


Need to know
iBatis 사용법.




iBatis 연동을 위해 아래의 작업을 진행한다.
1. pom.xml에 iBatis dependency 추가.
2. /WEB-INF/web.xml 수정.
3. /WEB-INF/spring/spring-config.xml 생성 .
4. /WEB-INF/sql-map-config.xml 생성 
5. Test.xml(sqlmap 파일) 생성.
6. dao 파일 생성
7. domain 생성
8. Controller 수정
9. JSP 수정


1. pom.xml 에 iBatis dependency 추가.
   ( spring Framework 개발환경 설정(1) 에 첨부된 파일 이미 추가되어 있슴)
<dependencies>
...
 <!--  DB- jdbc driver 시작  -->
    <dependency>    
       <groupId>mysql</groupId>
       <artifactId>mysql-connector-java</artifactId>
       <version>5.1.18</version>
    </dependency>
    <!--  DB - jdbc driver끝  -->
    
    <dependency>
   <groupId>commons-dbcp</groupId>
   <artifactId>commons-dbcp</artifactId>
   <version>1.4</version>
 </dependency>

 <dependency>
   <groupId>org.apache.ibatis</groupId>
   <artifactId>ibatis-sqlmap</artifactId>
   <version>2.3.4.726</version>
 </dependency>
...
</dependencies>



2. WEB-INF/web.xml 수정
아래의 내용을 web.xml 에 추가. 

 <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring/*-config.xml</param-value>
 </context-param>

 <listener>
  <display-name>SpringContextLoader</display-name>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener>


3. /WEB-INF/spring/spring-config.xml 생성 
web.xml 에 선언 후, 
/WEB-INF/spring 디렉토리에 *-config.xml 로 명명되는 파일은 spring configuration 용으로 사용.

아래는 spring-config.xml (jdbc , ibatis, dao 설정)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
      http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsd
         http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.0.xsd
         http://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
 
    
 <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://domain or ip/dbname"/>
        <property name="username" value="id"/>
        <property name="password" value="password"/>
        <property name="maxActive" value="30"/>
        <property name="maxIdle" value="10"/>
        <property name="maxWait" value="1000"/>
        <property name="defaultAutoCommit" value="true"/>
    </bean>

 
 <!-- SqlMap setup for iBATIS Database Layer -->
 <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
  <property name="configLocation" value="WEB-INF/sql-map-config.xml"/>
  <property name="dataSource" ref="dataSource"/>
 </bean>
 
 
 <!--  DAO -->  
 <bean id="testDao" class="com.springTest2.dao.TestDao">
  <property name="sqlMapClient" ref="sqlMapClient"/>
 </bean>

</beans>


4. /WEB-INF/sql-map-config.xml 생성 

아래의 내용은 query 문이 기록된 xml resource 설정

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMapConfig PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN"
    "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">

<sqlMapConfig>
 <sqlMap resource="com/springTest2/dao/map/Test.xml" />
</sqlMapConfig>

5. Test.xml(sqlmap 파일) 생성.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd">

<sqlMap namespace="Test">

 <typeAlias alias="TestTableInfo" type="com.springTest2.domain.TestTableInfo" />
 
 <resultMap id="testTableInfoResult" class="TestTableInfo">
  <result property="name" column="NAME" />
  <result property="age" column="AGE" />
  <result property="sex" column="SEX" />
 </resultMap>


 <!--  testTable 모든 데이터 조회  -->
 <select id="getTestTableList" parameterClass="map" resultMap="testTableInfoResult">
  SELECT name, age, sex 
  FROM testTable 
 </select> 

</sqlMap>


6. dao 파일 생성
package com.springTest2.dao;

import java.util.List;
import java.util.Map;

import org.springframework.dao.DataAccessException;
import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;


public class TestDao extends SqlMapClientDaoSupport{

 //testTable list를 조회한다.
 public List getTestTableData(Map map ) throws DataAccessException {
  return  getSqlMapClientTemplate().queryForList("getTestTableList", map);
 }
 
 
}


7. domain 생성 

package com.springTest2.domain;

public class TestTableInfo {
 
 private String name;
 
 private int  age;
 
 private String sex;

 
 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public int getAge() {
  return age;
 }

 public void setAge(int age) {
  this.age = age;
 }

 public String getSex() {
  return sex;
 }

 public void setSex(String sex) {
  this.sex = sex;
 }
 

}


8. Controller 수정

보통 Controller 에서는 Service Object만 사용하나  지금 테스트 하는 예제는 단순하기때문에 Service단을 생략하고 
Controller에서 Dao를 설정하여 사용하였다.


package com.springTest2.controller;

import java.util.HashMap;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import com.springTest2.dao.TestDao;

  
  
 @Controller
 public class TestController {
 
  @Autowired
  private TestDao testDao;
  
 
  @RequestMapping("/test1.do")
  public ModelAndView helloworld(){
  
   String message = "Hello Spring Framework";
   
   ModelAndView mnv = new ModelAndView();
  
   mnv.setViewName("resultPage");
   mnv.addObject("message", message);
  
   //query 문에 넘길 param 없으므로 아무값도 설정하지 않는다.
   HashMap map = new HashMap();
   
   //testTable data를 조회한다.
   List list = testDao.getTestTableData(map);
   mnv.addObject("TestTalbeDataList", list);
   
   return mnv; 
  
  }

  
 }

 

9. JSP 수정

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

<!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=UTF-8">
</head>
<body>
    ${message} 
    <br/>
    <br/>
    <table border="1">
     <!- DB에서 조회한 데이터 Display 하는 영역 -->
     <c:forEach var="TestTableData" items="${TestTalbeDataList}" >
          <tr>
           <td>name</td>
           <td>age</td>
           <td>sex</td>
          </tr>
         <tr>
            <td>${TestTableData.name}</td>
            <td>${TestTableData.age}</td>
            <td>${TestTableData.sex}</td>
          </tr>
      </c:forEach>
    </table>

</body>
</html>

결과확인




이제 spring Framework + iBatis 까징 설정 했으니 logging만 설정하믄 기본적인 준비는 다 되는 것 같다.

FOCUS
spring Framework에 logging 설정


Reference
1. http://shonm.tistory.com/217
2. http://blog.outsider.ne.kr/561

Need to know
/main/resource/ log4j.properties 파일이 위치하게 하는 설정법은 어떻게 하는거지?


1. /WEB-INF/ web.xml 에 아래와 같이 listener 추가.
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>

2. /WEB-INF/web.xml 에서 Log4J 설정파일 위치 설정

<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/logging/log4j.properties</param-value>
</context-param>

3. log4j 설정 파일인 log4j.properties 작성

  2.에서 설정한 위치에 log4j.properties 작성.


4. code 에 logging 적용시

private Logger log = Logger.getLogger(this.getClass());   
...
...

log.debug("this is spring Framework logger Test");

'스프링3.0' 카테고리의 다른 글

contextConfigLocation  (0) 2012.07.04
MyBatis  (0) 2012.07.03
Srping 3.0 sqlSession+DataSource 구현 하기. (Spring+mybatise0  (0) 2012.05.19
web.xml 구현부 encoder  (0) 2012.05.19
Spring 개발 환경 .  (0) 2012.05.19
Posted by 사라링

=================================


applicationcontext.xml


applicationDataSource.xml


db.properties


web-servlet.xml

=================================




먼저  web.xml 에 context-param 울 추가 하자.

여기서  classpath 의 값이 application*.xml 인 이유는

추후 DB 연결인 datasource 구현및 AOP 구현을 위해 만드는 것이다.

applicationAOP.xml 이면 AOP 구현 

applicationcontext.xml   context 구현

applicationDataSource.xml 이면 DS 구현   이다.


본래 마이바 티스 에서는

MyBatiseFacotry.java


config.xml

을 이런식으로 구현 하게 된다.

dipather의 즉 조립기에서는 연결된 sqlSessionFactoryBean을 만들기 위해서 application 구현부에 등록을 먼저 해야 한다.


applicationDataSource.xml 를 경로에 맞기 생성하자. Datasource 에서는 크게 3개의 컨테이너(bean) 울 구현 해야 한다.

먼저 datasource 를 보자 .


여기서 defaultAutoComiit의 경우 기본 값을  true 이나. comiit(커멧이 무엇인지는 알거라 믿음)이 여기서 ture 인경우 성능에 문제가 발생 된다고 한다.

아마도 select 문 의 경우 commit 필요 업는데도 불필요 하게 실행 되는등등의 문제가 있는듯 하다. 


라고 만들면 된다 .

p:configLocation 의 경우 


이렇게 구현되어 진다. 기존의 config.xml 이 데이터 베이스에 대한 것에 대하여 다 입력 되어 있었던것을 기억해 두자. 

이후에 같은 경로에 applicationcontext.xml 을 만들어 보자. 먼저 할것은


을 추가 하자 db 연결에 대한 설정 파일을  properties 에서 설정 함을 알수 있다.

이렇게 설정만들어 보자. !!


   MyBatis 에서 제공하는 MapperFacetoryBean 을 이용하여  프락시(대행)객체를 생성하여 호출
   단, 기존 dao의 로직이 있는 경우는 안됨,  해당 로직은 다른곳(서비스)에서 처리 한마디로 마이바티스 를 안만들고 자체적으로 처리됨.


mybatis-spring-1.1.1.jar

을 추가하자. 

그 후에 bean 컨테이너를 짜야 한다.


이런식으로!!!

추가:

p:sqlSessionFactory-ref="sqlSessionFactoryBean" 의 경우 반드시 service 구현부 에서 set 로 구현 되어야 한다.

ex)


이렇게 구현 하자 .

그리고

이것도 까먹지 말자. 생성 할때 추가 하던가 하는게 좋다.






'스프링3.0' 카테고리의 다른 글

MyBatis  (0) 2012.07.03
스프링 3.0 + ibatise  (0) 2012.07.03
web.xml 구현부 encoder  (0) 2012.05.19
Spring 개발 환경 .  (0) 2012.05.19
dispathcer 구현부 web-servlet.xml  (0) 2012.05.19
Posted by 사라링

web.xml 구현부 encoder

2012. 5. 19. 15:55

spring 구현시에 반드시 추가 해야만 한다. 안그러면 한글이 깨진다.


web,xml 구현


    <filter>
        <filter-name>encoding</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encoding</filter-name>
        <url-pattern>*.do</url-pattern>
    </filter-mapping>



을 추가 하자.

Posted by 사라링

Spring 개발 환경 .

2012. 5. 19. 15:06

이클립스에서 스프링을 구현해 보자.


http://www.springsource.org/spring-community-download


접속 하자.


아래와 같이 가입 하라고 나오나. 밑에 단에


(I'd rather not fill in the form. Just take me to the download page)  라고 써있다. 난 그런거 필요 없으니 다운로드

페이지를 보여줘..  라고 한다 클릭해 주자


라고 나온다 여기서 spring-framework-3.1.1.RELEASE-with-docs.zip 또는 아래 것을 다운 받으면 된다. 되도록이면  doc 가 포함 된 것을 받자.


압축을 푼후에 src 폴더의 내용을  builderpacher 또는 lib 폴더에 추가 시킨다.

대략적으로 사용 하는 것만 따로 추출 해보자면


org.springframework.aop-3.1.1.RELEASE.jar


org.springframework.asm-3.1.1.RELEASE.jar


org.springframework.beans-3.1.1.RELEASE.jar


org.springframework.context-3.1.1.RELEASE.jar


org.springframework.context.support-3.1.1.RELEASE.jar


org.springframework.core-3.1.1.RELEASE.jar


org.springframework.expression-3.1.1.RELEASE.jar


org.springframework.jdbc-3.1.1.RELEASE.jar


org.springframework.orm-3.1.1.RELEASE.jar


org.springframework.transaction-3.1.1.RELEASE.jar


org.springframework.web-3.1.1.RELEASE.jar


org.springframework.web.servlet-3.1.1.RELEASE.jar


이다. 각자 다운 받아도 되나 통합 사이트 에서 되도록 받자... ; 용량 문제로 한꺼번에 못올린다.







Posted by 사라링

-------------------

web-servlet.xml

-------------------



만약 스프링 폴더가 없다면 any-frame 에서 스프링 프레임웍을 이클립스에 넣어야 한다. 이클립스 종료후 이클립스 폴더에

설치 ::http://sararing.tistory.com/entry/Spring-%EA%B0%9C%EB%B0%9C-%ED%99%98%EA%B2%BD

core 한글 (애니프레임) 가이드 PDF:http://dev.anyframejava.org/docs/anyframe/plugin/essential/core/1.0.3/reference/pdf/core-1.0.3.pdf


Spring Bean Configuration File 입력후 경로및 파일이름(web-servlet.xml) 을 넣은 next를 하면



이렇게 나온다 여기서 XSD를 추가 해야만 한다. 지속 적으로 사용 하는 경우에 내용을 복사 해서 사용 해도 된다.

AOP 입력 맨 밑에 3.0.XSD 최신판을 추가 체크 하도록 하자.


추가 할것은

이렇게 된다. 만들어 보자.


만들어진 xml파일의 기본 내용은


이렇게 될것이다. 

기본적으로  Spring 에서 MVC 패턴을 구현 하다고 했을때 dipathcer 를 말하는 것은 방금 만든 web-xml 을 말하는 것이다.


dipathcer 구현은 MVC 패턴에서 가장 중심이 되는 것으로 신경써서 구현 해야 한다.  현재 Spring으로 구현 부는 member 와 board 가 있으며 pds 라는 다운로드 까지 포함 되어 있다.

controller 는 anotation을 통해 매핑 되어 있다.

controller 구현 bean을 보자.

위의 내용에 추가 된것을 하나씩 보자. 


내용을 보자면 "kr.or.ddit.web.controller" 경로 의 java 파일을 기본 위치로 설정 되어 컨트롤러를 확인 할수 있도록 되어 있다. 기본적으로 jsp 에서 요청시에 맨처음에 dispahcer 에서 실행 하는 것은 매칭된 controller를 찾는 것이다. 이 경로를 찾기 위에서는 HandlerMapping 이 작동 되는데 여기서는 ID="dahmhandlerMapping"

이라는 이름으로 구현 되어 있다. 참고로 fullpath를 이용 하려면 핸드러 매핑,핸드러 어뎁터 두 곳 모두  p:alwaysUseFullPath="true" 를 줘야 한다.



컨트롤러 매핑의 경우 직접적으로 줄수도 있는데


이렇게 하면 된다.


매핑되어 찾아진 controller 에서는 그 결과 값으로 Model 또는 view 값으로 결과 값을 리턴 하며 반환 값으로 String (controller 구현부에서 확인 가능) 으로 보여줄 view를 검색 하게 되는데 그렇게 보여 지는것을 viewResolver 라고 한다.


여기서 확인 해야 할것은. controller 에서 주는 값을 확인 해야 하는데 그 값에 prefix 는 앞에 suffix 는 뒤에 추가 하는 것을 위미 한다. order의 경우 우선순위를 말한다. 

dispatcher 에서 업로드 를 구현 할수 있는데 이경우 반드시 아이디 값을 = "multipartResolver" 로 줘야 한다.


insert 문이나 edit 문의 경우 결과 값 == 성공 또는 실패 에 대하여 view 단을 따로 구현 하는것은 매우 비효율 적이라고 할수 있다. 따라서 결과 값에 대하여 하나의 message 형태 도는 클래스 형태로 구분 되어 지는데 message 형태로 출력  dispather 또한 가능 하다.



이렇게 하여


실제 경로의 팔일은

이런식으로 구현하면 된다.   message 는 대충 보자.











'스프링3.0' 카테고리의 다른 글

web.xml 구현부 encoder  (0) 2012.05.19
Spring 개발 환경 .  (0) 2012.05.19
DispatcherServlet web.xml 구현부  (0) 2012.05.19
Encoding Filter (web.xml 구현 )  (0) 2012.05.19
Missing artifact ojdbc:ojdbc:jar:14:compile  (0) 2012.05.18
Posted by 사라링

    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--//WEB-INF/web-wervlet.xml을 기본설정 -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:kr/or/ddit/config/web-servlet.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>

'스프링3.0' 카테고리의 다른 글

Spring 개발 환경 .  (0) 2012.05.19
dispathcer 구현부 web-servlet.xml  (0) 2012.05.19
Encoding Filter (web.xml 구현 )  (0) 2012.05.19
Missing artifact ojdbc:ojdbc:jar:14:compile  (0) 2012.05.18
스프링 3.0 AOP 에러. 문제 해결  (1) 2012.05.15
Posted by 사라링

web.xml 구현   


<filter>
        <filter-name>encoding</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encoding</filter-name>
        <url-pattern>*.do</url-pattern>
    </filter-mapping>

'스프링3.0' 카테고리의 다른 글

dispathcer 구현부 web-servlet.xml  (0) 2012.05.19
DispatcherServlet web.xml 구현부  (0) 2012.05.19
Missing artifact ojdbc:ojdbc:jar:14:compile  (0) 2012.05.18
스프링 3.0 AOP 에러. 문제 해결  (1) 2012.05.15
Spring3.0 Tiles  (1) 2012.05.14
Posted by 사라링

전자 정부 프레임웍 .. 프로젝트 만들자 마자 에러 생김..


pom.xml 을 열어 <repository>  <dependency> 추가. 저작권 때문이 라고함. 아놔.



<repository>
    <id>mesir-repo</id>
    <url>http://mesir.googlecode.com/svn/trunk/mavenrepo</url>
</repository>

And you can get the ojdbc14 jar w/this dep. def.

<dependency>
  <groupId>com.oracle</groupId>
  <artifactId>ojdbc14</artifactId>
  <version>10.2.0.4.0</version>
</dependency>    




http://www.jroller.com/mert/entry/oracle_s_ojdbc14_jar_mesir 출처


'스프링3.0' 카테고리의 다른 글

DispatcherServlet web.xml 구현부  (0) 2012.05.19
Encoding Filter (web.xml 구현 )  (0) 2012.05.19
스프링 3.0 AOP 에러. 문제 해결  (1) 2012.05.15
Spring3.0 Tiles  (1) 2012.05.14
Spring3.0 DB  (0) 2012.05.14
Posted by 사라링


에러 메세지 :

심각: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException: Line 17 in XML document from file [D:\workJSP\.metadata\.plugins\org.eclipse.wst.server.core\tmp1\wtpwebapps\dditSpring\WEB-INF\classes\kr\or\ddit\config\applicationAOP.xml] is invalid; nested exception is org.xml.sax.SAXParseException: cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element 'tx:advice'.
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:396)



cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element 'tx:advice'.


 BeanFactory not initialized or already closed - call 'refresh' before accessing beans via the ApplicationContext


등의 에러 메세지가 나왔다. 대충 요약 하면 txManager  인 트렌젝션 매니저를 찾지 못한다는 것이다. 코드를 아무리 분석 해도 문제가 해결 안되었으나 문제는 bean 에 있는 것이 아니라. xsi:schemaLocation 에 있었다.


이 스키마 로케이션에 

xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
  http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
  http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
  http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd"


으로 추가및 수정 하여 문제 해결!!


but no declaration can be found for element

'스프링3.0' 카테고리의 다른 글

Encoding Filter (web.xml 구현 )  (0) 2012.05.19
Missing artifact ojdbc:ojdbc:jar:14:compile  (0) 2012.05.18
Spring3.0 Tiles  (1) 2012.05.14
Spring3.0 DB  (0) 2012.05.14
Spring3.0 View error filedown  (0) 2012.05.14
Posted by 사라링

Spring3.0 Tiles

2012. 5. 14. 19:15

기본 세팅 Tiles 프로젝트 파일


==============================


=================================이론=====================================

컨트롤러생성

template 메뉴에 링크등록

바디생성

dispatcher-servlet.xml 등록

tilesdef.xml 등록 - 타일스 설정


===============================프로젝트===================================
=================================코드=====================================
titlesDemo
src
    kr.spring.tiles.controller
           IndexController
package kr.spring.tiles.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class IndexController {
    @RequestMapping("/index.do")
    public String process() {
            return "index";
        }
}

           Menu1Controller
package kr.spring.tiles.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class Menu1Controller {
    @RequestMapping("/menu1.do")
    public String process() {
            return "menu1";
        }
}

           Menu2Controller
package kr.spring.tiles.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class Menu2Controller {
    @RequestMapping("/menu2.do")
    public String process() {
            return "menu2";
        }
}

           Menu3Controller
package kr.spring.tiles.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class Menu3Controller {
    @RequestMapping("/menu3.do")
    public String process() {
            return "menu3";
        }
}

WebContent
      tiles2def
           tiles2def.xml
<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE tiles-definitions PUBLIC
       "-//Apache Software Foundation//DTD Tiles Configuration 2.1//EN"
       "http://tiles.apache.org/dtds/tiles-config_2_1.dtd">

<tiles-definitions>
    <definition name="index" template="/WEB-INF/viewtiles2/template/layout.jsp">
        <put-attribute name="title"  value="Spring Tiles Example"/>
        <put-attribute name="menu"   value="/WEB-INF/viewtiles2/template/menu.jsp"/>
        <put-attribute name="header" value="/WEB-INF/viewtiles2/template/header.jsp"/>
        <put-attribute name="body"   value="/WEB-INF/viewtiles2/body.jsp"/>
        <put-attribute name="footer" value="/WEB-INF/viewtiles2/template/footer.jsp"/>
    </definition>
   
    <definition name="menu1" extends="index">
        <put-attribute name="body"   value="/WEB-INF/viewtiles2/body-menu1.jsp"/>
    </definition>
   
    <definition name="menu2" extends="index">
        <put-attribute name="body"   value="/WEB-INF/viewtiles2/body-menu2.jsp"/>
    </definition>
   
    <definition name="menu3" extends="index">
        <put-attribute name="body"   value="/WEB-INF/viewtiles2/body-menu3.jsp"/>
    </definition>
</tiles-definitions>

      viewtiles2
           template
                footer.jsp
<%@page contentType="text/html; charset=euc-kr"%>
<div align="center" style="background:yellow;">
    company information
</div>

                header.jsp
<%@page contentType="text/html; charset=euc-kr"%>
<h2 align="center">Spring Tiles Examples!!!</h2>

                layout.jsp
<%@ page contentType="text/html; charset=euc-kr"%>
<%@ taglib prefix="tiles"  uri="http://tiles.apache.org/tags-tiles"%>
 
<!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=utf-8">
        <title><tiles:getAsString name="title" /></title>
    </head>
    <body>

    <table border=0 cellpadding=0 cellspacing=1 bgcolor="#a0a0a0" width="100%">
        <tr height=100 valign="middle" bgcolor="#ffffff">
            <td colspan=2><tiles:insertAttribute name="header"/></td>
        </tr>
        <tr height="670" bgcolor="#ffffff">
            <td width="15%" valign="top"><tiles:insertAttribute name="menu"/></td>
            <td width="85%" align="center"><tiles:insertAttribute name="body"/></td>
        </tr>
        <tr bgcolor="#ffffff">
            <td colspan=2><tiles:insertAttribute name="footer"/></td>
        </tr>
    </table>
    </body>
</html>

                menu.jsp
<%@page contentType="text/html; charset=euc-kr"%>
<ul>
   
    <li><a href="index.do">main</a></li>
    <li><a href="menu1.do">menu1</a></li>
    <li><a href="menu2.do">menu2</a></li>
    <li><a href="menu3.do">menu3</a></li>
</ul>

      body.jsp
<%@page contentType="text/html; charset=euc-kr"%>
<b>main page body !!!</b>

      body-menu1.jsp
<%@page contentType="text/html; charset=euc-kr"%>
<br />
<br />
menu 1 body location

      body-menu2.jsp
<%@page contentType="text/html; charset=euc-kr"%>
<br />
<br />
menu 2 body location

      body-menu3.jsp
<%@page contentType="text/html; charset=euc-kr"%>
<br />
<br />
menu 3 body location

      dispatcher-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <bean class="kr.spring.tiles.controller.IndexController"/>
    <bean class="kr.spring.tiles.controller.Menu1Controller"/>
    <bean class="kr.spring.tiles.controller.Menu2Controller"/>   
    <bean class="kr.spring.tiles.controller.Menu3Controller"/>

    <bean id="tilesConfigurer"
        class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
        <property name="definitions">
            <list>
                <value>/WEB-INF/tiles2def/tilesdef.xml</value>
            </list>
        </property>
        <property name="preparerFactoryClass"
            value="org.springframework.web.servlet.view.tiles2.SpringBeanPreparerFactory" />
    </bean>

    <bean id="viewResolver"
        class="org.springframework.web.servlet.view.UrlBasedViewResolver">
        <property name="viewClass"
            value="org.springframework.web.servlet.view.tiles2.TilesView" />
    </bean>

</beans>

      web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>
  <filter>
    <filter-name>encodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>EUC-KR</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>encodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

index.jsp
<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<%
   response.sendRedirect(request.getContextPath()+"/index.do");
%>

================================결과값====================================


'스프링3.0' 카테고리의 다른 글

Missing artifact ojdbc:ojdbc:jar:14:compile  (0) 2012.05.18
스프링 3.0 AOP 에러. 문제 해결  (1) 2012.05.15
Spring3.0 DB  (0) 2012.05.14
Spring3.0 View error filedown  (0) 2012.05.14
Spring3.0 MVC 웹요청 처리  (0) 2012.05.14
Posted by 사라링

Spring3.0 DB

2012. 5. 14. 19:14

기본프로젝트
=================
완료프로젝트


=================================이론=====================================
p394

p412

p416

    //@Valid @InitBinder 와 연동해서 검증을 해줌
    @RequestMapping(value="/update.do", method=RequestMethod.POST)
    public String submit(@Valid MemberCommand memberCommand, BindingResult result){

        if(result.hasErrors()){
            return formViewName;
        }
        memberDao.updateMember(memberCommand);
        return "redirect:/list.do";
    }
    @InitBinder //initBinder 검증 등록
    protected void initBinder(WebDataBinder binder){
        binder.setValidator(new MemberValidator());
    }




===============================프로젝트===================================



=================================코드=====================================



===============================출력결과===================================


DB MEMBER1 테이블


멤버등록



리스트뿌리기

상세보기

수정하기

삭제하기






'스프링3.0' 카테고리의 다른 글

스프링 3.0 AOP 에러. 문제 해결  (1) 2012.05.15
Spring3.0 Tiles  (1) 2012.05.14
Spring3.0 View error filedown  (0) 2012.05.14
Spring3.0 MVC 웹요청 처리  (0) 2012.05.14
Spring 3.0 AOP  (0) 2012.05.14
Posted by 사라링

기본 세팅 프로젝트 파일


=================================이론=====================================
P309
뷰 영역 구현
P260
에러코드의 출력

P361
파일다운로드처리

p373~378
국제화처리

p362~367
엑셀,pdf 파일다운로드



===============================프로젝트===================================
chap07
src
    madvirus.spring.chap07.controller
           AuthenticationException *1 - 로그인 테스트 뷰영역 구현 에러코드출력
           Authenticator *1
           DownloadController *2 - 파일다운로드
           LocaleChangeController *3 - p376 Locale resolver
           LoginCommandValidator *1
           LoginCommnad *1
           LoginController *1
           MockAuthenticator *1
           PageRank *4 - 엑셀파일
           PageRanksController *4 - 엑셀파일 다운로드
           PageReportController *4 - pdf파일
    madvirus.spring.chap07.view
           DownloadView *2
           PageRanksView *4 - 엑셀파일
           PageReportView *4 - pdf파일

     messages
           label_en.properties *1
           label.properties *1
           validation_en.properties *1
           validation.properties *1

WebContent
      viewjsp
           loginForm.jsp *1
           loginSuccess.jsp *1

      dispatcherInternal-servlet.xml *1
      dispatcherNonHtml-servlet.xml *2
      web.xml

index.jsp
=================================코드=====================================
chap07
src
    madvirus.spring.chap07.controller
           AuthenticationException *1 - 로그인 테스트 뷰영역 구현 에러코드출력
package madvirus.spring.chap07.controller;

public class AuthenticationException extends RuntimeException {

    private static final long serialVersionUID = 1L;

    public AuthenticationException(String message) {
        super(message);
    }
}

           Authenticator *1
package madvirus.spring.chap07.controller;

public interface Authenticator {
    void authenticate(String id,String password);
}

           DownloadController *2 - 파일다운로드
package madvirus.spring.chap07.controller;

import java.io.File;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.ModelAndView;
    
@Controller
public class DownloadController implements ApplicationContextAware {

    private WebApplicationContext context = null;
   
    @RequestMapping("/file")
    public ModelAndView download() throws Exception {
        File downloadFile = getFile();
        return new ModelAndView("download","downloadFile",downloadFile);
    }
   
    private File getFile(){
        String path = context.getServletContext().getRealPath("/WEB-INF/설명.txt");
        return new File(path);
    }
   
    public void setApplicationContext(ApplicationContext applicationContext)throws BeansException {
        this.context = (WebApplicationContext)applicationContext;
    }
}

           LocaleChangeController *3 - p376 Locale resolver
package madvirus.spring.chap07.controller;

import java.util.Locale;

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

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.LocaleResolver;

@Controller
public class LocaleChangeController {

    private LocaleResolver localeResolver;

    @RequestMapping("/changLanguage")
    public String change(@RequestParam("lang")String language,HttpServletRequest request, HttpServletResponse response){
        Locale locale = new Locale(language);
        localeResolver.setLocale(request, response, locale);
        return "redirect:/index.jsp";
    }           
    public void setLocaleResolver(LocaleResolver localeResolver){
        this.localeResolver = localeResolver;
    }
}

           LoginCommandValidator *1
package madvirus.spring.chap07.controller;

import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;

public class LoginCommandValidator implements Validator {

    public void validate(Object target, Errors errors) {
        //비어있거나 공백이있으면 돌려보냄
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "id", "required");
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "password", "required");
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "loginType", "required");
    }

    public boolean supports(Class<?> clazz) {
        return LoginCommnad.class.isAssignableFrom(clazz);
    }   
}

           LoginCommnad *1
package madvirus.spring.chap07.controller;

public class LoginCommnad {
   
    private String id;
    private String password;
    private String loginType;
   
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public String getLoginType() {
        return loginType;
    }
    public void setLoginType(String loginType) {
        this.loginType = loginType;
    }
}

           LoginController *1
package madvirus.spring.chap07.controller;

import java.util.ArrayList;
import java.util.List;

import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

   /*//web.xml 에서 
  <servlet-mapping>
    <servlet-name>dispatcherInternal</servlet-name>
    <url-pattern>/jsp/*</url-pattern>
  </servlet-mapping>  => /jsp/login/login.do */
@Controller  
@RequestMapping("/login/login.do")
public class LoginController {

    private Authenticator authenticator;

    @ModelAttribute("login")
    public LoginCommnad formBacking(){
        return new LoginCommnad();
    }

    @RequestMapping(method = RequestMethod.GET)
    public String form(){
        return "loginForm";
    }

    @RequestMapping(method = RequestMethod.POST)
    public String submit(@ModelAttribute("login") LoginCommnad loginCommand,BindingResult result){
        new LoginCommandValidator().validate(loginCommand, result);

        if(result.hasErrors()){
            return "loginForm";
        }
        try{
            authenticator.authenticate(loginCommand.getId(), loginCommand.getPassword());

            return "loginSuccess";
        }catch (AuthenticationException ex){                    //null : loginCommand.getId() 가 null이면 default 값
            result.reject("invalidIdOrPassword", new Object[] {loginCommand.getId()},null);
            return "loginForm";
        }
    }

    @ModelAttribute("loginTypes")
    protected List<String> referenceData() throws Exception {
        List<String> loginTypes = new ArrayList<String>();
        loginTypes.add("일반회원");
        loginTypes.add("기업회원");
        loginTypes.add("헤드헌터회원");
        return loginTypes;
    }
   
    public void setAuthenticator(Authenticator authenticator){
        this.authenticator = authenticator;
    }
}

           MockAuthenticator *1
package madvirus.spring.chap07.controller;

public class MockAuthenticator implements Authenticator{

    public void authenticate(String id, String password) {
        if(!id.equals("madvirus")){
            throw new AuthenticationException("invalid id"+ id);
        }       
    }
}

           PageRank *4 - 엑셀파일
package madvirus.spring.chap07.controller;

public class PageRank {
 
    private int rank;
    private String page;
   
    public PageRank() {
    }
   
    public PageRank(int rank, String page) {
        super();
        this.rank = rank;
        this.page = page;
    }
   
    public int getRank() {
        return rank;
    }
    public String getPage() {
        return page;
    }   
}

           PageRanksController *4 - 엑셀파일 다운로드
package madvirus.spring.chap07.controller;

import java.util.ArrayList;
import java.util.List;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class PageRanksController {

    @RequestMapping("/pageRanks")
    public ModelAndView handleRequestInternal(){
       
        List<PageRank> pageRanks = new ArrayList<PageRank>();
       
        pageRanks.add(new PageRank(1, "/bbs/mir2/list"));
        pageRanks.add(new PageRank(2, "/bbs/mir3/list"));
        pageRanks.add(new PageRank(3, "/bbs/changchun2/list"));
       
        return new ModelAndView("pageRanks","pageRanks",pageRanks);
    }
}

           PageReportController *4 - pdf파일
package madvirus.spring.chap07.controller;

import java.util.ArrayList;
import java.util.List;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class PageReportController {

    @RequestMapping("/pageReport")
    public ModelAndView pdfReport(){
        List<PageRank> pageRanks = new ArrayList<PageRank>();
        pageRanks.add(new PageRank(1, "/bbs/mir2/list"));
        pageRanks.add(new PageRank(2, "/bbs/mir3/list"));
        pageRanks.add(new PageRank(3, "/bbs/changchun2/list"));
        return new ModelAndView("pageReport","pageRanks",pageRanks);
    }
}

    madvirus.spring.chap07.view
           DownloadView *2
package madvirus.spring.chap07.view;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.Map;

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

import org.springframework.util.FileCopyUtils;
import org.springframework.web.servlet.view.AbstractView;

public class DownloadView extends AbstractView {

    public DownloadView() {
        setContentType("application/download; charset=utf-8");
    }
       
    @Override
    protected void renderMergedOutputModel(Map<String, Object> model,
            HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        File file = (File) model.get("downloadFile");

        response.setContentType(getContentType());
        response.setContentLength((int) file.length());

        String userAgent = request.getHeader("User-Agent");
        boolean ie = userAgent.indexOf("MSIE") > -1;
        String fileName = null;
        if (ie) {
            fileName = URLEncoder.encode(file.getName(), "utf-8");
        } else {
            fileName = new String(file.getName().getBytes("utf-8"),
                    "iso-8859-1");
        }
        response.setHeader("Content-Disposition", "attachment; filename=\""
                + fileName + "\";");
        response.setHeader("Content-Transfer-Encoding", "binary");
        OutputStream out = response.getOutputStream();
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(file);
            FileCopyUtils.copy(fis, out);
        } finally {
            if (fis != null)
                try {
                    fis.close();
                } catch (IOException ex) {
                }
        }
        out.flush();
    }
}

           PageRanksView *4 - 엑셀파일
package madvirus.spring.chap07.view;

import java.util.List;
import java.util.Map;

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

import madvirus.spring.chap07.controller.PageRank;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.web.servlet.view.document.AbstractExcelView;

public class PageRanksView extends AbstractExcelView {

    //@SuppressWarnings("unchecked") : 문법에 문제가없는데 나오는 노란줄 경고 안나오게함
    @SuppressWarnings("unchecked")
    @Override
    protected void buildExcelDocument(Map<String, Object> model,
            HSSFWorkbook workbook, HttpServletRequest request,
            HttpServletResponse response) throws Exception {
        HSSFSheet sheet = createFirstSheet(workbook);
        createColumnLabel(sheet);

        List<PageRank> pageRanks = (List<PageRank>) model.get("pageRanks");
        int rowNum = 1;
        for (PageRank rank : pageRanks) {
            createPageRankRow(sheet, rank, rowNum++);
        }
    }

    private HSSFSheet createFirstSheet(HSSFWorkbook workbook) {
        HSSFSheet sheet = workbook.createSheet();
        workbook.setSheetName(0, "페이지 순위");
        sheet.setColumnWidth(1, 256 * 20);
        return sheet;
    }

    private void createColumnLabel(HSSFSheet sheet) {
        HSSFRow firstRow = sheet.createRow(0);
        HSSFCell cell = firstRow.createCell(0);
        cell.setCellValue("순위");

        cell = firstRow.createCell(1);
        cell.setCellValue("페이지");
    }

    private void createPageRankRow(HSSFSheet sheet, PageRank rank, int rowNum) {
        HSSFRow row = sheet.createRow(rowNum);
        HSSFCell cell = row.createCell(0);
        cell.setCellValue(rank.getRank());

        cell = row.createCell(1);
        cell.setCellValue(rank.getPage());

    }
}

           PageReportView *4 - pdf파일
package madvirus.spring.chap07.view;

import java.util.List;
import java.util.Map;

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

import madvirus.spring.chap07.controller.PageRank;

import org.springframework.web.servlet.view.document.AbstractPdfView;

import com.lowagie.text.Cell;
import com.lowagie.text.Document;
import com.lowagie.text.Font;
import com.lowagie.text.Paragraph;
import com.lowagie.text.Table;
import com.lowagie.text.pdf.BaseFont;
import com.lowagie.text.pdf.PdfWriter;

public class PageReportView extends AbstractPdfView {

    @SuppressWarnings("unchecked")
    @Override
    protected void buildPdfDocument(Map<String, Object> model,
            Document document, PdfWriter writer, HttpServletRequest request,
            HttpServletResponse response) throws Exception {
        List<PageRank> pageRanks = (List<PageRank>) model.get("pageRanks");
        Table table = new Table(2, pageRanks.size() + 1);
        table.setPadding(5);

        BaseFont bfKorean = BaseFont.createFont(
                "c:\\windows\\fonts\\batang.ttc,0", BaseFont.IDENTITY_H,
                BaseFont.EMBEDDED);

        Font font = new Font(bfKorean);
        Cell cell = new Cell(new Paragraph("순위", font));
        cell.setHeader(true);
        table.addCell(cell);
        cell = new Cell(new Paragraph("페이지", font));
        table.addCell(cell);
        table.endHeaders();

        for (PageRank rank : pageRanks) {
            table.addCell(Integer.toString(rank.getRank()));
            table.addCell(rank.getPage());
        }
        document.add(table);
    }
}

     messages
           label_en.properties *1
login.form.title=Login Form
login.form.type=Login Type
login.form.id=ID
login.form.password=Password
login.form.submit=Login

           label.properties *1
login.form.title=로그인
login.form.type=로그인 타입
login.form.id=회원Id
login.form.password=비밀번호
login.form.submit=전송

           validation_en.properties *1
required=required
required.login.id=login id is required
required.login.password=login password is requreid
required.login.loginType=You have to select login type
invalidIdOrPassword.login=Login id and password do not match. (You provided {0})

           validation.properties *1
required=필수입니다.
required.login.id=ID는 필수입니다.
required.login.password=비밀번호는 필수입니다.
required.login.loginType=로그인 타입을 선택하세요.
invalidIdOrPassword.login=당신이 입력한 id {0}. 로그인 아이디와 비밀번호가 일치하지 않습니다.

WebContent
      viewjsp
           loginForm.jsp *1
<%@ page contentType="text/html; charset=EUC-KR" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title><spring:message code="login.form.title"/></title>
</head>
<body>
<form:form commandName="login">
<form:errors />
<p>                       
    <label for="loginType"><spring:message code="login.form.type" /></label>
    <form:select path="loginType" items="${loginTypes}" />
</p>
<p>
    <label for="id"><spring:message code="login.form.id" /></label>
    <form:input id="id" path="id"/>
    <form:errors path="id" />
</p>
<p>
    <label for="password"><spring:message code="login.form.password" /></label>
    <form:password id="password" path="password"/>
    <form:errors path="password" />
</p>
<p>
    <input type="submit" value="<spring:message code="login.form.submit" />">
</p>
</form:form>
</body>
</html>

           loginSuccess.jsp *1
<%@ page language="java" contentType="text/html; charset=EUC-KR" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>로그인 성공</title>
</head>
<body>
로그인에 성공했습니다.
</body>
</html>

      dispatcherInternal-servlet.xml *1
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <!-- 커스텀태그이용 -->
    <bean class="madvirus.spring.chap07.controller.LoginController">
        <property name="authenticator">
            <bean class="madvirus.spring.chap07.controller.MockAuthenticator"/>
        </property>
    </bean>   
   
    <!-- 국제화 -->
    <bean class="madvirus.spring.chap07.controller.LocaleChangeController">
        <property name="localeResolver" ref="localeResolver"/>
    </bean>
    <bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver"/>
   
    <!-- 국제화2 -->
    <bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" p:paramName="language"/>
    <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
        <property name="interceptors">
            <list>
                <ref bean="localeChangeInterceptor"/>
            </list>
        </property>
    </bean>
   
    <!-- View 글로벌 설정 -->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/viewjsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
   
    <!-- 리소스 번들 지정 -->
    <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
        <property name="basenames">
            <list>
                <value>messages.validation</value>
                <value>messages.label</value>
            </list>
        </property>   
    </bean>
</beans>

      dispatcherNonHtml-servlet.xml *2
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans  
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <!-- 파일 다운로드 -->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
    <bean id="downloadController" class="madvirus.spring.chap07.controller.DownloadController"/>
    <bean id="download" class="madvirus.spring.chap07.view.DownloadView"></bean>
   
   
    <!-- 엑셀 다운로드 -->
    <bean id="pageRanksController" class="madvirus.spring.chap07.controller.PageRanksController" />
    <bean id="pageRanks" class="madvirus.spring.chap07.view.PageRanksView" />

    <!-- PDF 다운로드 -->
    <bean id="pageReportController" class="madvirus.spring.chap07.controller.PageReportController" />
    <bean id="pageReport" class="madvirus.spring.chap07.view.PageReportView"/>
   
    </beans>      

      web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <context-param>
    <param-name>defaultHtmlEscape</param-name>
    <param-value>false</param-value>
  </context-param>
  <servlet>
    <servlet-name>dispatcherInternal</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcherInternal</servlet-name>
    <url-pattern>/jsp/*</url-pattern>
  </servlet-mapping>
   <servlet>
    <servlet-name>dispatcherNonHtml</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcherNonHtml</servlet-name>
    <url-pattern>/download/*</url-pattern>
  </servlet-mapping>
  <filter>
    <filter-name>encodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>encodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

설명.txt
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!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=UTF-8">
<title>View 연습</title>
</head>
<body>
<a href="http://localhost:8080/chap07/jsp/login/login.do">LoginController </a><br>
<a href="http://localhost:8080/chap07/download/file">DownloadController - 파일 다운로드</a><br>
<a href="http://localhost:8080/chap07/jsp/changLanguage?lang=ko">LocaleChangeController -1 한글</a><br>
<a href="http://localhost:8080/chap07/jsp/changLanguage?lang=en">LocaleChangeController -2 영어</a><br>
<a href="http://localhost:8080/chap07/jsp/login/login.do?language=ko">LocaleChangeInterceptor -1 한글</a><br>
<a href="http://localhost:8080/chap07/jsp/login/login.do?language=en">LocaleChangeInterceptor -2 영어</a><br>
<a href="http://localhost:8080/chap07/download/pageRanks">PageRanksController - 엑셀파일  다운로드</a><br>
<a href="http://localhost:8080/chap07/download/pageReport">PageReportController - PDF파일  다운로드</a><br>
</body> 
</html>

===============================결과값====================================

1.로그인 테스트


en_US


ko_KR


2.다운로드


3. 국제화 LocaleReslover를 이용한 Locale 변경


국제화 LocaleChangeInterceptor


4.엑셀파일 다운로드 , PDF 다운로드





'스프링3.0' 카테고리의 다른 글

Spring3.0 Tiles  (1) 2012.05.14
Spring3.0 DB  (0) 2012.05.14
Spring3.0 MVC 웹요청 처리  (0) 2012.05.14
Spring 3.0 AOP  (0) 2012.05.14
Spring3.0 DI 3  (0) 2012.05.14
Posted by 사라링

프로젝트 기본설정상태

완료파일

=====================


스프링 MVC를 이용한 웹 요청 처리


=================================이론=====================================

스프링의 MVC의 주요 구성요소
DispatcherServlet : Struts2의 컨트롤러 :
HandlerMapping :
컨트롤러(Controller) : Struts2의 액션 :
ModelAndView :
뷰(View) :


실행 흐름 정리 : http://javai.tistory.com/561

웹브라우저 hello.do -> Dispatcher : DispatcherServlet
컨트롤러 요청 DefaultAnnotationHandlerMapping
HelloController 빈 리턴 -> Dispatcher : DispatcherServlet
처리요청 HelloController -> 모델뷰 리턴 -> Dispatcher : DispatcherServlet
hello에 매칭되는 View 객체 요청 ViewResolver : InternalResourceViewResolver 뷰 리턴 -> Dispatcher : DispatcherServlet
응답 생성 요청 -> InternalResourceView -> JSP를 이용하여 응답생성 -> hello.jsp

Dispatcher : DispatcherServlet 가 모든것을 컨트롤 하는것을 알 수 있다(Struts2의 Controller와 같은 역할)


커맨드 객체로 List 받기
자바빈->ArrayList넣기

컨트롤러 메서드의 파라미터 타입


1.@RequestParam 이용한 파라미터 매핑
필수가 아닌 파라미터의 경우 required 속성값을 false로 지정(기본값이 true)

@Controller
public class SearchController {
   
    @RequestMapping("/search/internal.do")
    public ModelAndView searchInternal(@RequestParam("query") String query, @RequestParam(value = "p", defaultValue = "1")int pageNumber){               //메서드명은 마음대로
        System.out.println("query="+query+",pageNumber"+pageNumber);
       
        return new ModelAndView("search/internal");
    }

    @RequestMapping("/search/external.do")
    public ModelAndView searchExternal(@RequestParam(value="query", required=false)String query,@RequestParam(value="p",defaultValue = "1")int pageNumber){   //메서드명은 마음대로
        System.out.println("query="+query+",pageNumber"+pageNumber);
   
    return new ModelAndView("search/external");
    }
}

dispatcher-servlet.xml 설정
    <!-- 파라미터로 전송된 데이터 처리 -->
    <bean id="searchController" class="madvirus.spring.chap06.controller.SearchController"/>


2.@CookieValue 어노테이션을 이용한 쿠키 매핑

필수가 아닌 쿠키의 경우 required 속성값을 false로 지정(기본값이 true)

@Controller
public class CookieController {
    @RequestMapping("/cookie/make.do")
    public String make(HttpServletResponse response){
        response.addCookie(new Cookie("auth", "1"));
        return "cookie/made";
    }

    //@CookieValue 어노테이션은 클라이언트가 제공하는 쿠키정보를 읽어드림
    @RequestMapping("/cookie/view.do")
    public String view(@CookieValue(value ="auth", defaultValue="0") String auth){
        System.out.println("auth 쿠기 : " + auth);
        return "cookie/view";
    }
}

<!-- @CookieValue 어노테이션을 이용한 쿠키 매핑 -->
<bean id="cookieController" class="madvirus.spring.chap06.controller.CookieController"/>


@RequestMappign(요청URL)

public [return 타입 P231] process([파라미터 타입 P225]  )

return 타입 - 1. ModelAndView :  View,View 개체
                   2. String : View
                   3. Map,Model : 키와 값을 쌍으로 저장할때

5.예제 @RequestHeader
 


@ModelAttribute 검색



Validator인터페이스를 이용한 폼 값 검증



예제9
restful 서비스

http://localhost:8080/chap06/index.do?id=dragon => http://localhost:8080/chap06/index/id/dragon




===============================프로젝트===================================


=================================코드=====================================
chap06
      src
          madvirus.spring.chap06.controller
              ArithmeticOperatorController (11.예제 예외페이지)
package madvirus.spring.chap06.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class ArithmeticOperatorController {

    @RequestMapping("/math/divide.do")
    public String divide(@RequestParam("op1") int op1, @RequestParam("op2") int op2, Model model){
        model.addAttribute("result", op1 / op2);
       
        return "math/result";
    }
}

              CharacterInfoController (9.예제 restful서비스)
package madvirus.spring.chap06.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class CharacterInfoController {
   
    @RequestMapping("/game/users/{userId}/characters/{characterId}")
    public String characterInfo(@PathVariable String userId, @PathVariable int characterId, ModelMap model){
        model.addAttribute("userId",userId);
        model.addAttribute("characterId", characterId);
        return "game/character/info";
       
    }   
}

              CookieController (4.예제 @CookieValue)
package madvirus.spring.chap06.controller;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class CookieController {
    @RequestMapping("/cookie/make.do")
    public String make(HttpServletResponse response){
        response.addCookie(new Cookie("auth", "1"));
        return "cookie/made"; //View 경로
    }

    //@CookieValue 어노테이션은 클라이언트가 제공하는 쿠키정보를 읽어드림
    @RequestMapping("/cookie/view.do")
    public String view(@CookieValue(value ="auth", defaultValue="0") String auth){
        System.out.println("auth 쿠기 : " + auth);
        return "cookie/view";
    }
}

              CreateAccountController (7.예제)
package madvirus.spring.chap06.controller;

import javax.servlet.http.HttpServletRequest;

import madvirus.spring.chap06.model.Address;
import madvirus.spring.chap06.model.MemberInfo;
import madvirus.spring.chap06.validator.MemberInfoValidator;

import org.springframework.jmx.export.assembler.AutodetectCapableMBeanInfoAssembler;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping("/account/create.do")
public class CreateAccountController {

    //Command 객체 초기화
    @ModelAttribute("command")
    public MemberInfo formBacking(HttpServletRequest request){
        //equalsIgnoreCase : 대소문자 관계없이 비교해줌 단!영문만 가능
        if(request.getMethod().equalsIgnoreCase("GET")){
            MemberInfo mi = new MemberInfo();
            Address address= new Address();
            address.setZipcode(autoDetectZipcode(request.getRemoteAddr()));
            mi.setAddress(address);
            return mi;
        }else{
            return new MemberInfo();
        }
    }
   
    private String autoDetectZipcode(String remoteAddr){
        return "000000";
    }
   
    @RequestMapping(method = RequestMethod.GET)
    public String form(){
        return "account/creationForm";
    }
   
    @RequestMapping(method = RequestMethod.POST)
    public String submit(@ModelAttribute("command")MemberInfo memberInfo,BindingResult result){
       
        new MemberInfoValidator().validate(memberInfo, result);
       
        if(result.hasErrors()){
            return "account/creationForm";
        }
        return "account/created";
    }
}

              GameInfoController (8.예제)
package madvirus.spring.chap06.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class GameInfoController {
   
    //@RequestMapping("/game/info") /game/* 를 탈려면 /game을 하면안됨
    /*  /game/info 로 쓰기위해서는
    <!-- 요청 URI 매칭  -->
    <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
        <property name="alwaysUseFullPath" value="true"/>
    </bean>   
    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
        <property name="alwaysUseFullPath" value="true"/>
    </bean>
    */
    @RequestMapping("/game/info")
    public String gameInfo(){
        return "game/info";
    }
   
    @RequestMapping("/game/list")
    public String gameList(){
        return "game/list";
    }
}

             GameSearchController (6.예제)
package madvirus.spring.chap06.controller;

import java.util.ArrayList;
import java.util.List;

import madvirus.spring.chap06.service.SearchCommand;
import madvirus.spring.chap06.service.SearchResult;
import madvirus.spring.chap06.service.SearchService;
import madvirus.spring.chap06.service.SearchType;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class GameSearchController {

    @Autowired
    private SearchService searchService;
   
    @ModelAttribute("searchTypeList")
    public List<SearchType> referenceSearchTypeList(){
        List<SearchType> options = new ArrayList<SearchType>();
        options.add(new SearchType(1, "전체"));
        options.add(new SearchType(2, "아이템"));
        options.add(new SearchType(3, "캐릭터"));
        return options;       
    }
   
    @ModelAttribute("popularQueryList")
    public String[] getPopularQueryList(){
        return new String[]{"게임","창천2","위메이드"};
    }
   
    @RequestMapping("/search/main.do")
    public String main(){
        return "search/main";
    }
   
    @RequestMapping("/search/game.do")
    public ModelAndView search(@ModelAttribute("command") SearchCommand command){
        ModelAndView mav = new ModelAndView("search/game");
       
        System.out.println("검색어 : " + command.getQuery().toUpperCase());
       
        SearchResult result = searchService.search(command);
        mav.addObject("searchResult",result);
       
        return mav;
    }
   
    @ExceptionHandler(NullPointerException.class)
    public String handleNullPointerException(NullPointerException ex){
        return "error/nullException";
    }
   
    public void setSearchService(SearchService searchService){
        this.searchService = searchService;
    }
}

              HeaderController (5.예제 @RequestHeader)
package madvirus.spring.chap06.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HeaderController {

   
    //@RequestHeader 어노테이션은 클라이언트가 전송한 해더 정보 읽기
    @RequestMapping("/header/check.do")
    public String check(
            @RequestHeader("Accept-Language") String languageHeader){
        System.out.println(languageHeader);
       
        return "header/pass";
    }
}

              HelloController (1.예제) - 스프링의 컨트롤러는 Struts2의 액션
package madvirus.spring.chap06.controller;

import java.util.Calendar;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

//컨트롤러 (Struts2 의 Action과 동일)을 구현하기 위해 @Controller 명시
@Controller
public class HelloController {

    //클라이언트의 요청에 대해 호출되는 메소드 지정
    @RequestMapping("/hello.do")
    public ModelAndView hello(){ //메소드명은 마음대로
        //View에 정보를 전달하기 위해 ModelAndView 객체 생성
        ModelAndView mav = new ModelAndView();
        //View의 이름 지정
        mav.setViewName("hello");
        //View에 사용할 데이터 저장
        mav.addObject("greeting", getGreeting());
        return mav;
    }
   
    private String getGreeting(){
        int hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
       
        if(hour >=6 && hour <=10 ){
            return "좋은 아침입니다.";
        }else if(hour >=12 && hour <=15 ){
            return "점심 식사는 하셨나요?";           
        }else if(hour >=18 && hour <=22 ){
            return "좋은 밤 되세요";
        }
        return "안녕하세요";
    }   
}

              NewArticleController (2.예제)
package madvirus.spring.chap06.controller;

import madvirus.spring.chap06.service.ArticleService;
import madvirus.spring.chap06.service.NewArticleCommand;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/*스탠다드 포맷 */


//컨트롤러 설정
@Controller
//클라이언트의 요청에 대해서 호출하는 메서드 지정
@RequestMapping("/article/newArticle.do")
public class NewArticleController {
   
    @Autowired
    private ArticleService articleService;
   
    @RequestMapping(method = RequestMethod.GET)
    public String form(){ //메소드가 지정되어 있는것은 아니지만 일반적으로 사용하는 명칭
        //리턴값은 View설정
        //글로벌설정이 /WEB-INF/view/ 이라  맨앞에/없음
        return "article/newArticleForm";
    }

    @RequestMapping(method = RequestMethod.POST)
                        //Command(자바빈) 클래스 설정)
    public String submit(@ModelAttribute("command") NewArticleCommand command){
        articleService.writeArticle(command);
        //리턴값은 View설정
        return "article/newArticleSubmitted";
    }
   
    public void setArticleService(ArticleService articleService){
        this.articleService =articleService;
    }   
}

              SearchController (3.예제 @RequestParam)
package madvirus.spring.chap06.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class SearchController {
   
    @RequestMapping("/search/internal.do")
    public ModelAndView searchInternal(@RequestParam("query") String query, @RequestParam(value = "p", defaultValue = "1")int pageNumber){
        System.out.println("query="+query+",pageNumber"+pageNumber);
       
        return new ModelAndView("search/internal");
    }
   
    @RequestMapping("/search/external.do")
    public ModelAndView searchExternal(@RequestParam(value="query", required=false)String query,@RequestParam(value="p",defaultValue = "1")int pageNumber){
        System.out.println("query="+query+",pageNumber"+pageNumber);
   
    return new ModelAndView("search/external");
    }
}

          SubmitReportController (10.예제 파일업로드)
package madvirus.spring.chap06.model;

import org.springframework.web.multipart.MultipartFile;

//스프링의 Command = 자바빈
public class SubmitReportCommand {

    private String subject;
    private MultipartFile reportFile;
   
    public String getSubject() {
        return subject;
    }
    public void setSubject(String subject) {
        this.subject = subject;
    }
    public MultipartFile getReportFile() {
        return reportFile;
    }
    public void setReportFile(MultipartFile reportFile) {
        this.reportFile = reportFile;
    }   
}

          madvirus.spring.chap06.model
              Address (예제7. Command클래스)
package madvirus.spring.chap06.model;

public class Address {
    private String zipcode;
    private String address1;
    private String address2;
   
    public String getZipcode() {
        return zipcode;
    }
    public void setZipcode(String zipcode) {
        this.zipcode = zipcode;
    }
    public String getAddress1() {
        return address1;
    }
    public void setAddress1(String address1) {
        this.address1 = address1;
    }
    public String getAddress2() {
        return address2;
    }
    public void setAddress2(String address2) {
        this.address2 = address2;
    }
}

              MemberInfo (7.예제)
package madvirus.spring.chap06.model;

public class MemberInfo {

    private String id;
    private String name;
    private Address address;
   
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Address getAddress() {
        return address;
    }
    public void setAddress(Address address) {
        this.address = address;
    }   
}

             SubmitReportCommand (10.예제 파일업로드)
package madvirus.spring.chap06.model;

import org.springframework.web.multipart.MultipartFile;

//스프링의 Command = 자바빈
public class SubmitReportCommand {

    private String subject;
    private MultipartFile reportFile;
   
    public String getSubject() {
        return subject;
    }
    public void setSubject(String subject) {
        this.subject = subject;
    }
    public MultipartFile getReportFile() {
        return reportFile;
    }
    public void setReportFile(MultipartFile reportFile) {
        this.reportFile = reportFile;
    }   
}

          madvirus.spring.chap06.service
             ArticleService (2.예제)
package madvirus.spring.chap06.service;

public class ArticleService {

    public void writeArticle(NewArticleCommand command) {
        System.out.println("신규 게시글 등록: " + command);
    }
}

              NewArticleCommand (2.예제)
package madvirus.spring.chap06.service;

// *Command = 자바빈과 같은 기능  Command라 부른다.
public class NewArticleCommand {

    private String title;
    private String content;
    private int parentId;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public int getParentId() {
        return parentId;
    }

    public void setParentId(int parentId) {
        this.parentId = parentId;
    }

    @Override
    public String toString() {
        return "NewArticleCommand [content=" + content + ", parentId="
                + parentId + ", title=" + title + "]";
    }
}

             SearchCommand (6.예제)
package madvirus.spring.chap06.service;
//자바빈
public class SearchCommand {

    private String type;
    private String query;
    private int page;
   
    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }
    public String getQuery() {
        return query;
    }
    public void setQuery(String query) {
        this.query = query;
    }
    public int getPage() {
        return page;
    }
    public void setPage(int page) {
        this.page = page;
    }   
}

             SearchResult (6.예제)
package madvirus.spring.chap06.service;

public class SearchResult {

}

             SearchService (6.예제)
package madvirus.spring.chap06.service;

public class SearchService {

    //SearchCommand 객체를 받는거
    public SearchResult search(SearchCommand command){
        return new SearchResult();
    }
}

             SearchType (6.예제)
package madvirus.spring.chap06.service;

public class SearchType {
   
    private int code;
    private String text;   
   
    public SearchType(int code, String text) {
        super();
        this.code = code;
        this.text = text;
    }
   
    public int getCode() {
        return code;
    }
    public void setCode(int code) {
        this.code = code;
    }
    public String getText() {
        return text;
    }
    public void setText(String text) {
        this.text = text;
    }   
}

          madvirus.spring.chap06.validator
             MemberInfoValidator (7.예제 검증)
package madvirus.spring.chap06.validator;

import madvirus.spring.chap06.model.Address;
import madvirus.spring.chap06.model.MemberInfo;

import org.springframework.validation.Errors;
import org.springframework.validation.Validator;

public class MemberInfoValidator implements Validator{

    //Validator가 해당 클래스에 대한 값 검증을 지원하는지 여부를 리턴
    @Override
    public boolean supports(Class<?> clazz) {
        return MemberInfo.class.isAssignableFrom(clazz);
    }

    //target객체에 대한 검증을 실행
    @Override
   
    public void validate(Object target, Errors errors) {
        MemberInfo memberInfo = (MemberInfo)target;
        if(memberInfo.getId()==null|| memberInfo.getId().trim().isEmpty()){
            errors.rejectValue("id","required");
        }
        if(memberInfo.getName()==null || memberInfo.getName().trim().isEmpty()){
            errors.rejectValue("name", "required");
        }
        Address address = memberInfo.getAddress();
        if(address == null){
            errors.rejectValue("address", "required");
        }
        if(address != null){
            errors.pushNestedPath("address");
            try{
                if(address.getZipcode() == null || address.getZipcode().trim().isEmpty()){
                    errors.rejectValue("zipcode", "required");
                }
                if(address.getAddress1()==null || address.getAddress1().trim().isEmpty()){
                    errors.rejectValue("address1", "required");
                }
            }finally{
                errors.popNestedPath();
            }
        }       
    }   
}

             SubmitReportValidator (10.예제 파일업로드)
package madvirus.spring.chap06.validator;

import madvirus.spring.chap06.model.MemberInfo;
import madvirus.spring.chap06.model.SubmitReportCommand;

import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;

public class SubmitReportValidator implements Validator {

    @Override
    public boolean supports(Class<?> clazz) {

        return SubmitReportCommand.class.isAssignableFrom(clazz);
    }

    @Override
    public void validate(Object target, Errors errors) {
       
        //방식1.데이터가 없는경우 돌려보냄
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "subject", "required");
       
        SubmitReportCommand command = (SubmitReportCommand)target;
       
        //방식2. 일반적인방법
        if(command.getReportFile() ==null || command.getReportFile().isEmpty())
            errors.rejectValue("reportFile", "required");
    }
}

          message
             validation.properties (7예제. 설정파일)
required=필수 항목입니다.
invalidIdOrPassword.logincommand=아이디({0})와 암호가 일치하지 않습니다.
required.loginCommand.userId=사용자 아이디는 필수 항목입니다.
required.password=암호는 필수 항목입니다.
typeMismatch.from=시작일 값 형식은 yyyy-MM-dd 여야 합니다.
typeMismatch.to=종료일 값 형식은 yyyy-MM-dd 여야 합니다.

      WebContent
          WEB-INF
              lib (스프링 다이나믹웹 프로젝트 라이브러리)         
          upload
          view
              account
                  created.jsp (7.예제)
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>계정 생성</title>
</head>
<body>
계정 생성됨
<ul>
 <li>아이디: ${command.id}</li>
 <li>이름: ${command.name}</li>
 <li>우편번호: ${command.address.zipcode}</li>
 <li>주소: ${command.address.address1} ${command.address.address2}</li>
</ul>
</body>
</html> 

                  creationForm.jsp (7.예제)
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>계정 생성</title>
</head>
<body>
<!-- 에러메세지를 처리하귀해서 Spring 사용 -->
<spring:hasBindErrors name="command" />
<form:errors path="command" />
<form method="post">
    아이디: <input type="text" name="id" value="${command.id}" />
    <form:errors path="command.id" />
    <br/>
    이름: <input type="text" name="name" value="${command.name}" />
    <form:errors path="command.name" />
    <br/>
    우편번호: <input type="text" name="address.zipcode" value="${command.address.zipcode}" />
    <form:errors path="command.address.zipcode" />
    <br/>
    주소1: <input type="text" name="address.address1" value="${command.address.address1}" />
    <form:errors path="command.address.address1" />
    <br/>
    주소2: <input type="text" name="address.address2" value="${command.address.address2}" />
    <form:errors path="command.address.address2" />
    <br/>
    <input type="submit" />
</form>
</body>
</html>

              article
                  newArticleForm.jsp (2.예제)
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>게시글 쓰기</title>
</head>
<body>
게시글 쓰기 입력 폼:
<form method="post">
    <input type="hidden" name="parentId" value="0" />
    제목: <input type="text" name="title" /><br/>
    내용: <textarea name="content"></textarea><br/>
    <input type="submit" />
</form>
</body>
</html>

                  newArticleSubmitted.jsp (2.예제)
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!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=UTF-8">
<title>게시글 쓰기</title>
</head>
<body>
게시글 등록됨:
<br/>
제목: ${command.title}
</body>
</html>

              cookie
                  made.jsp (4.예제 @CookieValue)
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>쿠키</title>
</head>
<body>
쿠키 생성함
</body>
</html>

                  view.jsp (4.예제 @CookieValue)
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>쿠키</title>
</head>
<body>
쿠키 확인
</body>
</html>

              error (에러체크)
                  exception.jsp
<%@ page language="java" contentType="text/html; charset=EUC-KR"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>예외 발생</title>
</head>
<body>
요청을 처리하는 도중에 예외가 발생하였습니다:
${exception.message}
<%
    Throwable e = (Throwable) request.getAttribute("exception");
    e.printStackTrace();
%>
</body>
</html>

                  mathException.jsp
<%@ page language="java" contentType="text/html; charset=EUC-KR"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>예외 발생</title>
</head>
<body>
연산 과정에서 예외가 발생하였습니다.
</body>
</html>

                  nullException.jsp
<%@ page language="java" contentType="text/html; charset=EUC-KR"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>예외 발생</title>
</head>
<body>
요청을 처리하는 과정에서 예외(null)가 발생하였습니다.
</body>
</html>

              game
                  character
                           info.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!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=UTF-8">
<title>호출 테스트</title>
</head>
<body>
[info] 호출 가능
</body>
</html>

                  info.jsp (8.예제)
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!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=UTF-8">
<title>호출 테스트</title>
</head>
<body>
[info] 호출 가능
</body>
</html>

                   ist.jsp (8.예제)
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!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=UTF-8">
<title>호출 테스트</title>
</head>
<body>
[list]호출 가능
</body>
</html>

              header
                  pass.jsp (5.예제 @RequestHeader)
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!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=UTF-8">
<title>헤더 검사 통과</title>
</head>
<body>
헤더 검사 통과
</body>
</html>
           
              math
                  result.jsp (11.예제 예외페이지)
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!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=UTF-8">
<title>연산 성공</title>
</head>
<body>
연산 성공
</body>
</html>

              report
                  submitReportForm.jsp (10.예제 파일업로드)
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<!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=UTF-8">
<title>리포트 등록 폼</title>
</head>
<body>
<spring:hasBindErrors name="report"/>
<form action="submitReport.do" method="post" enctype="multipart/form-data">
<p>
    <label for="subject">제목</label>
    <input type="text" id="subject" name="subject" value="${report.subject}">
    <form:errors path="report.subject"/>
</p>
<p>
    <label for="reportFile">리포트파일</label>
    <input type="file" id="reportFile" name="reportFile">
    <form:errors path="report.reportFile"/>
</p>
<p>
    <input type="submit" vlaue="리포트전송">
<p>
</body>
</html>

                  submittedReport.jsp (10.예제 파일업로드)
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!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=UTF-8">
<title>리포트 등록 완료</title>
</head>
<body>
리포트 '${report.subject}'를 동록했습니다.
</body>
</html>      

              search
                  external.jsp (3.예제 @RequestParam)
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>외부 검색</title>
</head>
<body>
외부 검색
</body>
</html>

                  game.jsp (6.예제)
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!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=UTF-8">
<title>게임 검색결과</title>
</head>
<body>
인기 키워드 : <c:forEach var="popualrQuery" items="${popularQueryList}">${popularQuery}></c:forEach>
<form action="game.do">
<select name="type">
    <c:forEach var="searchType" items="${searchTypeList}">
        <option value="${serchType.code}"<c:if test="${command.type == searchType.code}">selected</c:if>>${searchType.text}</option>
    </c:forEach>
</select>
<input type="text" name="query" value="${command.query}"/>
<input type="submit" value="검색"/>
</form>
검색결과 : ${searchResult}
</body>
</html>

                  internal.jsp (3.예제 @RequestParam)  
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>내부 검색</title>
</head>
<body>
내부 검색
</body>
</html>

                  main.jsp (6.예제)
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!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=UTF-8">
<title>게임 검색 메인</title>
</head>
<body>
인기 키워드 : <c:forEach var="popualrQuery" items="${popularQueryList}">${popualrQuery}></c:forEach>
<form action="game.do">
<select name="type">
    <c:forEach var="searchType" items="${searchTypeList}">
        <option value="${serchType.code}">${searchType.text}</option>
    </c:forEach>
</select>
<input type="text" name="query" value=""/>
<input type="submit" value="검색"/>
</form>
</body>  
</html>

              hello.jsp (1.예제)
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!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=UTF-8">
<title>인사</title>
</head>
<body>
인사말 :<strong>${greeting}</strong>
</body>
</html>

          dispatcher-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <context:annotation-config/>
   
    <!-- 기본설정 -->
    <bean id="helloController" class="madvirus.spring.chap06.controller.HelloController"/>
   
    <!-- 데이터를 전송하여 자바빈에 담기 -->
    <!-- <bean id="newArticleController" class="madvirus.spring.chap06.controller.NewArticleController" p:articleService-ref="articleService" /> -->
    <bean id="newArticleController" class="madvirus.spring.chap06.controller.NewArticleController"/>
   
    <bean id="articleService" class="madvirus.spring.chap06.service.ArticleService" />
   
    <!-- 파라미터로 전송된 데이터 처리 -->
    <bean id="searchController" class="madvirus.spring.chap06.controller.SearchController"/>
   
    <!-- @CookieValue 어노테이션을 이용한 쿠키 매핑 -->
    <bean id="cookieController" class="madvirus.spring.chap06.controller.CookieController"/>
   
    <!-- @RequestHeader 어노테이션을 이용한 쿠키 매핑 -->
    <bean class="madvirus.spring.chap06.controller.HeaderController"/>
       
    <!-- 뷰에 모델 데이터 전달하기 -->
    <bean class="madvirus.spring.chap06.controller.GameSearchController"/>
    <bean id="searchService" class="madvirus.spring.chap06.service.SearchService"/>
   
    <!-- 커멘드 객체 초기화 -->
    <bean class="madvirus.spring.chap06.controller.CreateAccountController"/>
   
    <!-- 요청 URI 매칭  -->
    <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
        <property name="alwaysUseFullPath" value="true"/>
    </bean>   
    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
        <property name="alwaysUseFullPath" value="true"/>
    </bean>
    <bean class="madvirus.spring.chap06.controller.GameInfoController"/>
   
    <!-- @PathVariable 어노테이션을 이용한 URI 템플릿 -->
    <bean class="madvirus.spring.chap06.controller.CharacterInfoController"></bean>
   
    <!-- 파일 업로드 -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="maxUploadSize" value="104857600"/>
        <property name="defaultEncoding" value="UTF-8"/>
    </bean>
    <bean class="madvirus.spring.chap06.controller.SubmitReportController"/>
   
    <!-- 예외처리 -->
    <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        <property name="exceptionMappings">
            <props>
                <prop key="java.lang.ArithmeticException">
                    error/mathException
                </prop>
                <prop key="java.lang.Exception">
                    error/exception
                </prop>
            </props>
        </property>
    </bean>   
    <bean class="madvirus.spring.chap06.controller.ArithmeticOperatorController"/>
   
    <!-- View 글로벌 설정  -->
    <bean id="ViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/view/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
   
    <!-- 리소스 번들 지정 -->
    <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
        <property name="basenames">
            <list>
                <value>messages.validation</value>
            </list>
        </property>
    </bean>
   
</beans>

          web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
 
 <!-- 기본 설정 --> <!-- DispatcherServlet -->
  <servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>*.do</url-pattern>
    <url-pattern>/game/*</url-pattern>
  </servlet-mapping>
  <!-- 캐릭터 인코딩 -->
  <filter>
    <filter-name>encodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>encodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

index.jsp (메인 링크페이지)
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!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=UTF-8">
<title>예제 요청 URL</title>
</head>
<body>
<a href="http://localhost:8080/chap06/hello.do">HelloController</a><br/>
<a href="http://localhost:8080/chap06/article/newArticle.do">NewArticleController</a><br/>
<a href="http://localhost:8080/chap06/search/internal.do?query=spring">SearchController - 1</a><br/>
<a href="http://localhost:8080/chap06/search/external.do">SearchController - 2</a><br/>
<a href="http://localhost:8080/chap06/cookie/make.do">쿠키 생성</a><br/>
<a href="http://localhost:8080/chap06/cookie/view.do">쿠키값 읽기</a><br/>
<a href="http://localhost:8080/chap06/header/check.do">헤더정보 읽기</a><br/>
<a href="http://localhost:8080/chap06/search/main.do">GameSearchController</a><br/>
<a href="http://localhost:8080/chap06/account/create.do">CreateAccountController</a><br/>
<a href="http://localhost:8080/chap06/game/info.do">GameInfoController -1</a><br/>
<a href="http://localhost:8080/chap06/game/list.do">GameInfoController -2</a><br/>
<a href="http://localhost:8080/chap06/game/users/dragon/characters/1">CharacterInfoController</a><br/>
<a href="http://localhost:8080/chap06/report/submitReport.do">파일업로드 SubmitReportController</a><br/>
<a href="http://localhost:8080/chap06/math/divide.do?op1=3&op2=0">예외발생</a><br/>
<a href="http://localhost:8080/chap06/math/divide.do?op1=4&op2=2">연산성공</a><br/>
</body>      
</html>                                                                

=================================결과값====================================

1.예제

2.예제


3.예제 @RequestParam



4.예제 @CookieValue

5.예제 @RequestHeader

6.예제 @ModelAttribute 검색


7.예제 : Validator인터페이스를 이용한 폼 값 검증


8.예제 :



9.예제 restful서비스

10.예제 파일업로드
파일없이 쿼리전송시

11예제. 예외페이지


'스프링3.0' 카테고리의 다른 글

Spring3.0 DB  (0) 2012.05.14
Spring3.0 View error filedown  (0) 2012.05.14
Spring 3.0 AOP  (0) 2012.05.14
Spring3.0 DI 3  (0) 2012.05.14
스프링 3.0 @ 어노테이션 기반 설정  (0) 2012.05.14
Posted by 사라링

Spring 3.0 AOP

2012. 5. 14. 19:10


05. 스프링 AOP




AOP(Aspect Oriented Programming)
 - 문제를 바라보는 관점을 기준으로 프로그래밍하는 기법
 - 문제를 해결하기 위한 핵심 관심 사항과 전체에 적용되는 공통 관심 사항을 기준으로 프로그래밍 함으로써 공통 모듈을 여러 코드에 쉽게 적용

공통관심사항 (cross-cutting concern)
어플리케이션에서 로깅과 같은 기본적인 기능에서부터 트랙잭션이나 보안과 같은 기능에 이르기까지 어플리케이션 전반에걸쳐 적용되는 공통기능이

핵심로직을 핵심 관심 사항(core concern) 이라고 표현.




* AOP용어 *



Advice    : 언제 공통 관심 기능을 핵심 로직에 적용할지를 정의
Joinpoint : Advice를 적용 가능한 지점을 의미 (메서드호출, 필드값 변경 등)
Pointcut  :  Joinpoint의 부분집합(그룹화)  실제로 Advice가 Joinpoint  적용된 스프링 정규표현식이나 AspectJ의 문법을 이용하여 Pointcut을 정의 할 수있다.
Weaving  : Advice를 핵심 로직 코드에 적용하는것
Aspect   :  공통관심사항


세가지 Weaving 방식

 - 컴파일 시에  Weaving 하기
 - 클래스 로딩시에 Weaving 하기
 - 런타임 시에 Weaving 하기


스프링에서의 AOP
스프링은 자체적으로 프록시 기반의 AOP를 지원한다 따라서 스프링 AOP는 메서드호출 Joinpoint만을 지원하고 필드값변경같은 Joinpoint를 사용하기 위해서는 AspectJ와 같이 풍부한 기능을 지원하느 AOP 도구를 사용

스프링은 세가지 방식으로 AOP구현
 - XML 스키마 기반의 POJO클래스를 이용한 AOP 구현
 - AspectJ 5/6에서 정의한 @Aspect 어노테이션 기반의 AOP구현
 - 스프링 API를 이용한 AOP 구현 (많이사용하지는 않음)


Advice    : 언제 공통 관심 기능을 핵심 로직에 적용할지를 정의

Advice 정의 관련태그
<aop:before>            : 메서드 실행전에 적용되는 Advice를 정의
<aop:after-returning> : 메서드가 정상적으로 실행된 후에 적용되는 Advice를 정의
<aop:throwing>         : 예외를 발생시킬 때 적용되는 Advice를 정의 (catch와 비슷)
<aop:after>              : 예외 여부와 상관없는 Advice를 정의한다 (finally 블록봐 비슷)
<aop:around>           : 메서드 호출 이전, 이후, 예외 발생 등 모든 시점에서 적용 가능한 Advice를 정의한다.

public class ProfilingAdvice {
    public Object trace(ProceedingJoinPoint joinPoint) throws Throwable{

전처리
        String signatureString = joinPoint.getSignature().toShortString();
        System.out.println(signatureString + "시작");
        long start = System.currentTimeMillis();

       
        try{
            Object result = joinPoint.proceed();
            return result;
        }finally{

후처리
            long finish = System.currentTimeMillis();
            System.out.println(signatureString + "종료");
            System.out.println(signatureString + "실행 시간 : " + (finish - start) + "ms");

        }
    }
}

XML스키마를 이용한 AOP 설정

<aop:config> : AOP 설정 정보임을 나타낸다.
<aop:aspect> : Aspect를 설정한다.
<aop:pointcut> : Pointcut을 설정 한다.
<aop:around> : Around Advice를 설정한다. 이외에도 다양한 Advice를 설정




Aspect   :  공통관심사항
@Aspect 어노테이션을 이용해서 Aspect 클래스를 구현한다 .이때 Aspect 클래스는 Advice를 구현한 메서드와 Pointcut을 포함한다.








Pointcut  :  Joinpoint의 부분집합(그룹화)  실제로 Advice가 Joinpoint  적용된 스프링 정규표현식이나 AspectJ의 문법을 이용하여 Pointcut을 정의 할 수있다.



Joinpoint : Advice를 적용 가능한 지점을 의미 (메서드호출, 필드값 변경 등)
Weaving  : Advice를 핵심 로직 코드에 적용하는것


AspectJ의 Pointcut 표현식 P181




===============================프로젝트===================================
예제.
src/
madvirus.spring.chap05.aop.annot
      ProfilingAspect (어노테이션)

madvirus.spring.chap05.aop.pojo
      Main (POJO)
      ProfilingAdvice (POJO)

madvirus.spring.chap05.board
      Article ()

madvirus.spring.chap05.board.dao
      ArticleDao (interface)
      MySQLArticleDao ()

madvirus.spring.chap05.board.service
      WriteArticleService (interface)
      WriteArticleServiceImpl ()

madvirus.spring.chap05.member
      Member ()

madvirus.spring.chap05.member.service
      MemberService (interface)
      MemberServiceImpl ()
      UpdateInfo ()

applicationContext.xml (POJO)
applicationContext02.xml (어노테이션)


==================================코드======================================
예제.
src/
madvirus.spring.chap05.aop.annot
      Main02(어노테이션)
package madvirus.spring.chap05.aop.annot;

import madvirus.spring.chap05.board.Article;
import madvirus.spring.chap05.board.service.WriteArticleService;
import madvirus.spring.chap05.member.Member;
import madvirus.spring.chap05.member.service.MemberService;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main02 {
    public static void main(String[] args){
        String[] configLocations = new String[] {"applicationContext02.xml" };
        ApplicationContext context = new ClassPathXmlApplicationContext(configLocations);
       
        WriteArticleService articaleService = (WriteArticleService)context.getBean("writeArticleService");
       
        articaleService.write(new Article());
    }
}

      ProfilingAspect (어노테이션)
package madvirus.spring.chap05.aop.annot;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class ProfilingAspect {

    @Pointcut("execution(public * madvirus.spring.chap05.board..*(..))")
    private void profileTarget(){}

    @Around("profileTarget()")
    public Object trace(ProceedingJoinPoint joinPoint)throws Throwable{
       
        String signatureString = joinPoint.getSignature().toShortString();
        System.out.println(signatureString + "시작");
        long start = System.currentTimeMillis();
       
        try{
            Object result =joinPoint.proceed();
            return result;
        }finally{
           
            long finish = System.currentTimeMillis();
            System.out.println(signatureString + "종료");
            System.out.println(signatureString + "실행시간 : "+(finish-start)+"ms");               
        }
    }
}


madvirus.spring.chap05.aop.pojo
      Main (POJO)
package madvirus.spring.chap05.aop.pojo;

import madvirus.spring.chap05.board.Article;
import madvirus.spring.chap05.board.service.WriteArticleService;
import madvirus.spring.chap05.member.Member;
import madvirus.spring.chap05.member.service.MemberService;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
    public static void main(String[] args){
        String[] configLocations = new String[] {"applicationContext.xml" };
        ApplicationContext context = new ClassPathXmlApplicationContext(configLocations);
       
        WriteArticleService articaleService = (WriteArticleService)context.getBean("writeArticleService");
       
        articaleService.write(new Article());
       
        MemberService memberService = (MemberService)context.getBean("memberService");
        memberService.regist(new Member());
    }
}

      ProfilingAdvice (POJO)
package madvirus.spring.chap05.aop.pojo;

import org.aspectj.lang.ProceedingJoinPoint;

public class ProfilingAdvice {
    public Object trace(ProceedingJoinPoint joinPoint) throws Throwable{
        String signatureString = joinPoint.getSignature().toShortString();
        System.out.println(signatureString + "시작");
        long start = System.currentTimeMillis();
       
        try{
            Object result = joinPoint.proceed();
            return result;
        }finally{
            long finish = System.currentTimeMillis();
            System.out.println(signatureString + "종료");
            System.out.println(signatureString + "실행 시간 : " + (finish - start) + "ms");
        }
    }
}


madvirus.spring.chap05.board
      Article ()
package madvirus.spring.chap05.board;

import madvirus.spring.chap05.board.dao.ArticleDao;

import org.springframework.beans.factory.annotation.Configurable;

public class Article {

    private int id;
    private ArticleDao articleDao;

    public Article() {
    }

    public Article(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }

    public void increaseReadCount() {
        articleDao.updateReadCount(id, 1);
    }

    public void setArticleDao(ArticleDao articleDao) {
        this.articleDao = articleDao;
    }
}


madvirus.spring.chap05.board.dao
      ArticleDao (interface)
package madvirus.spring.chap05.board.dao;

import madvirus.spring.chap05.board.Article;

public interface ArticleDao {

    void insert(Article article);

    void updateReadCount(int id, int i);
}

      MySQLArticleDao ()
package madvirus.spring.chap05.board.dao;

import madvirus.spring.chap05.board.Article;

public class MySQLArticleDao implements ArticleDao {

    @Override
    public void insert(Article article) {
        System.out.println("MySQLArticleDao.insert() 실행");
    }

    @Override
    public void updateReadCount(int articleId, int inc) {
        System.out.println("MySQLArticleDao.updateReadCount() 실행");
    }
}


madvirus.spring.chap05.board.service
      WriteArticleService (interface)
package madvirus.spring.chap05.board.service;

import madvirus.spring.chap05.board.Article;

public interface WriteArticleService {

    void write(Article article);
}

      WriteArticleServiceImpl ()
package madvirus.spring.chap05.board.service;

import madvirus.spring.chap05.board.Article;
import madvirus.spring.chap05.board.dao.ArticleDao;

public class WriteArticleServiceImpl implements WriteArticleService {

    private ArticleDao articleDao;

    public WriteArticleServiceImpl() {
    }
   
    public WriteArticleServiceImpl(ArticleDao articleDao) {
        this.articleDao = articleDao;
    }

    //실제적으로 출력될 메서드
    @Override
    public void write(Article article) {
        System.out.println("WriteArticleServiceImpl.write() 메서드 실행");
        articleDao.insert(article);
    }
}


madvirus.spring.chap05.member
      Member ()
package madvirus.spring.chap05.member;

public class Member {

}


madvirus.spring.chap05.member.service
      MemberService (interface)
package madvirus.spring.chap05.member.service;

import madvirus.spring.chap05.member.Member;

public interface MemberService {
   
    void regist(Member member);
   
    boolean update(String memberId,UpdateInfo info);
}

      MemberServiceImpl ()
package madvirus.spring.chap05.member.service;

import madvirus.spring.chap05.member.Member;

public class MemberServiceImpl implements MemberService {

    @Override
    public void regist(Member member) {
        System.out.println("MemberServiceImpl.regist() 메서드 실행");
    }

    @Override
    public boolean update(String memberId, UpdateInfo info) {
        System.out.println("MemberServiceImpl.update() 메서드 실행");
        return true;
    }
}

      UpdateInfo ()
package madvirus.spring.chap05.member.service;

public class UpdateInfo {

}


applicationContext.xml (POJO)
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans  
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd">


    <!-- Advice 클래스를 빈으로 등록 -->
    <bean id="preformanceTraceAdvice" class="madvirus.spring.chap05.aop.pojo.ProfilingAdvice"/>
   
    <!-- Aspect 설정 : Advice를 어떤 Pointcut에 적용할 지 설정 -->
    <aop:config>
        <aop:aspect id="traceAspect1" ref="preformanceTraceAdvice">
            <!-- 광범위하게 적용 : madvirus.spring.chap05.board 안에있는  모든 메소드에 적용 -->
            <aop:pointcut id="publicMethod" expression="execution(public * madvirus.spring.chap05.board..*(..))" />
            <aop:around pointcut-ref="publicMethod" method="trace"/>       
        </aop:aspect>   
       
        <aop:aspect id="traceAspect2" ref="preformanceTraceAdvice">
            <!-- 광범위하게 적용 : madvirus.spring.chap05.board 안에있는  모든 메소드에 적용 -->
            <aop:around pointcut="execution(public * madvirus.spring.chap05.member..*(..))" method="trace"/>       
        </aop:aspect>   
    </aop:config>
   
    <bean id="writeArticleService" class="madvirus.spring.chap05.board.service.WriteArticleServiceImpl">
        <constructor-arg>
            <ref bean="articleDao"/>
        </constructor-arg>
    </bean>   
   
    <bean id="articleDao" class="madvirus.spring.chap05.board.dao.MySQLArticleDao" />
   
    <bean id="memberService" class="madvirus.spring.chap05.member.service.MemberServiceImpl"/>
   
</beans>

applicationContext02.xml (어노테이션)
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans  
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <aop:aspectj-autoproxy/>

    <!-- Advice 클래스를 빈으로 등록 -->
    <bean id="preformanceTraceAspect" class="madvirus.spring.chap05.aop.annot.ProfilingAspect"/>
   
    <bean id="writeArticleService" class="madvirus.spring.chap05.board.service.WriteArticleServiceImpl">
        <constructor-arg>
            <ref bean="articleDao"/>
        </constructor-arg>
    </bean>   
   
    <bean id="articleDao" class="madvirus.spring.chap05.board.dao.MySQLArticleDao" />
   
</beans>


==================================결과값=====================================

1. (POJO)

2. (POJO)

3 (어노테이션)


'스프링3.0' 카테고리의 다른 글

Spring3.0 View error filedown  (0) 2012.05.14
Spring3.0 MVC 웹요청 처리  (0) 2012.05.14
Spring3.0 DI 3  (0) 2012.05.14
스프링 3.0 @ 어노테이션 기반 설정  (0) 2012.05.14
Spring3.0 message&event  (1) 2012.05.14
Posted by 사라링

Spring3.0 DI 3

2012. 5. 14. 19:10


==================================이론======================================

*의존관계 자동 설정

private Board board
          (Type) (Name)

byName : 프로퍼티의 이름과 같은 이름을 갖는 빈 객체를 설정한다.
byType : 프로퍼티의 타입과 같은 타입을 갖는 빈 객체를 설정한다.
constructor : 생성자 파라미터 타입과 같은 타입을 갖는 빈 객체를 생성자에 전달한다.
autodetect : constructor 방식을 먼저 적용하고, byType 방식을 적용하여 의존 객체를 설정한다.

<beans default-autowire="byName"> : 하위 태그 모두영향
   <bean autowire="byName"/> : 태그에 autowire 속성값지정
</beans>



*프로퍼티 타입을 이용한 의존관계 자동설정

1. 프로퍼티 이름을 이용한 의존 관계 자동 설정    

    <!-- 프로 퍼티  이름을 이용한 의존 관계 자동 설정-->
    <bean name="writeArticleService" class="madvirus.spring.chap02.WriteArticleServiceImpl" autowire="byName"/>
    <bean name="articleDao" class="madvirus.spring.chap02.MySQLArticleDao"/>  

    WriteArticleServiceImpl 클래스가 이름이 articleDao인 프로퍼티를 갖고 있다면, 이름이 articleDao 빈 객체가 프로퍼티의 값으로 전달된다.


2. 프로퍼티 타입을 이용한 의존관계 자동설정

    동일한 타입의 빈 객체가 두 개 이상 존재하게 되면 스프링은 어떤 빈 객체를 사용해야 할 지 알 수 없기 때문에 예외를 발생 시기키게 된다.
    이는 byType 방식을 이용할 경우, 프로퍼티 타입과 동일한 타입의 빈 객체를 오직 한개만 설정할 수 있다는 것을 의미며, 동일한 타입의 빈객체를 다수
    설정해야하는 경우 byType을 사용할수 없다.

    <!-- 프로퍼티 타입을 이용한 의존 관계 자동 설정  -->
    <bean name="writeArticleService2" class="madvirus.spring.chap02.WriteArticleServiceImpl" autowire="byType"/>
    <bean name="mysqlArticleDao" class="madvirus.spring.chap02.MySQLArticleDao"/>
    //<bean name="orcleArticleDao" class="madvirus.spring.chap02.MySQLArticleDao"/> 동일타입 빈객체가 존재하면 예외발생  


3. 생성자 파라미터 타입을 이용한 의존 관계 자동설정

    <!-- 생성자 파라미터 타입을 이용한 의존 관계 자동설정  -->
    <bean name="writeArticleService" class="madvirus.spring.chap02.WriteArticleServiceImpl" autowire="constructor"/>
    <bean name="mysqlArticleDao" class="madvirus.spring.chap02.MySQLArticleDao"/>

    이 경우  WriteArticleServiceImpl(ArticleDao articleDao) 생성자의 첫 번째 파라미터에 ArticleDao타입인 mysqlArticleDao 빈 객체가 전달된다.


4. 생성자 프로퍼티 타입을 이용한 자동설정

    <!-- 생성자 및 프로퍼티 타입을 이용한 자동설정  -->
    <bean name="writeArticleService" class="madvirus.spring.chap02.WriteArticleServiceImpl" autowire="autodetect"/>
    <bean name="mysqlArticleDao" class="madvirus.spring.chap02.MySQLArticleDao"/>

autodetect 방식은 constructor 방식을 먼저 적용하거, constructor 방식을 적용할 수 없는 경우 byType 방식을 적용하여 의존 객체를 설정해 준다.
autodetect 방식은 constructor 방식과 byType 방식을 사용하므로, 동일한 타입의 빈 객체를 2개 이상 정의할 수 없다는 단점을 그대로 갖는다.


5. 자동설정과 직접 설정의 혼합

경우에 따라서는 프로퍼티 중 일부는 자동 설정을 하지 않고 직접적으로 명시하고 싶을 때가 있을 것이다. 이런경우에는 자동 설정과 함께 <property>태그를 이용하여 해당 프로퍼티의 값을 직접 설정해 주면 된다.
    <bean name="writeArticleService" class="madvirus.spring.chap02.WriteArticleServiceImpl" autowire="byName">
        <property name="eventListener" ref="emailAdaptor" />
    </bean> 

특정 프로퍼티의 값이 자동 설정에 의해 초기화 되지 않도록 하려면, <null>태그를 이용하여 프로퍼티의 값을 null로 설정할 수도 있다.

    <bean name="writeArticleService" class="madvirus.spring.chap02.WriteArticleServiceImpl" autowire="byName">
        <property name="eventListener"><null/><</property>
    </bean> 

* 의존 관계를 자동으로 알맞게 설정해 주는 기능은 스프링 설정 파일의 크기를 줄여 주므로, 분명 유요한 기능임에 틀림없다.
  하지만 설정파일만으로 빈객체 간의 의존 관계를 파악하기 힘들다는 단점이있다. - 규모가 커지면 디버깅이 어렵게된다.
  가급적 빈객체 사이의 의존 관계를 모두 명시해준다.


* 부모 빈을 통한 설정 재사용 P88

빈 정보를 설정하다 보면 여러 빈태그의 설정 정보가 중복되는 경우가 있다.
중복되는 빈은 이름만 다를 뿐 나머지 설정은 대부분 동일한 것.
중복되는 설정을 갖는 빈이 다수 존재할 경우, 중복되는 설정 정보를 담고있는 부모 빈을 정의 한뒤 , 부모 빈 정보를 재사용 하도록 설정할 수 있다.

    <!-- 부모빈을 통한 설정 재사용 -->
    <bean id="commonMonitor" class="madvirus.spring.chap02.SystemMonitor" abstract="true">
        <property name="periodTime" value="10"></property>
        <property name="sender" ref="smsSender"></property>
    </bean>
    <bean id="doorMonitor" parent="commonMonitor" />
    <bean id="lobbyMonitor" parent="commonMonitor" />
    <bean id="roomMonitor" parent="commonMonitor">
        <property name="periodTime" value="20"></property>
    </bean>
    <bean id="smsSender" class="madvirus.spring.chap02.SmsSender"/>

<bean abstract="true">   abstract 속성값을 true로 지정하게 되면 스프링 컨테이너는 해당 빈 객체를 생성하지 않는다. 

자식 빈에서는 parent속성을 사용하여 클래스 및 프로퍼티 설정 정보를 물려 받을 부모 빈을 설정하면 된다.
위 코드의 경우 doorMonitor, lobbyMonitor, roomMonitor 빈이 모두 commonMonitor 빈의 설정 정보를 사용하도록 설정하고 있다.
따라서, 이 세 빈은 모두 class 속성의 값으로 madvirus.spring.chap02.SystemMonitor를 사용한다.

parent 속성을 이용하여 물려 받은 설정 정보 중에서 변경하고 싶은 값이 있다면 추가로 입력해주면 된다.
예를 들어, commonMonitor의 periodTime 프로퍼티의 값은 10인데, 다른 값을 사용하고 싶다면
위 코드에서 roomMonitor 빈 객체처럼 사용할 프로퍼티 값을 입력해주면 된다.
프로퍼티 뿐만 아니라 클래스도 새롭게 지정할 수 있다.


*빈객체범위 총 5개

singleton : 스프링 컨테이너에 한개의 빈 객체만 존재한다(기본값)
prototype : 빈을 사요할 때 마다 객체를 생성한다.

request : HTTP 요청 마다 빈 객체를 생성한다. WebApplicationContext에서만 적용 가능하다.
session : HTTP  세션 마다 빈 객체를 생성한다. WebApplicationContext에서만  적용 가능하다.
global-session : 글로벌 HTTP 세션에 대해빈 객체를 생성한다. 포틀릿을 지원하는 컨텍스트에 대해서만 적용 가능하다.

<bean id="workerBean" class="madvirus.spring.chap02.Worker" scope="singleton">
   .......................
</bean>


*서로 다른 범위 빈에 대한 의존 처리 P91

<bean id="workerBean" class="madvirus.spring.chap02.Worker" scope="prototype">
    <!-- <aop:scoped-proxy /> : id="workerBean"이 싱글턴을 사용할경우 싱글턴으로 인정하기때문에  프로토탑입으로 인정시키기위해 사용 -->
    <aop:scoped-proxy />
</bean>


*외부 설정 프로퍼티

방법1:

    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
           <list>
            <value>classpath:config/jdbc.properties</value>
            <value>classpath:config/jdbc2.properties</value> // 한개이상의 프로퍼티 파일을 지정하려면 <list> 태그를 이용  교제P102
           </list>
        </property>
    </bean>

방법2:

    xmlns:context="http://www.springframework.org/schema/context"
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd"
    beans에 등록후

    <context:property-placeholder location="classpath:config/jdbc.properties, classpath:config/jdbc2.properties"/>
                                                                                                       // 한개이상의 프로퍼티 파일을 지정하려면 , 로 구분

PropertyPlaceholderConfigurer 사용시 주의사항

PropertyPlaceholderConfigurer를 두번 설정하면안된다!!!! 위와같이 하나의 PropertyPlaceholderConfigurer에서 여러파일을 등록해서 사용
PropertyPlaceholderConfigurer를 나누면 예외발생



* 컨테이너 간 계층

BeanFactory 나 ApplicationContext는 컨테이너 간 자식- 부모의 계층 구조를 가질 수 있다.
컨테이너 간 계층 구조를 구성하면, 자식 컨테이너부모 컨테이너정의된 빈 객체에 접근할 수 있다.
반면에 부모 컨테이너에서자식 컨테이너정의된 빈객체에 접근할 수 없다.


 <!-- parent.xml -->
<bean id="smsSender" class="madvirus.spring.chap02.SmsSender"/>

<!-- child.xml -->
<bean id="monitor" class="madvirus.spring.chap02.SystemMonitor" p:periodTime="10" p:sender-ref="smsSender"/>
<bean id="smsSender" class="madvirus.spring.chap02.SmsSender"/>   



==================================프로젝트======================================
예제.
config
      jdbc.properties (외부 설정 프로퍼티)

madvirus.spring.chap02
     Article (객체형식을 지정할 용도)
     ArticleDao (인터페이스 insert메소드)
     Command (인터페이스 execute메소드)
     CommandFactory (인터페이스 createCommand 메소드)
     CommandFactoryImpl (CommandFactory를 구현 createCommand메소드 구현)
     DataSourceFactory (외부 설정 프로퍼티)
     Executor(서로 다른 범위 빈에 대한 의존 처리)
     Main05 (프로퍼티 이름을 이용한 의존 관계 자동 설정)
     Main06 (프로퍼티 타입을 이용한 의존관계 자동설정)
     Main07 (부모빈을 통한 설정 재사용)
     Main08 (서로 다른 범위 빈에 대한 의존 처리)
     Main09 (외부 설정 프로퍼티)
     MySQLArticleDao (ArticleDao 구현 insert메소드 구현)
     PerformanceMonitor (콜렉션 타입 프로퍼티 설정 - List타입과 배열)
     Processor (getCommandFactory메서드를 통해 CommandFactory를 객체생성 createCommand(commandName)
                      로 Command객체를 생성 execute메서드실행)
     SmsSender (객체형식을 지정할 용도)
     SomeCommand (Command 를 구현  execute메서드 구현)
     SystemMonitor (XML네임스페이스 출력부분)
     Worker (서로 다른 범위 빈에 대한 의존 처리)
     WorkUnit (서로 다른 범위 빈에 대한 의존 처리)
     WriteArticleService (인터페이스 write메소드)
     WriteArticleServiceImpl (WriteArticleService를 구현한 write메소드 구현)
applicationContext03.xml (외부 설정 프로퍼티)
applicationContext2.xml (DI(Dependency Injection 처리): 객체의 외부에서 두개의 의존성있는 객체의 관계를 형성)


==================================코드======================================

예제.
config
      jdbc.properties (외부 설정 프로퍼티)
jdbc.driver=oracle.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:@localhost:1521:orcl
jdbc.username=hr
jdbc.password=hr

madvirus.spring.chap02
     Article (객체형식을 지정할 용도)
package madvirus.spring.chap02;

public class Article {

}

     ArticleDao (인터페이스 insert메소드)
package madvirus.spring.chap02;

public interface ArticleDao {
    void insert(Article article);
}

     Command (인터페이스 execute메소드)
package madvirus.spring.chap02;

public interface Command {   
    void execute();
}

     CommandFactory (인터페이스 createCommand 메소드)
package madvirus.spring.chap02;

public interface CommandFactory {

    Command createCommand(String commandName);
}

     CommandFactoryImpl (CommandFactory를 구현 createCommand메소드 구현)
package madvirus.spring.chap02;

public class CommandFactoryImpl implements CommandFactory{

    @Override
    public Command createCommand(String commandName) {
        if(commandName.equals("some")){
            return new SomeCommand();
        }
        return null;
    }
}

     DataSourceFactory (외부 설정 프로퍼티)
package madvirus.spring.chap02;

public class DataSourceFactory {

    private String jdbcDriver;
    private String jdbcUrl;
    private String username;
    private String password;
   
    public void setJdbcDriver(String jdbcDriver) {
        this.jdbcDriver = jdbcDriver;
    }
    public void setJdbcUrl(String jdbcUrl) {
        this.jdbcUrl = jdbcUrl;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public void setPassword(String password) {
        this.password = password;
    }
   
    @Override
    public String toString() {
        return "DataSourceFactory [jdbcDriver=" + jdbcDriver + ", jdbcUrl="
                + jdbcUrl + ", username=" + username + ", password=" + password
                + "]";
    }   
}


     Executor(서로 다른 범위 빈에 대한 의존 처리)
package madvirus.spring.chap02;

public class Executor {

    private Worker worker;
   
    public void addUnit(WorkUnit work){
        worker.work(work);
    }
   
    public void setWorker(Worker worker){
        this.worker = worker;
    }
}

     Main05 (프로퍼티 이름을 이용한 의존 관계 자동 설정)
package madvirus.spring.chap02;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main05 {
    public static void main(String[] args){
        String[] configLocations = new String[] {"applicationContext2.xml" };
        ApplicationContext context = new ClassPathXmlApplicationContext(configLocations);
       
        //프로퍼티 이름을 이용한 의존 관계 자동 설정
        WriteArticleService articleService = (WriteArticleService)context.getBean("writeArticleService");
       
        articleService.write(new Article());
    }
}

     Main06 (프로퍼티 타입을 이용한 의존관계 자동설정)
package madvirus.spring.chap02;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main06 {
    public static void main(String[] args){
        String[] configLocations = new String[] {"applicationContext2.xml"};
        ApplicationContext context =new ClassPathXmlApplicationContext(configLocations);
       
        //프로퍼티 타입을 이용한 의존관계 자동설정
        WriteArticleService articleService= (WriteArticleService)context.getBean("writeArticleService2");
       
        articleService.write(new Article());
    }
}   

     Main07 (부모빈을 통한 설정 재사용)
package madvirus.spring.chap02;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main07 {
    public static void main(String[] args){
        String[] configLocations = new String[] {"applicationContext2.xml" };
        ApplicationContext context = new ClassPathXmlApplicationContext(configLocations);
       
        //부모 빈을 통한 설정 재사용
        SystemMonitor articleService = (SystemMonitor)context.getBean("doorMonitor");
        System.out.println(articleService);
        SystemMonitor articleService02 = (SystemMonitor)context.getBean("lobbyMonitor");
        System.out.println(articleService02);
        SystemMonitor articleService03 = (SystemMonitor)context.getBean("roomMonitor");
        System.out.println(articleService03);
       
    }
}

     Main08 (서로 다른 범위 빈에 대한 의존 처리)
package madvirus.spring.chap02;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main08 {
    public static void main(String[] args){
        String[] configLocations = new String[] {"applicationContext2.xml" };
        ApplicationContext context = new ClassPathXmlApplicationContext(configLocations);
       
        //서로 다른 범위 빈에 대한 의존 처리
        Executor executor = context.getBean("executor",Executor.class);
        executor.addUnit(new WorkUnit());
        executor.addUnit(new WorkUnit());
        executor.addUnit(new WorkUnit());
       
        Worker worker = context.getBean("workerBean", Worker.class);
        worker.work(new WorkUnit());
        worker.work(new WorkUnit());
    }   
}

     Main9 (외부 설정 프로퍼티)
package madvirus.spring.chap02;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main09 {
    public static void main(String[] args){
        String[] configLocations = new String[] {"applicationContext03.xml" };
        ApplicationContext context = new ClassPathXmlApplicationContext(configLocations);
       
        DataSourceFactory dataSourceFactory = context.getBean("dataSourceFactory",DataSourceFactory.class);
       
        System.out.println(dataSourceFactory.toString());
    }
}


     MySQLArticleDao (ArticleDao 를 구현 insert메소드 구현)
package madvirus.spring.chap02;

public class MySQLArticleDao implements ArticleDao{
   
    @Override
    public void insert(Article article){
        System.out.println("MySQLArticleDao.insert()실행");
    }
}


     PerformanceMonitor (콜렉션 타입 프로퍼티 설정 - List타입과 배열)
package madvirus.spring.chap02;

import java.util.List;

public class PerformanceMonitor {
   
    private List<Double> deviations;
   
    public void setDeviations(List<Double> deviations){
        this.deviations = deviations;
    }

    @Override
    public String toString() {
        return "PerformanceMonitor [deviations=" + deviations + "]";
    }
}

     Processor (getCommandFactory메서드를 통해 CommandFactory를 객체생성 createCommand(commandName)
                      로 Command객체를 생성 execute메서드실행)
package madvirus.spring.chap02;

public class Processor {

    public void process(String commandName){
        CommandFactory factory = getCommandFactory();
        Command command = factory.createCommand(commandName);
        command.execute();
    }
   
    protected CommandFactory getCommandFactory(){
        return null;
    }
}

     SmsSender (객체형식을 지정할 용도)
package madvirus.spring.chap02;

public class SmsSender {
}

     SomeCommand (Command 를 구현  execute메서드 구현)
package madvirus.spring.chap02;

public class SomeCommand implements Command{

    @Override
    public void execute() {
        System.out.println("SomeCommand executed.");
    }   
}

     SystemMonitor (XML네임스페이스 출력부분)
package madvirus.spring.chap02;

public class SystemMonitor {
   
    private long periodTime;
    private SmsSender sender;
   
   
    public void setPeriodTime(long periodTime) {
        this.periodTime = periodTime;
    }
    public void setSender(SmsSender sender) {
        this.sender = sender;
    }
   
    @Override
    public String toString() {
        return "SystemMonitor [periodTime=" + periodTime + ", sender=" + sender
                + "]";
    }
}

     Worker (서로 다른 범위 빈에 대한 의존 처리)
package madvirus.spring.chap02;

public class Worker {
   
    public void work(WorkUnit unit){
        System.out.println(toString()+" work " + unit);
    }
}

     WorkUnit (서로 다른 범위 빈에 대한 의존 처리)
package madvirus.spring.chap02;

public class WorkUnit {

}

     WriteArticleService (인터페이스 write메소드)
package madvirus.spring.chap02;

public interface WriteArticleService {
    void write(Article article);
}

     WriteArticleServiceImpl (WriteArticleService를 구현한 write메소드 구현)
package madvirus.spring.chap02;

public class WriteArticleServiceImpl implements WriteArticleService{

    private ArticleDao articleDao;
   
    //의존 관계 설정 방식: 프로퍼티
    public void setArticleDao(ArticleDao articleDao){
        this.articleDao = articleDao;
    }   
   
    @Override
    public void write(Article article) {       
        System.out.println("WriteArticleServiceImpl.write() 메서드 실행");
        articleDao.insert(article);
    }   
}

applicationContext03.xml (외부 설정 프로퍼티)
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans  
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd">

<!--    
    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <value>classpath:config/jdbc.properties</value>
        </property>
    </bean>
-->
   
    <context:property-placeholder location="classpath:config/jdbc.properties"/>
   
    <bean id="dataSourceFactory" class="madvirus.spring.chap02.DataSourceFactory">
        <property name="jdbcDriver" value="${jdbc.driver}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>       
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>       
    </bean>   
</beans>

applicationContext2.xml (DI(Dependency Injection 처리): 객체의 외부에서 두개의 의존성있는 객체의 관계를 형성)
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans  
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <!-- 프로 퍼티  이름을 이용한 의존 관계 자동 설정-->
    <bean name="writeArticleService" class="madvirus.spring.chap02.WriteArticleServiceImpl" autowire="byName"/>

    <bean name="articleDao" class="madvirus.spring.chap02.MySQLArticleDao"/>
   
    <!-- 프로퍼티 타입을 이용한 의존 관계 자동 설정  -->
    <bean name="writeArticleService2" class="madvirus.spring.chap02.WriteArticleServiceImpl" autowire="byType"/>
   
    <bean name="mysqlArticleDao" class="madvirus.spring.chap02.MySQLArticleDao"/>
   
    <!-- 부모빈을 통한 설정 재사용 -->
    <bean id="commonMonitor" class="madvirus.spring.chap02.SystemMonitor" abstract="true">
        <property name="periodTime" value="10"></property>
        <property name="sender" ref="smsSender"></property>
    </bean>
    <bean id="doorMonitor" parent="commonMonitor" />
    <bean id="lobbyMonitor" parent="commonMonitor" />
    <bean id="roomMonitor" parent="commonMonitor">
        <property name="periodTime" value="20"></property>
    </bean>
    <bean id="smsSender" class="madvirus.spring.chap02.SmsSender"/>
   
    <!-- 서로 다른 범위 빈에 대한 의존 처리  -->
    <bean id="workerBean" class="madvirus.spring.chap02.Worker" scope="prototype">
    <!-- <aop:scoped-proxy /> :id="workerBean"이 싱글턴을 사용할경우 싱글턴으로 인정하기때문에  프로토탑입으로 인정시키기위해 사용 -->
        <aop:scoped-proxy />
    </bean>
   
    <bean id="executor" class="madvirus.spring.chap02.Executor">
        <property name="worker" ref="workerBean"/>
    </bean>       
   
</beans>

==================================결과값=====================================

1.프로퍼티 이름을 이용한 의존 관계 자동 설정

   



2.프로퍼티 타입을 이용한 의존관계 자동설정

   



3. 부모빈을 통한 설정 재사용

   



4. 서로 다른 범위 빈에 대한 의존 처리


    <aop:scoped-proxy /> 처리

    

     <aop:scoped-proxy /> 빼면 같아짐 Worker가 싱글턴이기 때문

   

5. 외부 설정 프로퍼티

    


'스프링3.0' 카테고리의 다른 글

Spring3.0 MVC 웹요청 처리  (0) 2012.05.14
Spring 3.0 AOP  (0) 2012.05.14
스프링 3.0 @ 어노테이션 기반 설정  (0) 2012.05.14
Spring3.0 message&event  (1) 2012.05.14
Spring3.0 Di 2  (0) 2012.05.14
Posted by 사라링


04장. 어노테이션 기반 설정



어노테이션 쉽게 명시하기

http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd

<!--RequiredAnnotationBeanPostProcessor @Required 사용시
         AutowiredAnnotationBeanPostProcessor @Autowired 사용시
         CommonAnnotationBeanPostProcessor @Resource, @PoastConstruct, @PreDestroy 사용시
         ConfigurationClassPostProcessor @Configuration 사용시     
         context를 명시하면 context태그 하나로 사용가능     
        <context:annotation-config/> -->



==================================이론======================================

1.1 @Required 어노테이션을 이용한 필수 프로퍼티 검사

@Required : 필수 프로퍼티를 명시하여 값을 넘겨오는것을 강요 안넘겨오면 에러                    
                     number 프로퍼티를 설정하지 않을 경우 예외 발생


Camera
   import org.springframework.beans.factory.annotation.Required;

 //@Required : 필수요소를 체크해줌 : 스프링에서만 사용할수있다.
    @Required
    public void setNumber(int number){
        this.number = number;
    }

applicationContext.xml
    <!-- @Required 어노테이션 사용시 필수적으로 설정 -->
    <bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/>
     <!-- RequiredAnnotationBeanPostProcessor 대신 context를 명시하면 context태그를 사용가능
            <context:annotation-config/> -->
   
    <bean id="camera1" class="madvirus.spring.chap04.homecontrol.Camera">
        <!--
            number 프로퍼티에 @Required 어노테이션 적용
            number 프로퍼티를 설정하지 않을 경우 예외 발생
         -->
         <property name="number" value="1" />
    </bean>

1.2 @Autowired 어노테이션을 이용한 자동 설정

@Autowired : 타입을 이용하여 의존하는 객체를 삽입해준다. 생성자, 필드,메서드 세곳에 적용이 가능하다.
  프로퍼티 설정 메서드에 @Autowired 적용하면  어노테이션 타입을 이용한 프로퍼티 자동 설정 기능을 제공한다.
   
@Required 와 마찬가지로 @Autowired기본적으로  값을 강요하는데 필수여부를 조정해줄수있다.
@Autowired(required=false) 기본값은 true이다

    <!-- @Autowired 어노테이션 사용시 필수적으로 설정 -->
    <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
    <bean id="monitor" class="madvirus.spring.chap04.homecontrol.SystemMonitor"/>
    <bean id="sender" class="madvirus.spring.chap04.homecontrol.SmsSender"/>

@Autowired 어노테이션은 타입을 기반으로하기 때문에 자동 설정할 타입이 두개 이상 존재할 경우 예외를 발생 시킨다.
그래서 @Qualifier 어노테이션을 이용한 자동 설정 제한 을 이용한다.

@Qualifier
로 레코드를 지정   
    <!-- @Qualifier 어노테이션을 이용한 자동 설정 제한 -->
    <bean id="systemMonitor" class="madvirus.spring.chap04.homecontrol.SystemMonitor2"/>
    <bean id="recorder" class="madvirus.spring.chap04.homecontrol.Recorder">
        <qualifier value="main"/>
    </bean>   


1.3 @Resource 어노테이션을 프로퍼티 설정

어플리케이션에서 필요로 하는 자원을 자동 연결할때 사용된다.
의존하는 빈 객체를 전달할 때 사용한다.
@Resource 어노테이션을 사용 하려면 name 속성에 자동으로 연결할 빈 객체의 이름을 입력 하면된다.

동일한 객체타입인데 객체주소가 다른 여러객체가 들어올때 사용하면 GOOD!!


<!-- @Resource 어노테이션 사용시 필수적으로 설정 -->
<!-- 스프링에서의 singleton id 하나당 객체한개 -->
<bean id="homeController" class="madvirus.spring.chap04.homecontrol.HomeController"/>
<bean id="camera2" class="madvirus.spring.chap04.homecontrol.Camera" p:number="2"/>
<bean id="camera3" class="madvirus.spring.chap04.homecontrol.Camera" p:number="3"/>
<bean id="camera4" class="madvirus.spring.chap04.homecontrol.Camera" p:number="4"/>


1.4 @PostConstruct 어노테이션및 @PreDestory어노테이션과 라이플 사이클

라이프 사이클(생명주기) 초기화 및 제거 과정을 제공한다.
@PostConstruct는 의존하는 객체를 설정한 이후에 초기화 작업을 수행할 메서드에 적용된다.
@PreDestroy는 컨테이너에서 객체를 제거하기 전에 호출될 메서드에 적용된다.
스프링 설정 파일에서 init-method 속성과  destroy-method 속성성을 이용하여 명시한 메서드와 동일한 시점에 실행된다.

*사용후 재사용가능하게 메모리정리를안함
ApplicationContext context = new ClassPathXmlApplicationContext(configLocations);
       
* 작업이끝나고 메모리정리까지함
AbstractApplicationContext context = new ClassPathXmlApplicationContext(configLocations);

        @PostConstruct
        public void init(){
            System.out.println("init 메소드 동작");
        }
       
        @PreDestroy
        public void close(){
            System.out.println("close 메소드 동작");
        }



2.1 어노테이션을 이용한 자동스캔

@Component, @Service, @Controller 는 클래스 선언부분에 붙게된다.

@Component 어노테이션은 클래스에 적용했다면

//스프링이 클래스를 검색할 패키지를 지정.
<context:component-scan base-package="madvirus.spring.chap04.homecontrol"/>
*@Component  어노테이션 적용된 클래스를 검색하여 빈으로 등록하게된다.

<context:annotation-config/>와같이<context:component-scan/>  태그를 쓰면
RequiredAnnotationBeanPostProcessor @Required 사용시
AutowiredAnnotationBeanPostProcessor @Autowired 사용시
CommonAnnotationBeanPostProcessor @Resource, @PoastConstruct, @PreDestroy 사용시
ConfigurationClassPostProcessor @Configuration 사용시    
같은 어노테이션이 함께 적용된다.

* 명시적으로 설정해야하는부분이 많아서 오토스캔만 사용하는경우는 극히적다. 적당히 썩어서 사용

3.1 @Configuration 어노테이션과 @Bean 어노테이션을 이용한 코드 기반 설정
스프링3.0에 새로생김

@Configuration 과 @Bean 을 이용해서 스프링 컨텐이너에 새로운 빈 객체를 제공할 수 있다.

@Configuration
public class SpringConfig{

     @Bean // XML 빈정의 설정시 해당 메소드 이름을 사용한다.
     //@Bean(name="smsAlarmDevice") //메서드 이름이 아닌 다른이름을 사용하고 싶다면 name 속성을 사용
     //@Bean(autowire = Autowire.BY_NAME) 
     //Autowire.BY_NAME:이름을 이용해서 자동연관처리, Autowire.BY_TYPE:타입을 이용하여 자동연관처리, Autowire.NO:자동연관처리 안함
     public AlarmDevice alarmDevice(){
            return new SmsAlarmDevice();
     }
}

@Configuration 적용된 클래스를 설정정보로 이용하는 방법.

@Configuration
public class MainConfig{

     public static void main(String[] args){

            ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);

            //한개이상의 @Configuration 적용 클래스로부터 ApplicationContext 를 생성하고 싶다면 @Configuration 목록을 지정
            //ApplicationContext context = new AnnotationConfigApplicationContext
         //                                                   (
ArticleServiceConfig.class,ArticleRepositoryConfig.class);

            HomeController homeController = context.getBean("homeController",HomeController .class);
            ....
     }
}

XML 설정파일에서도 @Configuration 적용된 클래스를 사용할수있다.

<bean class="org.springframework.beans.factory.annotation.ConfigurationClassPostProcessor"/>// @Configuration 사용시 
<bean class="madvirus.spring.chap04.config.SpringConfig"/> 

//<context:component-scan base-package="madvirus.spring.chap04.config.SpringConfig">

반대로 @Configuration 적용된 클래스 XML 설정파일 정보를 사용하기

@Configuration
@ImportResource("classpath:/article-repository.xml")
//두개이상사용시 배열형태로
@ImportResource({"classpath:/article-repository.xml", "
classpath:/article-datasource.xml"})
public class SpringConfig{

     @Bean
   
public AlarmDevice alarmDevice(){
            return new SmsAlarmDevice();
     }
}

@Configuration 클래스 간의 의존 설정

@Configuration
public class ArticleServiceConfig{

     @Autowired
     private ArticleRespositoryConfig respositoryConfig;

     @Bean
   
public ArticleService articleService(){
            return new ArticleServiceImpl(respositoryConfig.articleRepository());
     }
}

@Import를 이용한 @Configuration 클래스의 조합

@Configuration
@Import({"ArticleServiceConfig.class, ArticleRepositoryConfig.class"})
public class SpringConfig{

     @Bean
   
public AlarmDevice alarmDevice(){
            return new SmsAlarmDevice();
     }
}



===============================프로젝트===================================
예제.
madvirus.spring.chap04.homecontrol
      AlarmDevice (@Resource)
      Camera (@Required)
      Homecontrolloer (@Resource)
      Homecontrolloer2 (@PostConstruct,@PreDestroy)
      Main (@Required)
      Main02 (@Autowired)
      Main03 (@Autowired - @Qualifier)
      Main04 (@Resource)
      Main05 (@PostConstruct,@PreDestroy)
      Main06 (@Component )
      MessageSender (@Autowired)
      Recorder (@Autowired - @Qualifier)
      SmsSender (@Autowired)
      SystemMonitor (@Autowired)
      SystemMonitor2 (@Autowired - @Qualifier)
      Viewer (@Resource)

applicationContext.xml
applicationContext02.xml

==================================코드======================================
예제.
madvirus.spring.chap04.homecontrol
      AlarmDevice (@Resource)
package madvirus.spring.chap04.homecontrol;

public interface AlarmDevice {
   
    void alarm(String name);
}

       Camera (@Required)
package madvirus.spring.chap04.homecontrol;

import org.springframework.beans.factory.annotation.Required;

public class Camera {
   
    private int number;
   
    public Camera() {
    }

    //@Required : 필수요소를 체크해줌 : 스프링에서만 사용할수있다.
    @Required
    public void setNumber(int number){
        this.number = number;
    }

    @Override
    public String toString() {
        return "Camera [number=" + number + "]";
    }   
}

      Homecontrolloer (@Resource)
package madvirus.spring.chap04.homecontrol;

import javax.annotation.Resource;

import org.springframework.stereotype.Component;

@Component("homeController")
public class HomeController {

   
        private AlarmDevice alarmDevice;
        private Viewer viewer;

        //@Resource 프로퍼티 설정
        //결과적으론 private Camera camera1 에보관.
        @Resource(name = "camera1")
        private Camera camera1;

        @Resource(name = "camera2")
        private Camera camera2;

        @Resource(name = "camera3")
        private Camera camera3;       

        private Camera camera4;

        public void setCamera1(Camera camera1) {
            this.camera1 = camera1;
        }

        public void setCamera2(Camera camera2) {
            this.camera2 = camera2;
        }

        public void setCamera3(Camera camera3) {
            this.camera3 = camera3;
        }

        //메소드에도 명시할수있음
        @Resource(name = "camera4")
        public void setCamera4(Camera camera4) {
            this.camera4 = camera4;
        }

        @Override
        public String toString() {
            return "Homecontrolloer [camera1=" + camera1 + ", camera2="
                    + camera2 + ", camera3=" + camera3 + ", camera4=" + camera4
                    + "]";
        }       
}

      Homecontrolloer2 (@PostConstruct,@PreDestroy)
package madvirus.spring.chap04.homecontrol;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;

public class HomeController2 {

   
        private AlarmDevice alarmDevice;
        private Viewer viewer;

        //@Resource 프로퍼티 설정
        //결과적으론 private Camera camera1 에보관.
        @Resource(name = "camera1")
        private Camera camera1;

        @Resource(name = "camera2")
        private Camera camera2;

        @Resource(name = "camera3")
        private Camera camera3;       

        private Camera camera4;

        public void setCamera1(Camera camera1) {
            this.camera1 = camera1;
        }

        public void setCamera2(Camera camera2) {
            this.camera2 = camera2;
        }

        public void setCamera3(Camera camera3) {
            this.camera3 = camera3;
        }

        //메소드에도 명시할수있음
        @Resource(name = "camera4")
        public void setCamera4(Camera camera4) {
            this.camera4 = camera4;
        }

        @PostConstruct
        public void init(){
            System.out.println("init 메소드 동작");
        }
       
        @PreDestroy
        public void close(){
            System.out.println("close 메소드 동작");
        }
}

      Main (@Required)
package madvirus.spring.chap04.homecontrol;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
   
    public static void main (String[] args){
        String[] configLocations = new String[] {"applicationContext.xml"};
        ApplicationContext context = new ClassPathXmlApplicationContext(configLocations);
       
        Camera camera = context.getBean("cameara1", Camera.class);
        System.out.println(camera);
    }
}

      Main02 (@Autowired)
package madvirus.spring.chap04.homecontrol;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main02 {
   
    public static void main(String[] args){
        String[] configLocations = new String[] { "applicationContext.xml" };
        ApplicationContext context = new ClassPathXmlApplicationContext(configLocations);
       
        SystemMonitor monitor = context.getBean("monitor",SystemMonitor.class);
       
        System.out.println(monitor.getSender());
    }
}

      Main03 (@Autowired - @Qualifier)
package madvirus.spring.chap04.homecontrol;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main03 {
    public static void main(String[] args){
        String[] configLocations = new String[] { "applicationContext.xml" };
        ApplicationContext context = new ClassPathXmlApplicationContext(configLocations);
       
        SystemMonitor2 monitor = context.getBean("systemMonitor",SystemMonitor2.class);

        System.out.println(monitor.getSender());
        System.out.println(monitor.getRecorder());
    }
}

      Main04 (@Resource)
package madvirus.spring.chap04.homecontrol;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main04 {
    public static void main(String[] args){
        String[] configLocations = new String[] { "applicationContext.xml" };
        ApplicationContext context = new ClassPathXmlApplicationContext(configLocations);
       
        HomeController home = context.getBean("homeController" , HomeController.class);
       
        System.out.println(home);
    }   
}

      Main05 (@PostConstruct,@PreDestroy)
package madvirus.spring.chap04.homecontrol;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main05 {
    public static void main(String[] args){
        String[] configLocations = new String[] { "applicationContext.xml" };
        //사용후 재사용가능하게 메모리정리를안함
        //ApplicationContext context = new ClassPathXmlApplicationContext(configLocations);
       
        //작업이끝나고 메모리정리까지함
        AbstractApplicationContext context = new ClassPathXmlApplicationContext(configLocations);
       
        context.registerShutdownHook();
       
        HomeController2 home = context.getBean("homeController2" , HomeController2.class);       
    }   
}

      Main06 (@Component )
package madvirus.spring.chap04.homecontrol;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main06 {
    public static void main(String[] args){
        String[] configLocations = new String[] { "applicationContext02.xml" };
        ApplicationContext context = new ClassPathXmlApplicationContext(configLocations);
       
        HomeController home = context.getBean("homeController" , HomeController.class);
       
        System.out.println(home);
    }   
}

      MessageSender (@Autowired)
package madvirus.spring.chap04.homecontrol;

public interface MessageSender {

}

      Recorder (@Autowired - @Qualifier)
package madvirus.spring.chap04.homecontrol;

public class Recorder {

}

      SmsSender (@Autowired)
package madvirus.spring.chap04.homecontrol;

public class SmsSender implements MessageSender {
    public SmsSender (){}
   
    public SmsSender(boolean value){}
}

      SystemMonitor (@Autowired)
package madvirus.spring.chap04.homecontrol;

import org.springframework.beans.factory.annotation.Autowired;

public class SystemMonitor {

    private int periodTime;
    private MessageSender sender;
   
   
    public SystemMonitor() {}
   
    public SystemMonitor(int period) {
        this(period, null);
    }
   
    public SystemMonitor(int period, MessageSender sender) {
        this.periodTime = period;
        this.sender = sender;
    }

    public int getPeriodTime() {
        return periodTime;
    }

    public void setPeriodTime(int periodTime) {
        this.periodTime = periodTime;
    }

    public MessageSender getSender() {
        return sender;
    }
   
    @Autowired
    public void setSender(MessageSender sender) {
        this.sender = sender;
    }   
}

      SystemMonitor2 (@Autowired - @Qualifier)
package madvirus.spring.chap04.homecontrol;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

public class SystemMonitor2 {

    private MessageSender sender;

    @Autowired
    @Qualifier("main")
    private Recorder recorder;
   

    public SystemMonitor2(MessageSender sender){
        this.sender = sender;
    }
   
    public SystemMonitor2() {}

    public MessageSender getSender() {
        return sender;
    }
   
    @Autowired
    public void setSender(MessageSender sender) {
        this.sender = sender;
    }

    public Recorder getRecorder() {
        return recorder;
    }
   
    public void setRecorder(Recorder recorder) {
        this.recorder = recorder;
    }
}

      Viewer (@Resource)
package madvirus.spring.chap04.homecontrol;

public interface Viewer {

        void add (Camera camera1);
       
        void draw();
}

applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans  
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <!--RequiredAnnotationBeanPostProcessor @Required 사용시
         AutowiredAnnotationBeanPostProcessor @Autowired 사용시
         CommonAnnotationBeanPostProcessor @Resource, @PoastConstruct, @PreDestroy 사용시
         ConfigurationClassPostProcessor @Configuration 사용시    
        context를 명시하면 context태그 하나로 사용가능    
        <context:annotation-config/> -->
     
    <!-- @Required 어노테이션 사용시 필수적으로 설정 -->
    <bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/>
    <bean id="camera1" class="madvirus.spring.chap04.homecontrol.Camera">
        <!--
            number 프로퍼티에 @Required 어노테이션 적용
            number 프로퍼티를 설정하지 않을 경우 예외 발생
         -->
         <property name="number" value="1" />
    </bean>
   
    <!-- @Autowired 어노테이션 사용시 필수적으로 설정 -->
    <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
    <bean id="monitor" class="madvirus.spring.chap04.homecontrol.SystemMonitor"/>
    <bean id="sender" class="madvirus.spring.chap04.homecontrol.SmsSender"/>
   
    <!-- @Qualifier 어노테이션을 이용한 자동 설정 제한 -->
    <bean id="systemMonitor" class="madvirus.spring.chap04.homecontrol.SystemMonitor2"/>
    <bean id="recorder" class="madvirus.spring.chap04.homecontrol.Recorder">
        <qualifier value="main"/>       
    </bean>   
   
    <!-- @Resource 어노테이션 사용시 필수적으로 설정 -->
    <!-- 스프링에서의 singleton id 하나당 객체한개 -->
    <bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" />
    <bean id="homeController" class="madvirus.spring.chap04.homecontrol.HomeController"/>
    <bean id="camera2" class="madvirus.spring.chap04.homecontrol.Camera" p:number="2"/>
    <bean id="camera3" class="madvirus.spring.chap04.homecontrol.Camera" p:number="3"/>
    <bean id="camera4" class="madvirus.spring.chap04.homecontrol.Camera" p:number="4"/>
   
    <!-- @PostConstruct 어노테이션 및    @PreDestroy 어노테이션 사용 -->
    <bean id="homeController2" class="madvirus.spring.chap04.homecontrol.HomeController2"/>    
   
   
</beans>

applicationContext02.xml
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans  
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd">


    <context:component-scan base-package="madvirus.spring.chap04.homecontrol"/>
   
    <bean id="camera1" class="madvirus.spring.chap04.homecontrol.Camera" p:number="1"/>
    <bean id="camera2" class="madvirus.spring.chap04.homecontrol.Camera" p:number="2"/>
    <bean id="camera3" class="madvirus.spring.chap04.homecontrol.Camera" p:number="3"/>
    <bean id="camera4" class="madvirus.spring.chap04.homecontrol.Camera" p:number="4"/>
   
</beans>

==================================결과값=====================================

1.@Required

  @Required에 값을 안넣어주는경우.


2.@Autowired

3.@Autowired - @Qualifier


4.@Resource

5.@PostConstruct,@PreDestroy

6.@Component


'스프링3.0' 카테고리의 다른 글

Spring 3.0 AOP  (0) 2012.05.14
Spring3.0 DI 3  (0) 2012.05.14
Spring3.0 message&event  (1) 2012.05.14
Spring3.0 Di 2  (0) 2012.05.14
Spring3.0 DI AOP  (0) 2012.05.14
Posted by 사라링

Spring3.0 message&event

2012. 5. 14. 19:07

메시지 및 이벤트 처리 - 국제화


==================================이론======================================

*메시지 소스를 이용한 메시지 국제화 처리

* 프로퍼티 파일은 유니코드를 이용하여 값을 표시해 주어야 한다. (JDK에서 제공하는 native2ascii를 이용하여 유니코드 값으로 변환)

<!-- 국제화 처리를 위한 리소스 번들지정  -->
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
    <property name="basenames">
        <list>
            <value>message.greeting</value>
            <value>message.error</value>
        </list>       
    </property>
</bean>

* 빈 객체에서 메시지 이용하기

 - ApplicationContextAware 인터페이스를 구현한 뒤, setApplicationContext()메서드를 통해 전달받은 ApplicationContext의 getMessage()메서드를 이용하여 메시지 사용
 - MessageSourceAware 인터페이스 구현한 뒤, setMessageSource() 메서드를 통해 전달받은 MessageSource의 getMessage()메서드를  이용하여 메시지 사용


public interface MessageSourceAware{
    void setMessageSource(MessageSource messageSource)
}

public class LogingProcessor implements MessageSourceAware{

   private MessageSource messageSource;

   public void setMessageSource(MessageSource messageSource){
       this.messageSource = messageSource;
   }

   public void login(String username, String password){
        ...
        Object[] arg = new String[] {username};
        String failMessage = messageSource.getMessage("login.fail",args,locale);
        ...
   }
}


*스프링 컨텍스트 이벤트

ApplicationContext는 이벤트를 발생시킬수 있는 publishEvent() 메서드를 제공한다.

void publishEvent(ApplicationEvent event)

publishEvent() 메서드는 org.springframework.context.ApplicationEvent 타입의 객를 전달 받는다.

ApplicationEvent 는 추상 클래스로서 다음과 같이 생성자를 통해서 이벤트를 발생시킨 객체를 전달받는다.

public abstract class ApplicationEvent extends EventObject{
      ...
      public ApplicationEvent(Object source){
            super(source);
            this.timestamp = System.currentTimeMillis();
      }
   
      public final long getTimestamp(){
            return this.timestamp;
      }
}

ApplicationContext를 통해서 이벤트를 발생시키고 싶은 빈은 ApplicationContextAware 인터페이스를 구현한뒤 ApplicationContext가 제공하는 publishEvent()메서드를 이용해서 이벤트를 발생시키면된다.

public classs MemberService implements ApplicationContextAware{

         private ApplicationContext context;
         public void setApplicationContext(ApplicationContext context){
              this.context = context;
         }

         public void regist(Member member){
               ...
              context.publishEvent(new MemberRegistrationEvent(this, member));
          }
}

이벤트 클래스는 ApplicationEvent클래스를 상속받아 구현하면된다.

public classs MemberRegistrationEvent extends ApplicationEvent{

         private Member member;

         public void MemberRegistrationEvent (Object source, Member member){
              super(source);
              this.member= member;
         }

         public Member getMember(){
               return member;
          }
}

ApplicationContext가 발생시킨 이벤트를 처리할 클래스는 ApplicationListenner 인터페이스를 알맞게 구현해 주면 된다. ApplicationListener인터페이스는 다음과 같이 정의 되어있다.

public interface ApplicationListener<E extends ApplicationEvent> extends EventListener{
        void onApplicationEvent(E event);
}

ApplicationContext는 이벤트 발생시 ApplicationListenner 인터페이스를 구현한빈 객체의 onApplicationEvent() 메서드를 호출함으로서 이벤트를 전달한다. 아래 코드는 ApplicationListenner인터페이스를 구현한 클래스의 전형적인 구현 방식을 보여주고있다.

public classs CustomEventListener implements ApplicationListener<MemberRegistationEvent>{
     
         @Override
         public void onApplicationEvent(MemberRegistationEvent event){
              //원하는 이벤트 처리 코드 삽입
          }
}

ApplicationListenner 인터페이스를 구현한 클래스를 스프링 빈으로 등록해 주기만하면 ApplicationContext가 발생한 이벤트를 전달받아 처리할 수 있게 된다.

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans  
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
  
    <!-- 스프링 컨텍스트 이벤트 객체만들기 -->
    <bean id="customEventListener" class="madvirus.spring.chap03.CustomEventListener"/>
   
</beans>


스프링은 기본적으로 ApplicationContext와 관련된 이벤트를 발생시키고 있는데, 이들 이벤트는 다음과 같다.

org.springframework.context.event.ContextRefreshedEvent : ApplicationContext가 초기화 되거나 설정을 재로딩해서 초기화를재수행할 때 발생한다.
org.springframework.context.event.ContextClosedEvent : ApplicationContext가 종료될 때 발생한다.
org.springframework.context.event.ContextStartEvent : ApplicationContext가 시작될 때 발생한다.
org.springframework.context.event.ContextStoppedEvent : ApplicationContext가 중지될 때 발생한다.

스프링 3.0  부터는 ApplicationListenner에 제네릭이 적용되었기 때문에, 지정한 타입만 처리하는 리스너를 작성할수 있게 되었다.

스프링 2.5 버전는 instanceof 연산자로 객체를 비교했어야했다 P114에 예제있음


==================================프로젝트======================================
예제.
madvirus.spring.chap03
      CustomeventListener (스프링 컨텍스트 이벤트 객체만들기)
      LoginProcessor (클래스내의 메시지 소스를 사용)
      Main (메시지 소스를 이용한 메시지 국제화 처리)
      Main02 (메시지 소스를 이용한 메시지 국제화 처리:강제 영어설정)
      Main03 (클래스내에서 메시지 소스를 사용)
      Main04 (스프링 컨텍스트 이벤트 객체만들기)
      Member (스프링 컨텍스트 이벤트 객체만들기)
      MemberRegistartionEvent (스프링 컨텍스트 이벤트 객체만들기)
      MemberService (스프링 컨텍스트 이벤트 객체만들기)

message
      error.properties
      greeting_en.properties
      greeting_ko.properties

applicationContext.xml


==================================코드======================================

madvirus.spring.chap03
      CustomeventListener (스프링 컨텍스트 이벤트 객체만들기)
package madvirus.spring.chap03;

import org.springframework.context.ApplicationListener;

public class CustomeventListener implements ApplicationListener<MemberRegistartionEvent> {

    @Override
    //MemberRegistartionEvent 객체를 받는다.
    public void onApplicationEvent(MemberRegistartionEvent event) {
        System.out.println("회원 가입 이벤트 발생: " + event.getMember());
    }
}

      LoginProcessor (클래스내의 메시지 소스를 사용)
package madvirus.spring.chap03;

import java.util.Locale;

import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;

public class LoginProcessor  implements MessageSourceAware{

    private MessageSource messageSource;
       
    @Override
    public void setMessageSource(MessageSource messageSource) {
        this.messageSource = messageSource;
    }
   
    public void login(String username,String password){
        if(!username.equals("medvirus")){
            Object[] args = new String[] { username};
            String failMessage = messageSource.getMessage("login.fail", args, Locale.getDefault());
            throw new IllegalArgumentException(failMessage);
        }
    }
}

      Main (메시지 소스를 이용한 메시지 국제화 처리)
package madvirus.spring.chap03;

import java.util.Locale;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {

    public static void main(String[] args){
        String[] configLocations = new String[] {"applicationContext.xml"};
        ApplicationContext context = new ClassPathXmlApplicationContext(configLocations);
       
        Locale locale = Locale.getDefault();
        String greeting = context.getMessage("greeting",new Object[0], locale);
       
        System.out.println("Default Locale Greeting: "+greeting);
    }
}

      Main02 (메시지 소스를 이용한 메시지 국제화 처리:강제 영어설정)
package madvirus.spring.chap03;

import java.util.Locale;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main02 {

    public static void main(String[] args){
        String[] configLocations = new String[] {"applicationContext.xml"};
        ApplicationContext context = new ClassPathXmlApplicationContext(configLocations);
       
        Locale locale = Locale.ENGLISH;
        String greeting = context.getMessage("greeting",new Object[0], locale);
       
        System.out.println("English Locale Greeting: "+greeting);
    }
}

      Main03 (클래스내에서 메시지 소스를 사용)
package madvirus.spring.chap03;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main03 {

    public static void main(String[] args){
        String[] configLocations = new String[] {"applicationContext.xml"};
        ApplicationContext context = new ClassPathXmlApplicationContext(configLocations);
       
        LoginProcessor loginProcessor = context.getBean("loginProcessor",LoginProcessor.class);
       
        try{
            loginProcessor.login("madvirus2", "1234");
        }catch(Throwable e){
            System.out.println("예외 발생 : "+e.getMessage());
        }       
    }
}

      Main04 (스프링 컨텍스트 이벤트 객체만들기)
package madvirus.spring.chap03;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main04 {
   
    public static void main(String[] args){
        String[] configLocations = new String[] {"applicationContext.xml"};
        ApplicationContext context = new ClassPathXmlApplicationContext(configLocations);
       
        MemberService memberService = context.getBean("memberService",MemberService.class);
       
        memberService.regist(new Member("madvirus", "최범균"));
    }
}

      Member (스프링 컨텍스트 이벤트 객체만들기)
package madvirus.spring.chap03;

public class Member {
 
    private String id;
    private String name;
   
    public Member(String id, String name) {
        super();
        this.id = id;
        this.name = name;
    }

    public void setId(String id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return "Member [id=" + id + ", name=" + name + "]";
    }   
}

      MemberRegistartionEvent (스프링 컨텍스트 이벤트 객체만들기)
package madvirus.spring.chap03;

import org.springframework.context.ApplicationEvent;

public class MemberRegistartionEvent extends ApplicationEvent {

    private Member member;   

    public MemberRegistartionEvent(Object source, Member member) {
        super(source);
        this.member = member;
    }
    public Member getMember() {
        return member;
    }
}

      MemberService (스프링 컨텍스트 이벤트 객체만들기)
package madvirus.spring.chap03;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class MemberService implements ApplicationContextAware {

    private ApplicationContext applicationContext;
   
    //객체를 받을수있도록 setter를 만듬
    @Override
    public void setApplicationContext(ApplicationContext applicationContext)throws BeansException {
        this.applicationContext = applicationContext;
    }

    public void regist(Member member){
        //publishEvent 를 불러 이벤트 처리
        applicationContext.publishEvent(new MemberRegistartionEvent(this, member));
    }
}

message
      error.properties
login.fail=Member ID {0} is not matching password

      greeting_en.properties
greeting=Hello!

      greeting_ko.properties
greeting=안녕하세요!


applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans  
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <!-- 국제화 처리를 위한 리소스 번들지정  -->
    <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
        <property name="basenames">
            <list>
                <value>message.greeting</value>
                <value>message.error</value>
            </list>       
        </property>
    </bean>
   
    <!-- 빈 객체에서 메시지 이용하기 -->
    <bean id="loginProcessor" class="madvirus.spring.chap03.LoginProcessor"/>
   
    <!-- 스프링 컨텍스트 이벤트 객체만들기 -->
    <bean id="memberService" class="madvirus.spring.chap03.MemberService"/>
    <bean class="madvirus.spring.chap03.CustomeventListener"/>
   
</beans>

==================================결과값=====================================

1. Main (메시지 소스를 이용한 메시지 국제화 처리)

2. Main02 (메시지 소스를 이용한 메시지 국제화 처리) - locale 처리

3.클래스내에서 메시지 소스를 사용

4.스프링 컨텍스트 이벤트 객체만들기


'스프링3.0' 카테고리의 다른 글

Spring3.0 DI 3  (0) 2012.05.14
스프링 3.0 @ 어노테이션 기반 설정  (0) 2012.05.14
Spring3.0 Di 2  (0) 2012.05.14
Spring3.0 DI AOP  (0) 2012.05.14
스프링 3.0 강좌  (0) 2012.05.11
Posted by 사라링

Spring3.0 Di 2

2012. 5. 14. 19:06

chap01.zip chap02.zip
컨트롤+ 스페이스바 = 이클립스 단축키

==================================이론======================================

스프링 컨테이너


BeanFactory 인터페이스

  FileSystemResource        : 파일 시스템의 특정 파일로부터 정보를 읽어 온다.
  InputStreamResource       : InputStream 으로 부터 정보를 읽어온다.
  ClassPathResource          : 클래스패스(src) 에있는 자원으로부터 정보를 읽어온다.
  UrlResource                   : 특정 URL로부터 정보를 읽어온다.
  ServletContextResource    : 웹 어플리케이션의 루트 디렉터리를 기준으로 지정한 경로에 위치한 자원으로 부터 정보를 읽어온다.


ApplicationContext 인터페이스
WebApplicationContext 인터페이스
  ClassPathXmlApplicationContext    : 클래스에 위치한 XML 파일로부터 설정 정보를 로딩한다.
  FileSystemXmlApplicationContext   : 파일 시스템에 위치한 XML 파일로부터 설정 정보를 로딩한다.
  XmlWebApplicationContext            : 웹 어플리케이션에 위치한 XML 파일로 부터 설정 정보를 로딩한다.

빈(Bean)생성과 의존 관계 설정

의존관계설정

(1)생성자 방식
 



(2)프로퍼티 설정 방식

<!-- 프로퍼티 설정 방식 -->
<bean name="writeArticleService" class="madvirus.spring.chap02.WriteArticleServiceImpl">
     <property name="articleDao">
            <ref bean="mysqlArticleDao"/>           
        </property>
    </bean>
<bean name="mysqlArticleDao" class="madvirus.spring.chap02.MySQLArticleDao"/>


(3)XML 네임스페이스를 이용한 프로퍼티 설정

xmlns:p="http://www.springframework.org/schema/p

<bean id="monitor" class="madvirus.spring.chap02.SystemMonitor" p:periodTime="10" p:sender-ref="smsSender"/>
<bean id="smsSender" class="madvirus.spring.chap02.SmsSender"/>   

주의!!
p:프로퍼티이름 형식을 사용할 경우 이름이 Ref로 끝나는 프로퍼티에 대해서는 설정할 수가 없다. 따라서, 이런 경우에는 <property> 태그를 이용해서 값을 설정해주어야한다.


(4)룩업 메서드 인젝션 방식

룩업 메서드는 다음과 같은 규칙을 따라야 한다.

* 접근 수식어가 public 이나 protected 여야 한다.
* 리턴 타입이 void가 아니다.
* 인자를 갖지않는다.
* 추상 메서드여도(abstract) 된다. = 추상메서드 추상클래스여야한다.
*  final이 아니다.


(5)임의 빈 객체 전달

한번밖에 호출못한 ID가없기때문.
별로 좋은방법은 아니다.



콜렉션 타입 프로퍼티 설정

<list> : java.util.List                    : List 타입이나 배열에 값 목록을 전달할 때 사용된다.
<map>: java.util.Map                 : Map 타입에 <키,값> 목록을 전달 할 때 사용된다.
<set>: java.util.Set                     : Set 타입에 값 목록을 전달할 때 사용된다.
<properties>: java.util.Properties : Properties 타입에 <프로퍼티이름, 프로퍼티값> 목록을 전달할 때 사용된다.


(1) List 타입과 배열

<!-- List 타입 프로퍼티 설정 -->
<bean name="performanceMonitor" class="madvirus.spring.chap02.PerformanceMonitor">
   <property name="deviations">
       <list//<list value-type="java.lang.Double"> 로 리스트에 타입을 명시해도 된다.
            //제네릭표현 Double시
           <value type="java.lang.Double">0.2</value>
           <value type="java.lang.Double">0.3</value>
       </list>
   </property></bean> 


<!-- List 타입 프로퍼티 설정 -->
<bean name="performanceMonitor" class="madvirus.spring.chap02.PerformanceMonitor">
   <property name="deviations">
       <list>
            //ref 태그로 객체목록을 전달받는다.
           <ref bean="monitor"/>
         <ref bean="smsSender"/>
         <bean class="madvirus.spring.chap02.HeaderFiter"/> //임의 객체를 List에 전달할수도있다.
       </list>
   </property>

 </bean>  

<bean id="monitor" class="madvirus.spring.chap02.SystemMonitor" />
<bean id="smsSender" class="madvirus.spring.chap02.SmsSender"/>  



(2) Map 타입

Object형이기때문에 제네릭 표현이가능
key - Object
Value - Object

<bean name="handlerFactory" class="madvirus.spring.chap02.ProtocolHandlerFactory">
   <property name="handlers">
      <map>
            <entry>
               <ket><value>soap</value></key> //키값
               <ref bean="soapHandler"/>  //값
            </entry>
            <entry>
                <key><value>rest</value></key>
                <ref bean="restHandler"/>
            </entry>
            <entry>
                <key><키태그>...</키태그></key>            
                         <값태그>...</값태그>
            </entry>
      </map>
   </property>
</bean>

<ref> - 다른 스프링 빈 객체를 키로사용
<bean> - 임의 빈 객체를 생성해서 키로 사용
<value> - 래퍼타입이나 String 을 키로 사용
<list>,<map>,<props>,<set> - 콜렉션 객체를 키로 사용
<null> - null값을 키로 사용

//키와 값의 속성을 지정
<map key-type="jana.lang.Integer" value-type="java.lang.Double">



(3) Properties 타입 : 특별한 타입의 Map 으로 키와 값 모두 String 인 맵으로 보통 Properties 클래스는 환경변수나 설정정보와 같이 상황에 따라 변경되는 값을 저장하기 위한 용도로 주로 사용된다.

String으로만 처리하기때문에 제네릭안함
key - String
Value - String

<bean name="client" class="madvirus.spring.chap02.BookClient">
   <property name="config">
      <props>
            <prop key="server">192.168.1.100</prop>
            <prop key="connectionTimeout">5000</prop>
      </props>
   </property>
</bean>


(4) Set 타입

중복값을 허용하지 않는다.
중복값을 허용하지 않는 경우외에는 보통 리스트 사용을 많이함.

<property name="subset">
    <set value-type="java.lang.Integer">
         <value>10</value>
         <value>20</value>
         <value>30</value>
    </set>
</property>

<ref> - 다른 스프링 빈 객체를 키로사용
<bean> - 임의 빈 객체를 생성해서 키로 사용
<value> - 래퍼타입이나 String 을 키로 사용
<list>,<map>,<props>,<set> - 콜렉션 객체를 키로 사용
<null> - null레퍼런스를 값으로 사용

==================================프로젝트======================================
예제.
madvirus.spring.chap02
     Article (객체형식을 지정할 용도)
     ArticleDao (인터페이스 insert메소드)
     Command (인터페이스 execute메소드)
     CommandFactory (인터페이스 createCommand 메소드)
     CommandFactoryImpl (CommandFactory를 구현 createCommand메소드 구현)
     Main (기본 프로퍼티 설정)
     Main02 (XML네임스페이스를 이용한 프로퍼티 설정)
     Main03 (룩업 메서드 인젝션 방식)
     Main04 (콜렉션 타입 프로퍼티 설정 - List타입과 배열)
     MySQLArticleDao (ArticleDao 를 구현 insert메소드 구현)
     PerformanceMonitor (콜렉션 타입 프로퍼티 설정 - List타입과 배열)
     Processor (getCommandFactory메서드를 통해 CommandFactory를 객체생성 createCommand(commandName)
                      로 Command객체를 생성 execute메서드실행)
     SmsSender (객체형식을 지정할 용도)
     SomeCommand (Command 를 구현  execute메서드 구현)
     SystemMonitor (XML네임스페이스 출력부분)
     WriteArticleService (인터페이스 write메소드)
     WriteArticleServiceImpl (WriteArticleService를 구현한 write메소드 구현)
applicationContext.xml (DI(Dependency Injection 처리): 객체의 외부에서 두개의 의존성있는 객체의 관계를 형성)

==================================코드======================================
예제.
madvirus.spring.chap02
     Article (객체형식을 지정할 용도)
package madvirus.spring.chap02;

public class Article {
}

     ArticleDao (인터페이스 insert메소드)
package madvirus.spring.chap02;

public interface ArticleDao {
    void insert(Article article);
}

     Command (인터페이스 execute메소드)
package madvirus.spring.chap02;

public interface Command {   
    void execute();
}

     CommandFactory (인터페이스 createCommand 메소드)
package madvirus.spring.chap02;

public interface CommandFactory {

    Command createCommand(String commandName);
}

     CommandFactoryImpl (CommandFactory를 구현 createCommand메소드 구현)
package madvirus.spring.chap02;

public class CommandFactoryImpl implements CommandFactory{

    @Override
    public Command createCommand(String commandName) {
        if(commandName.equals("some")){
            return new SomeCommand();
        }
        return null;
    }
}

     Main (기본 프로퍼티 설정)
package madvirus.spring.chap02;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;

public class Main {
    public static void main(String[] args){
        Resource resource = new ClassPathResource("applicationContext.xml");
        BeanFactory beanFactory = new XmlBeanFactory(resource);
        //WriteArticleService articleService = (WriteArticleService)beanFactory.getBean("writeArticleService");
       
        //제네릭표현
        WriteArticleService articleService = beanFactory.getBean("writeArticleService",WriteArticleService.class);
       
        articleService.write(new Article());
    }
}

     Main02 (XML네임스페이스를 이용한 프로퍼티 설정)
package madvirus.spring.chap02;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main02 {
    public static void main(String[] args){
        String[] configLocations = new String[] {"applicationContext.xml"};
        ApplicationContext context = new ClassPathXmlApplicationContext(configLocations);
       
        //XML 네임 스페이스를 이용한 프로퍼티 설정
        SystemMonitor articleService = (SystemMonitor)context.getBean("monitor");
        System.out.println(articleService);
    }
}

     Main03 (룩업 메서드 인젝션 방식)
package madvirus.spring.chap02;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main03 {
    public static void main (String[] args){
        String[] configLocations = new String[] {"applicationContext.xml" };
        ApplicationContext context = new ClassPathXmlApplicationContext(configLocations);
       
        //룩업 메서드 인젝션 방식
        Processor processor = context.getBean("processor",Processor.class);
        processor.process("some");
    }
}

     Main04 (콜렉션 타입 프로퍼티 설정 - List타입과 배열)
package madvirus.spring.chap02;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main04 {
    public static void main(String[] args){
        String[] configLocations = new String[]{"applicationContext.xml"};   
        ApplicationContext context = new ClassPathXmlApplicationContext(configLocations);
       
        //List 타입 프로퍼티 설정
        PerformanceMonitor monitor= (PerformanceMonitor)context.getBean("performanceMonitor");
        System.out.println(monitor);
    }
}

     MySQLArticleDao (ArticleDao 를 구현 insert메소드 구현)
package madvirus.spring.chap02;

public class MySQLArticleDao implements ArticleDao{
   
    @Override
    public void insert(Article article){
        System.out.println("MySQLArticleDao.insert()실행");
    }   
}

     PerformanceMonitor (콜렉션 타입 프로퍼티 설정 - List타입과 배열)
package madvirus.spring.chap02;

import java.util.List;

public class PerformanceMonitor {
   
    private List<Double> deviations;
   
    public void setDeviations(List<Double> deviations){
        this.deviations = deviations;
    }

    @Override
    public String toString() {
        return "PerformanceMonitor [deviations=" + deviations + "]";
    }
}

     Processor (getCommandFactory메서드를 통해 CommandFactory를 객체생성 createCommand(commandName) 로 Command객체를 생성 execute메서드실행
package madvirus.spring.chap02;

public class Processor {

    public void process(String commandName){
        CommandFactory factory = getCommandFactory();
        Command command = factory.createCommand(commandName);
        command.execute();
    }
   
    protected CommandFactory getCommandFactory(){
        return null;
    }
}

     SmsSender (객체형식을 지정할 용도)
package madvirus.spring.chap02;

public class SmsSender {
}

     SomeCommand (Command 를 구현  execute메서드 구현)
package madvirus.spring.chap02;

public class SomeCommand implements Command{

    @Override
    public void execute() {
        System.out.println("SomeCommand executed.");
    }   
}

     SystemMonitor (XML네임스페이스 출력부분)
package madvirus.spring.chap02;

public class SystemMonitor {
   
    private long periodTime;
    private SmsSender sender;
   
   
    public void setPeriodTime(long periodTime) {
        this.periodTime = periodTime;
    }
    public void setSender(SmsSender sender) {
        this.sender = sender;
    }
   
    @Override
    public String toString() {
        return "SystemMonitor [periodTime=" + periodTime + ", sender=" + sender
                + "]";
    }
}

     WriteArticleService (인터페이스 write메소드)
package madvirus.spring.chap02;

public interface WriteArticleService {
    void write(Article article);
}

     WriteArticleServiceImpl (WriteArticleService를 구현한 write메소드 구현)
package madvirus.spring.chap02;

public class WriteArticleServiceImpl implements WriteArticleService{

    private ArticleDao articleDao;
   
    //의존 관계 설정 방식: 프로퍼티
    public void setArticleDao(ArticleDao articleDao){
        this.articleDao = articleDao;
    }   
   
    @Override
    public void write(Article article) {       
        System.out.println("WriteArticleServiceImpl.write() 메서드 실행");
        articleDao.insert(article);
    }   
}

applicationContext.xml (DI(Dependency Injection) 처리 : 객체의 외부에서 두개의 의존성있는 객체의 관계를 형성)
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans  
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <!-- 프로퍼티 설정 방식 -->
    <bean name="writeArticleService" class="madvirus.spring.chap02.WriteArticleServiceImpl">
        <property name="articleDao">
            <ref bean="mysqlArticleDao"/>           
        </property>
    </bean>
    <bean name="mysqlArticleDao" class="madvirus.spring.chap02.MySQLArticleDao"/>
   
    <!-- XML 네임스페이스를 이용한 프로퍼티 설정 -->
    <!-- p:periodTime p:sender  프로퍼티명  -->
    <!-- ref="smsSender" 빈객체 전달 -->
    <bean id="monitor" class="madvirus.spring.chap02.SystemMonitor" p:periodTime="10" p:sender-ref="smsSender"/>
    <bean id="smsSender" class="madvirus.spring.chap02.SmsSender"/>   
   
    <!-- 룩업 메서드 인젝션 방식 -->
    <bean id="processor" class="madvirus.spring.chap02.Processor">
        <!-- 메서드인젝션 -->
        <lookup-method name="getCommandFactory" bean="commandFactory"/>       
    </bean>
    <bean id="commandFactory" class="madvirus.spring.chap02.CommandFactoryImpl"/>   
   
    <!-- List 타입 프로퍼티 설정 -->
    <bean name="performanceMonitor" class="madvirus.spring.chap02.PerformanceMonitor">
        <property name="deviations">
            <list>
                <value type="java.lang.Double">0.2</value>
                <value type="java.lang.Double">0.3</value>
            </list>
        </property>
    </bean>
</beans>

==================================결과값=====================================
1. 프로퍼티 설정 방식



2. XML네임스페이스를 이용한 프로퍼티 설정


3. 룩업 메서드 인젝션 방식


4. 콜렉션 타입 프로퍼티 설정 - List타입과 배열


'스프링3.0' 카테고리의 다른 글

스프링 3.0 @ 어노테이션 기반 설정  (0) 2012.05.14
Spring3.0 message&event  (1) 2012.05.14
Spring3.0 DI AOP  (0) 2012.05.14
스프링 3.0 강좌  (0) 2012.05.11
스프링 3.0 동영상 강좌.  (0) 2012.05.09
Posted by 사라링

BLOG main image
.. by 사라링

카테고리

사라링님의 노트 (301)
JSP (31)
J-Query (41)
JAVA (24)
VM-WARE (0)
디자인패턴 (1)
스크랩 (0)
스트러츠 (3)
안드로이드 (11)
오라클 (45)
우분투-오라클 (1)
이클립스메뉴얼 (6)
스프링3.0 (23)
자바스크립트 (10)
HTML5.0 (17)
정보처리기사 (1)
기타(컴퓨터 관련) (1)
문제점 해결 (3)
프로젝트 (2)
AJAX (4)
하이버네이트 (3)
트러스트폼 (11)
Jeus (2)
재무관리(회계) (5)
정규식 (5)
아이바티스 (8)
취미 (2)
소프트웨어 보안 관련모음 (0)
정보보안기사 (6)
C언어 베이직 및 프로그램 (3)
보안 관련 용어 정리 (2)
넥사크로 (6)
Total :
Today : Yesterday :