레이블이 struts actionform인 게시물을 표시합니다. 모든 게시물 표시
레이블이 struts actionform인 게시물을 표시합니다. 모든 게시물 표시

2013년 10월 23일 수요일

[자바객체복사배열복사]자바배열(Java Array),배열복사/복제

[자바객체복사배열복사]자바배열(Java Array),배열복사/복제, System.arrayCopy, clone,배열복제,객체복제

 객체는 값의 할당을 원칙으로 함.
배열은 객체임. 일반적인 방법으로 복사되지 않음.
 
 
배열 복사의 두 가지 방법
 
- System.arrayCopy()메서드 이용
 
 
 
public static void arraycopy(Object src , int src_position ,
                  Object dst ,int dst_position ,int length)
Object src : 원본배열
int src_position : 원본배열의 시작위치

Object dst : 복사할 배열
int dst_position : 복사할 배열의 시작위치
int length : 복사할 개수.

- Object클래스의 clone()메서드 이용

메모리를 복사하여 Object형 객체 리턴
원래 타입으로 다운캐스팅 필요
[Clone()메서드로 객체복사 시 주의점]
Cloneable인터페이스 구현필요
배열은 이미 구현되어 쓸 구현 필요 없음
 
int[] mytarget = (int[])mydream.clone();
 
[예1]

public class ArrayTest {
   public static void main(String[] args) {
  
   int[] onjoraclejava  = new int[]{5, 4, 6, 9, 7, 9};   
      int[] target = {10, 20, 30, 40, 50, 60,70, 80};
     
      System.arraycopy(onjoraclejava, 2, target, 3, 4);
     
      for(int i=0; i<target.length; i++)
      {
         System.out.println("target["+i+"] : " + target[i]);
      }
   }
}

[결과]
 
target[0] : 10
target[1] : 20
target[2] : 30
target[3] : 6
target[4] : 9
target[5] : 7
target[6] : 9
target[7] : 80
 
[예2]
 
public class CloneTest {
   public static void main(String[] args) {
      int[] oraclejavanew  = new int[]{1, 4, 6, 9};
      int[] target = (int[])oraclejavanew.clone(); 
      for(int i=0; i<target.length; i++)
      {
         System.out.println("target["+i+"] : " + target[i]);
      }
   }
}
 
[결과]
 

target[0] : 1
target[1] : 4
target[2] : 6
target[3] : 9

2013년 10월 3일 목요일

오라클 논리적 저장 공간, 오라클의 논리적 구성, 데이터베이스 구성,테이블,테이블스페이스,블로그 익스텐트

오라클 논리적 저장 공간, 오라클의 논리적 구성, 데이터베이스 구성,테이블,테이블스페이스,블로그 익스텐트


논리적 저장영역
1. Data Block
- Oracle에서 Data를 저장하는 가장 작은 단위, 블록단위로 DataBase의 DataFile에 있는 저장영역
을 관리한다.
- Data Block의 크기는 최대한계내에는 운영체제 블록크기의 배수여야 한다.
- 구성
  Head : 블록주소와 Segment유형(Data,Index,RollBack…)등의 일반적인 블록정보를 포함
Table Directory : 해당블록에 행을 가지는 Table에대한 정보를 가진다.
Row Directory : 블록내의 실제 행에 대한 정보를 가진다.
Row Data : Table Data Or Index Data를 포함한다.
빈영역
  트랜잭션 입력항목에 사용되는 영역 :  블록내의 하나이상의 행을 Access하는
                                      Insert/Update/Delete/Select등의 명령문은
                                      블록에 하나의 트랜잭션 입력항목을 필요로 한다.
                                      대부분의 운영체제에서는 약23 Byte정도를 필
                                      요로함


2. Extents
- 저장영역할당을 위한 논리적인 단위로 연속적인 몇 개의 Data Block으로 구성된다.
- 각 Segment는 적어도 하나이상의 Extents(RollBack Segment는 2개이상)를 자지고 생성됩니다.
이러한 확장을 initial extents라고 한다.
- 일반적으로 한 Segment의 확장영역은 drop table또는 drop cluster명령으로 개체를 삭제하여
TableSpace에 반환한다.
(예외)truncate … drop storage를 이용하여 Table이나 Cluster를 Truncate시킬수 있슴
    Oracle은 주기적으로 RollBack Segment에 있는 하나이상의 Extents를 해제할수
    있다.
    DBA는 alter table table_name deallocate unused명령을 이용하여 확장영역을 해제할
    수 있다.


3. Segment
- Extents(확장영역)의 집합
A. Data Segment
- DataBase의 SnapShot과SnapShot Log를 포함한 모든 Cluster화 되지 않은 Table은 자신의
Data를 저장하기위해 단일데이터세그먼트(Single Data Segment)를 가진다. Create
Table/SnapShot/SnapShot Log명령을 사용하여 Object를 생성할때 Data Segment를
생성하며 Create Cluster명령이 실행될때 Cluster 에 대한 Data Segment를 생성한다.

B. Index Segment
- Index생성시 Segment할당된다.(Create Index…)

C. RollBack Segment
- Transaction이 RollBack되어야할 경우 트랜잭션 작동을 기록
- 각 DataBase에는 하나이상의 RollBack Segment가 있슴
- Transaction별로 변경되기전의  Data를 기록
- Transaction을 Commit할때 RollBack Segment의 정보를 해체하지만 바로 없애지는 않는다.
Transaction을 Commit 하기전에 시작된 Query에 관련된 Data의 read-consistent  view(읽기
일관성 뷰)를 생성하지위해 data가 RollBack Segment에 남아 있다.
그러한 View를 생성할 가능성이 있는한 RollBack Data를 사용할 수 있도록 Oracle은
RollBack Segment의 확장영역을 순차적으로 사용한다.
RollBack Segment의 마지막 영역이 꽉차면 첫번째 Extents로 돌아가서 RollBack Data를 기록함.
또한 장기적으로 실행되는 Transaction은 RollBack Segment에 새로운 Extents(확장영역)를
요구할수도 있슴.

D. Temp Segment
- Create Index, Select Order By, Select Distinct, Select Group By, Select Union,
Select,Minus,Select ,Intersect등의 명령은 Temp Sefment를 필요로 한다.
예를들어 Query에 Distint,Group By,Order by등이 있으면 Oralce은 두개의 Temp
Segment를 요구할수도 있다. 명령이 완료되면 Oracle은 Temp Segment를 삭제한다.

- Oracle은 사용자 Session기간 동안 필요한만큼의 Temp Segment를 생성한다.
Create User나 Alter User등의 명령에 Temporary TableSpace다음의 TableSpace에 Temp
Segment를 생성한다. 사용자가 Temp Segment를 생성하지 않으면 Default System TableSpace임

예)create user scott identified by tiger default tablespace users temporary
tablespace temp;

오라클자바커뮤니티에서 설립한 개발자교육6년차 오엔제이프로그래밍 실무교육센터
(오라클SQL,튜닝,힌트,자바프레임워크,안드로이드,아이폰,닷넷 실무개발강의)  




2013년 8월 9일 금요일

[오라클자바커뮤니티, Java Framework]객체 지향 패러다임

객체 지향 패러다임

오라클자바커뮤니티에서 설립한 오엔제이프로그래밍 실무교육센터
(오라클SQL, 튜닝, 힌트,자바프레임워크, 안드로이드, 아이폰, 닷넷 실무전문 강의)  


 
S/W개발을 기능별로 나누는 것이 아니라 객체 단위로 분리하는 것. 객체지향 기법은 data(객체)를 중심으로 system을 바라보고 이를 system 개발에 적용하겠다는 것

객체란 데이터와 그 데이터를 처리하는 여러 개의 기능들을 하나의 단위로 묶은 것으로, 외부에 블랙박스 형태로 보인다. 즉 입력과 출력 부분만이 노출이 되고 내부적인 처리 과정은 완전히 밀폐되어 있으며, 외부에서 알 필요도 없는 것

소프트웨어 공학과 프로그래밍 언어에 관한 이론 중에서 객체지향적 분석(Object-Oriented Analysis)이나 객체지향적 설계(Object-Oriented Design) 그리고 객체지향 프로그래밍 언어(Objected-Oriented Language)와 같이 객체지향에 관련된 모든 것을 통틀어 말한다

기존의 프로시저 기반의 구조적 프로그래밍(C나 Pascal과 같은 명령형 패러다임)에서는 프로그램 내에서 일어나는 모든 변화와 동작, 사건 등을 프로그래머가 직접 기술하는 형태로 프로그램을 기술했지만 객체지향 프로그래밍에서는 똑똑한 객체에게 자신이 원하는 일을 해달라는 메시지를 전달하는 형태로 프로그램을 기술한다

기존 시스템들은 절차 중심적으로 개발되어진 경우가 많아서 유지 보수 단계에서 많은 어려움을 겪고 있는 반면, 객체 지향 패러다임은 재사용성, 확장성 등의 특성을 내포하고 있어 유지 보수 단계를 용이하게 해 준다.

객체들 사이의 인터페이스를 위해 사건(또는 메시지)들을 주고받는데 기존의 방법보다 더 실행 시간을 요할 수 있다. 깊은 클래스 계층 구조가 있는 경우와 system 작동 중 객체에 대한 동적 할당과 제어시 성능에 대한 문제가 제기될 수도 있다.

객체지향 기법은 data보다는 성능을 중요시하며, 많은 계산을 요하는 system에서는 적합지 않을 수 있다. 실시간 반응을 해야하는 system의 경우 객체지향 기법을 적용하는 것이 이를 통해 얻을 수 있는 이점보다 성능 등에 대한 부담이 높아져 허용되는 한계(예: 반응시간) 를 넘을 수도 있다. 군사용 미사일 제어 system이나 병원의 환자 상태 관리 system 등이 그 예가 될 수 있다.

컴포넌트가 21세기 정보기술(IT) 산업의 지각변동을 몰고 올 새로운 패러다임으로 급부상하고 있다.

SW를 이제까지처럼 계획, 설계, 분석, 구현, 테스트하는 순차적인 개발과정으로 보는 것이 아니라 레고블록이나 자동차 부품처럼 조립하는 개념으로 간주하며 컴포넌트 SW는 레고블록을 쌓는 것처럼 일단 표준화된 프레임워크와 규칙을 기반으로 만들어진 기능별 SW를 필요한대로 조립하면 원하는 SW를 만들 수 있다. 개발이나 유지보수에도 특별한 노력이 요구되지 않으며 표준화, 규격화를 지향하기 때문에 SW 품질도 눈에 띄게 좋아진다.

현재 국내 신생업체들을 중심으로 자바 컴포넌트 기술을 이용해 상용 애플리케이션을 개발하는 사례가 늘고 있으며 특히 전사적자원관리(ERP) 시스템에서부터 개발툴, XML 솔루션, 검색엔진, 통신용 SW, 인터넷 구축툴, 언어처리 모듈, 지식관리(KM), 고객관리(CRM) 등의 분야에 이르기까지 다양한 분야에서 개발이 진행되고 있다.

컴포넌트의 특장점은 인터넷이라는 환경의 부상으로 더욱 강력한 위치를 차지하게 됐다. 인터넷은 모든 업무를 빠르게 변화시키고 있으며 표준화할 것을 요구하고 있으며 이러한 업무를 지원하는 SW 및 정보시스템도 표준에 기반해 빠른 변화를 수용해야만 하는데 이러한 요구에 가장 부합하는 것이 바로 컴포넌트 개념이다.

Object : 시스템의 관점에서 본다면 어떤 상태(state)를 나타내는 데이터의 구조와 동작을 수행하는 연산(operation)으로 이루어진 프로그램의 한 요소이다. 여기서의 연산을 객체지향에선 메소드(method)라고 한다. 이렇게 객체의 상태는 데이터에 의해 결정되고 동작은 메소드에 의해 결정된다.

Message : 홀로 존재하는 객체는 아무런 의미가 없다. 대부분의 객체는 무언가를 실행하기 위해서 다른 객체를 필요로 한다. 이러한 상호 작용은 메시지를 통해 이루어진다.

Class : 모든 객체는 반드시 클래스를 통해서만 정의될 수 있다. 클래스는 객체의 타입을 정의하는 템플릿(template)으로서, 여러 객체의 공통적인 속성(attribute)과 메소드(method)를 가지고 있는 클래스가 먼저 정의되면, 이 클래스를 통해서 다시 객체가 정의되는 것이다.한 클래스에 속하는 각각의 객체를 그 클래스의 인스턴스(instance)라고 한다.


클래스(Class)
어떤 종류의 모든 객체들에 대해 일반적으로 적용할수 있는 변수와 메소드를 정의하고 있는 설계도 또는 프로토타입 이다.
사용자 정의 자료형, 객체의 자료형
Field라는 변수와 오퍼레이션을 가하는 method 로 이루어짐
클래스의 이름은 대문자로 시작, 다음 단어의 시작은 대문자

객체(Object)
클래스의 인스턴스는 new 수식에 의해 만들어지며 이것이 객체이다.
타입이 클래스인 변수
이름은 소문자로 시작, 다음 단어의 시작은 대문자


•추상 데이타 타입(ADT;abstract data type)
–클래스를 이용하여 표현

•상속(inheritance)
–동적 바인딩(dynamic binding) cf) Static binding
–한 클래스를 확장하여 새로운 클래스를 만드는 것을 말한다. 이렇게 새로 만들어지는 클래스를 하위클래스(SubClass)라고 부른다. 그리고 원래의 클래스는 상위클래스(SuperClass)라고 부른다.
–자바의 모든 클래스는 상속의 대상이 되는 상위클래스(SuperClass)가 반드시 하나 존재한다
–프로그램의 재사용성과 확장성을 높인다.
–하위 클래스는 상속된 필드와 메쏘드 중에 private으로 선언된 것이 아닌 것에만 접근할 수 있다.



객체지향의 핵심 내용

연관(Association)
객체 또는 클래스가 다른 객체 또는 클래스와 ‘어떤 의미의’ 관계를 가질 수 있다.

집합연관(Aggregation)
순수 연관(Association)은 두 동료 클래스, 객체간의 구조적 관계
하나의 객체가 다른 객체들의 조합에 의해 만들어 짐
전체/부분 관계를 모델링 하는 경우 한 클래스는 더 큰 것을(“전체”) 대표하고 그것은 더 작은 것들(“부분”)로 이루어져 있다. Ex)회사와 부서의 관계
전체”와 “부분”의 개념적 관계(“whole-part of”)
Component는 집합체와는 별개로 독립적으로 존재 할 수 있다.(nonexclusive ownership )


복합연관(Composition)
단순한 집합연관은 전적으로 개념적이며 “전체” 와 “부분”을 구분 하는 것 이상의 어떤 것도 수행하지 않는다.
일종의 집합연관으로 전체는 강력한 소유권을 가지며  부분/전체는 동시적 일생을 산다.(“cascading delete”)
(Window : Frame, 책상 : 서랍, 책상 : 다리)
전체는 부분에 대한 책임을 진다. 바꿔 말하면 전체는 부분을 생성시키고 소멸시킨다.
“부분”은 어느 시점에 하나의 “전체”에 속한다.
Component는 집합체와는 별개로 독립적으로 존재 할 수 없다.(exclusive ownership )
전체의 다중성은 0 또는 1(0..1), 부분의 경우는  어느것이 와도 관계 없다(0..*)



상속과 Composition
상속과 컴포지션은 동전의 양면과 같이 유사하게 서로에게 관련이 있다.
상속은 마치 양파가 여러 껍질로 이루어진 것과 같이 계층화된 객체
컴포지션은 여러 재료(객체)가 한데 뭉쳐서 만들어진 죽
컴포지션은 개체들간의 'has a' 관계, 상속은 ‘is a’관계
상속과 컴포지션은 상호 배타적이지 않으며 개발자는 이 둘을 같이 사용한다.


다형성
•다형성(polymorphism)
–상속을 받은 것을 그대로 사용하지 않고 입맛에 맞게 바꾸어 줄 수 있도록 하는 것
–다형성을 위해 자바에서는 메소드 overriding 과 메소드 overloading을 제공 한다.
–상속계층 상에서 어떤 객체의 어느 메소드를 호출할 것인지를 결정하는 객체의 능력을 다형성 이라 한다.
–사인곡선을 그리는 함수가 있다고 할 때 사용자는 파라미터로 radian이나 degree값을 넣게 되지만 둘 다 처리할 수 있다. 이것은 sine(int degrees)나 sine(float Radians)와 같이 동일 이름의 함수가 다른 파라미터로 두 번 선언되었기 때문이다.


다형성(polymorphism)
Overloading : 동일한 함수의 이름 사용 가능, 같은 클래스 내에 같은 이름의 생성자나 메소드를 사용하는 행위,매개변수의 개수와 타입이 달라야 한다

Overriding : 상위 클래스에서 정의된 함수를 하위 클래스에서 재 정의, 기존 클래스의 메소드 구현 부분만 약간 변화시켜 새로운 클래스를 생성할 수 있다. 매개변수의 개수와 타입이 같아야 한다.
 
상위 클래스로부터 메소드를 상속받을 때, 서브클래스 내에 같은 이름의 메소드가 있는 경우에 Signature가 다르면 중복(overloading)이 되고 Signature가 같으면 재정의(overriding)가 된다.

Template : 타입을 인자로 하여 새로운 타입을 생성



캡슐화(encapsulation)
객체는 자신이 수행하는 모든 행동과 속성을 다른 객체와 외부 세계에는 보이지 않는다
객체 자신의 Operation을 수행하고 결과를 내놓지만 그 Operation의 동작 원리는 숨기는 것이다.
높은 모듈성과 정보은닉을 제공



추상클래스
추상클래스는 어떠한 클래스를 만들기 위해 미리 정의해 둔 클래스의 틀을 의미한다. 앞에서 작성한 Employee(직원)클래스와 직원의 하위 클래스를 예로 든다면 직원이라는 클래스는 프로그래머(Programmer), 디자이너(Designer), 프로그램팀장(ProgrammerChief)등을 만들기 위해 작성된 클래스라고 할 수 있다. 사실 직원이라는 클래스는 실제 회사의 프로그램을 개발한다고 했을 때 사용해서는 안되는 클래스라고 할 수 있다. 왜냐하면 A라는 회사에 직원 중 어느 부서에 해당되지 않고 자기 마음대로 회사를 출근하고 퇴근하는 직원은 존재하지 않을 것이기 때문이다. 하지만 Employee 라는 클래스가 존재하는 이상 일반 사용자에게 메뉴얼을 작성해 “Employee 클래스는 다른 특정직원 클래스를 만들기 위한 클래스입니다.”라고 하기 전에는 Employee의 본래의미를 모르고 Employee 의 객체를 생성하여 사용할 수 있다. 물론 이 것은 원래 개발을 한 개발자의 의도와는 상관이 없는 잘못된 사용이지만 이를 막을 수 없는 것이다. 즉 다음과 같은 소스 코딩을 막을 수 없다.
        Employee s1 = new Employee("홍길동", “12345");     
        s1.gotoTheOffice();

만약 Employee 클래스는 사용하기 보다는 다른 클래스에 상속되여 새로운 직원 클래스를 만드는 것이 바람직하다는 의미를 소스 코드에 부여한다면 개발자의 Employee 클래스 개발 의도를 사용자가 쉽게 알 수 있게 될 것이다. 이 때 사용되는 키워드가 abstract 키워드이다. 이 키워드가 클래스에 붙으면 이 클래스는 추상클래스라는 의미이다.


앞서 작성한 Emplopyee 클래스에는 없지만 이를 상속받은 모든 클래스에서 정의하고 재정의하여 사용하고 있는 startJob 이라는 메소드를 Employee에서 추상메소드로 선언하여 정의할 수 있다
       
상속의 개념으로만 본다면 이러한 추상클래스는 굳이 만들 필요가 없다. 추상클래스가 아니더라도 위와 같은 상속과 메소드의 재정의는 얼마든지 가능하기 때문이다. 하지만 수퍼타입(super type)을 이용한 다형성(Polymorphism)의 측면에서 추상클래스(Abstract Class)는 유용하게 쓰일 수 있다.
       
A라는 직원이 회사에 입사했는데 처음에는 디자인팀에 있다가 얼마 후 프로그램개발팀로 소속을 옮기게 되었다. 그러다가 경력을 쌓아 프로그램개발팀장으로 까지 진급하게 되었다. 이렇게 한 사람의 직원은 시간에 따라 때로는 상황에 따라 여러가지 모습으로, 여러가지 업무를 담당하게 된다. 바로 이런 것을 가능하도록 객체를 설계하는 것이 바로 다형성의 구현이다. 즉 실생활의 회사 직원처럼 상황과 시간에 따라 여러가지 모습을 지니는 다형성을 구현할 수 있게 되는 것이다. 모든 직원의 하위클래스들을 수퍼 타입(상위클래스)로 형변환하면 가능하다.

클래스는 필드로 기본자료형, 클래스 등이 올 수 있지만 인터페이스는 int, double 등의 기본 자료형만이 필드로 사용될 수 있다. 또한 각 필드는 반드시 초기화가 되어야 한다. 초기화가 되어야 하는 이유는 인터페이스의 필드는 암시적으로 final과 static이 설정되어 있기 때문이다.

        int maxSmall = 5  &agrave; static final int maxSmall = 5;

인터페이스는 메소드를 선언만 하고 구현하지는 않는다. 그리고 인터페이스의 모든 메소드는 접근지정이 기본적으로 public으로 설정된다. 그리고 모든 메소드는 추상메소드이다. 즉 아래의 void driveSmallCar();라는 선언은 암시적으로 설정되는 public과 abstract 키워드를 추가하면 다음과. 같이 선언되어 있는 것과 같다.

                public abstract void driveSmallCar();

인터페이스
추상메소드로 이루어진 클래스라 할 수있다.
Interface와 구현(implementation)의 분리
다중상속의 일부 기능 지원(한가지 인터페이스로 여러 구현을 실행할 수 있다)
인터페이스의 모든 메소드는 자동적으로 public abstract이다
인터페이스의 모든 변수는 자동적으로 public static final이다.
객체의 Instance를 생성할 수 없음
메소드의 구현을 갖지 않으며, 몸체부분은 세미콜론으로 대체된다.
클래스가 인터페이스를 구현하게 되면 인터페이스 내에 정의된 상수는 상속된 것 처럼 직접 사용할 수 있다.


인터페이스와 추상 클래스
추상메소드를 가지고 있고 이를 상속받거나 구현하는 클래스는 이 추상 메소드를 재정의하고 구현해야 한다는 점, 그리고 다형성을 구현하는 방법이라는 점, 메소드들이 동적으로 바인딩 된다는 점들은 비슷하다.
       
차이점
- 인터페이스는 서로 연관성이 없는 클래스들에 의해 구현될 수 있고 따라서 수평적인 구현이 가능하지만 추상클래스의 경우 단일 상속 개념 하에 수직적인 구조로 상속을 해야만 한다.

- 인터페이스에서는 메소드를 선언만 할 수 있으며 구현할 수 없다. 그리고 이 구현은 인터페이스를 구현하도록 설정된 클래스에서 가능하다. 하지만 추상클래스의 경우에는 추상 클래스 내부에서 메소드의 선언과 구현이 모두 가능하며 또한 이를 상속 받은 클래스에서도 재정의가 가능하다.

2013년 8월 8일 목요일

[Struts Shopping cart, 오라클자바커뮤니티]스트럿츠 이번에는 상품 상세보기에서 장바구니 담기를 구현해 보도록 하죠^^

이번에는 상품 상세보기에서 장바구니 담기를 구현해 보도록 하죠^^


오라클자바커뮤니티에서 설립한 오엔제이프로그래밍 실무교육센터
(오라클SQL, 튜닝, 힌트,자바프레임워크, 안드로이드, 아이폰, 닷넷 실무전문 강의)  


 

---------------------------------------------------------------
1. 상품상세보기 에서는 다음과 같이 HTML FORM 태그를 구성합니다.
---------------------------------------------------------------

<html:form action="/CartInsert">



----------------------------------------------------------------
2. CartInsert를 위한 struts-config.xml은 다음과 같습니다.
----------------------------------------------------------------

<!-- Insert ShoppingCart  -->
        <action         
            path="/CartInsert"
            type="goods.action.CartInsertAction"
            name="cartForm"                                     
        />

혹시 몰라 말씀드리는데... 스트럿츠의 <html:form>에는 html이나 jsp에서 from name을 주지않도록 되어 있는데,.,, 이는 struts-config.xml안에서 정의하기 때문이죠... html 소스 보기를 하면 자동으로 form name이 변환되어져 있는 것을 확인 할 수 있습니다.


----------------------------------------------------------------
3. CartInsertAction.java
----------------------------------------------------------------

//============================================================================
/**
  * 시스템명 : goods / 장바구니
  * 작 성 일  : 2005-05-15
  * 작 성 자  : Lee, Jong-Cheol
  * 수 정 자  :
  * 파 일 명  : goods.action.CartInsertAction
  * 버    전  : 1.0
  * 개    요  : 쇼핑카트의 물품 추가 Action
  * 이    력  : 2005-05-15 : 초기 작성
  *     
  */
//============================================================================

package goods.action;

import java.util.ArrayList;

import goods.model.Cart;

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

import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.DynaActionForm;

import oraclejava.BaseActionLogin;
import oraclejava.Constants;
import oraclejava.YLog;


/**
 * @author 이종철
 *
 * TODO To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
public class CartInsertAction extends BaseActionLogin{
    public ActionForward cartInsert(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response)
                    throws Exception {                         
       
                DynaActionForm dForm = (DynaActionForm)form;
       
                String gCode        = dForm.get("gcode").toString();
                String gName        = dForm.get("gname").toString();
                String gName2      = dForm.get("gname2").toString();
                String price        = dForm.get("price").toString();
                String cnt          = dForm.get("cnt").toString();
                String juklip_ratio = dForm.get("juklip_ratio").toString();
                String unit        = dForm.get("unit").toString();
                String image_path3  = dForm.get("image_path3").toString();
                String is_taekbae_discount  = dForm.get("is_taekbae_discount").toString();
                String is_direct    = dForm.get("is_direct").toString();
             
                Cart cart = getCart(request);
                                                                                                                     
                cart.addItem(gCode, gName, gName2, price, cnt, juklip_ratio, unit, image_path3, is_taekbae_discount);
               
                ArrayList cartList = (ArrayList)cart.getCartItems();
               
                HttpSession session = request.getSession();
                   
                session.setAttribute(Constants.CART_LIST, cartList);
               
                //장바구니 보기
                if (is_direct.equals("N")) {                                     
                    return mapping.findForward(Constants.CARTOK);
                }
                //바로 주문하기
                else {
                    return mapping.findForward(Constants.ORDERPAGE); 
                }                                                         
            }
}


Cart.java, CartItem.java는 이전 강좌를 참고 하세요~

[오라클자바커뮤니티]Struts Validator 프레임워크 소개

Struts Validator 프레임워크 소개 


오라클자바커뮤니티에서 설립한 오엔제이프로그래밍 실무교육센터
(오라클SQL, 튜닝, 힌트,자바프레임워크, 안드로이드, 아이폰, 닷넷 실무전문 강의)  


스트럿츠의 Validator 프레임워크는 특별한 검증 로직을 개발자가 프로그래밍 하지 않고 애플리케이션의 Validation Rule을 이용하여 설정 할 수 있게 해 줍니다.(사용자가 필수입력 항목에 값을 넣었는지, 값이 지정된 범위에 맞게 되어 있는지, 이메일 주소 형식이 올바른지, 우편번호 형식이 맞는지…)  마치 닷넷 프레임워크의 Validation Control과 같은 기능을 수행 합니다.  (값을 꼭 넣으세요, 나이는 0 ~99 사이 입니다, 전화번호 형식이 잘못 되었군요, E-Mail 주소 형식이 잘못 되었군요와 같은 오류를 출력 할 수 있겠죠^^)

ActionForm에서 개개 프로퍼티에 대해 분리된 검증 로직을 구현하기 위해서는 에러 발견시 수동으로 ActionErrors를 만들고 ActionErros 컬렉션에 추가하는 별도의 작업을 개발자가 해 주어야 합니다.

이러한 방식의 문제점은 애플리케이션 전체에 걸쳐 많은 검증 로직을 포함하는 각각의 ActionForm 내부에 코딩을 해야 한다는 것 입니다. 값이 꼭 입력되어야 하는 “필수입력” 이라는 것만 생각 해 보아도 이것을 개개 프로퍼티(속성) 마다 , 그리고 모든 ActionForm에 대해 기술 한다는 것은 상당한 낭비라고 생각합니다. 물론 이러한 형태는 유지 보수도 어렵게 하는 단점도 있습니다.

Validator Framework는 현재 Jakarta Comons 프로젝트의 한 부분으로 스트럿츠 메인 배포판에 포함되어 있습니다. 물론 Commons 다운로드 페이지에서도 다운 받을 수 있습니다.
(http://jakarta.apache.org/commons)

Validator Framework에는 고유한 기능들을 위한 몇 개의 패키지가 필요한데 그 중 Jakarta ORO 패지지가 가장 중요 합니다. 정규 표현식, 치환, 텍스트 분리 등의 기능을 포함하고 있습니다. 스트럿츠에서 필요로 하는 패키지는 스트럿츠의 배포판에 포함되어 있는데 commons-validator.jar와 commons-oro.jar 파일을 /WEB-INF/lib 폴더에 추가 해야 합니다. 

Validator 프레임워크는 프로그래밍이 아닌 선언을 통해 사용자의 입력 값을 검증 하는 것으로 이것은 결국 소스 외부의 어떤 검증 규칙이 있다는 것을 의미 합니다. 즉 validation-rule.xml과 validation.xml 이라는 두 개의 설정 파일을 필요로 합니다.

---------------------------------
Validator Framework에 관해
---------------------------------

- 일종의 프레임웍 컴포넌트 입니다.
- XML 파일을 통해 설정 하며, 이 파일을 통해 폼의 필드에 대한 Validation 조건을 기술 합니다.
- 날짜나 정수형과 같은 기본 데이터 타입을 위한 Validator가 제공 됩니다.
- 우편번호나 전화번호 같은 패턴 기반 검증도 가능 합니다.
- 멀티 페이지와 지역화된 검증이 지원 됩니다.
- 리소스의 최적 사용 :: JavaScript 검증 기능을 제공 하거나 서버 측의 검증을 보장 가능
- 유지보수를 한곳에서 :: 클라이언트와 서버측 검증 모두를 동일한 Configuration으로부터 생성 가능
- 확장성 :: 사용자 정의 검증은 정규 표현식이나 자바 코드를 통해 가능
- 스트럿츠와의 통합 :: 기본적으로 검증은 스트럿츠의 메시지 번들을 공유
 

--------------------------------------
Validator를 구성하는 Component
--------------------------------------

- Validator
       
기본적인 공통의 타입을 다루며 required mask, minLength, maxLength, range, native types, date, email, credit card등을 포함 합니다.

- Resource Bundle
       
        지역화된 메시지와 라벨을 제공

- XML Configuration (File)

        검증 룰에 대한 정의
       
- JSP Tag

        주어진 폼 이름과 액션 경로를 통한 JavaScript 검증을 발생 시킵니다.       

- ValidatorForm
       
자동적으로 폼빈 이름에 기반한 프로퍼티들을 검증 합니다.
(실행 시점에 ActionMapping 파라미터를 통해 validate() 메소드로 보내어진)

- ValidatorActionForm

        자동적으로 액션 경로에 기반한 프로퍼티들을 검증 합니다.
(실행 시점에 ActionMapping 파라미터를 통해 validate() 메소드로 보내어진)

2013년 8월 6일 화요일

다중 애플리케이션(Struts Multi-Application)

다중 애플리케이션(Multi-Application)


오라클자바커뮤니티에서 설립한 오엔제이프로그래밍 실무교육센터
(오라클SQL, 튜닝, 힌트,자바프레임워크, 안드로이드, 아이폰, 닷넷 실무전문 강의)   
 스트럿츠 1.1이상에서는 다중 애플리케이션 사용이 가능 합니다.

애플리케이션의 모듈이 동일한 웹애플리케이션의 일부 이지만 서로 독립적입니다.

다중 애플리케이션을 사용하는 이유는 업무를 좀 더 조직화, 세분화 할 수 있다는 장점이 있습니다.

쇼핑몰을 개발하는데 상품의 디스플레이 부분과 쇼핑카트를 구현 하는 부분을 별도의 다중 애플리케이션으로 구성 하는 것이 가능 합니다. 이렇게 하는 이유는 상호 독립적이고 수평적인 개발이 가능하도록 하기 위해서 입니다.


기본 애플리케이션이 아닌 모듈은 config/ 로 시작 합니다.

config/ 다음에 오는 부분은 애플리케이션 모듈의 접두어가 되며 프레임웍 전반을 걸쳐클라이언트의 요청을 처리하는데 사용 됩니다.

아래에 간략히 방법을 설명 하고 예제를 만들어 보도록 합니다.
(이클립스에서 톰캣 애플리테이션으로 Login이라는 프로젝트를 작성 후… 별도의 test라는 독립된 애플리케이션을 만들려고 합니다.)

1.        웹 애플리테이션의 web.xml 파일에 다중 애플리케이션을 위한 설정을 합니다.

<servlet>
          <servlet-name>action</servlet-name>
          <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
          <init-param>
                        <param-name>config</param-name>
                        <param-value>/WEB-INF/struts-config.xml</param-value>
          </init-param>
          <init-param>
                  <param-name>config/test</param-name>
                  <param-value>/WEB-INF/struts-test-config.xml</param-value>
          </init-param>
          <load-on-startup>1</load-on-startup>               
        </servlet>


2.        이번에 어떻게 모듈(애플리케이션)을 Switch하는지 알아 봅니다.

두 가지의 큰 방법이 있는데 아래와 같습니다.

-        forward를 이용하는 방법

struts-config.xml에서 test 애플리케이션으로 스위칭을 하기 위해서 forward를 이용합니다.

유심히 볼 부분은 contextRelative가 true가 되어 있다는 것이다. 이 값은 하나의 웹 애플리테이션을 사용 하는 경우에는 false(path 설정 시 기준을 애플리케이션을 기준으로)  이지만 다중 웹 애플리케이션을 사용 하기 위해서는 true(path 설정 시 기준이 context가 기준)로 설정 합니다.

즉 아래에서 test 라는 또 하나의 애플리케이션을 가리킬 때 /test/mysubmit과 같이 컨텍스트를 기준으로 경로를 사용 했습니다. (현재 톰캣 프로젝트를 하나 만들었죠^^ Login 이라는 것을…)

<struts-config>
...
<global-forwards>
<forward name="toModuleB"
contextRelative="true"
path="/test/mysubmit"
redirect="true"/>
...
</global-forwards>

</struts-config>



- org.apache.struts.actions.SwitchAction를 이용하는 방법

<action-mappings>
<action path="/toModule"
type="org.apache.struts.actions.SwitchAction"/>
...
</action-mappings>



이제 예제를 만들어 보도록 하겠습니다. 예제는 개념을 익히기 위해 최대한 간단히 작성 했습니다.


[처리흐름]

Login이라는 톰캣 프로젝트(웹애플리케이션)를 하나 만들고 별도의 독립적인 test라는 애플리케이션을 만들어 struts-config.xml과는 별도로 struts-test-config.xml을 만들어 보겠습니다. (물론 둘은 업무적으로 어떤 연관성을 가지지는 않고 있습니다. 예문에서는 단지 다중 애플리케이션을 설정하고 로딩 하는 것만 살펴 볼테니까요…)

사용자가 /Login/login.jsp를 실행 합니다.

실행 화면은 다음과 같습니다. (간단히 ID와 PASSWORD만 입력 받고 submit 버튼을 누릅니다.)

 

Submit 버튼을 누르면 이 액션을 /toTest라는 path로 넘어갑니다. 이 요청을 우선 Login 애플리케이션에서 받습니다.

<action
                path="/toTest"
                type="login2.toTest"
                validate="false" 
                name="loginForm"             
        />

위와 같이 설정이 되어 있습니다. 그래서 login2.toTest 라는 클래스가 실행을 하겠죠…

toTest.java 에서는 간단히 위에서 설명한 2번 방법대로 forward를 이용하여 test라는 애플리케이션으로 스위칭을 해 버립니다.

public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) {
                               
                //sub application인 test로 버네기 위해 forward 이용
                return (mapping.findForward("toTest"));
               
        }

위에서 return (mapping.findForward("toTest")); 부분의 처리를 위해 당연히 “toTest” 라는 forward가 있어야 겠죠^^

메인 설정 파일인 struts-config.xml에서 아래와 같이 정의하고 있습니다.

<forward name="toTest"
                contextRelative="true"
                path="/test/mysubmit.do"
                redirect="true"/>


이제 제어가 /test/mysubmit.do라는 액션으로 인해 test 라는 애플리케이션으로 넘어 가게 됩니다. 물론 위의 /test/mysubmit.do 는 struts-test-config.xml에서 정의를 하고 있습니다. 그 설정 내용은 다음과 같습니다.

<action-mappings>           
        <!-- 현재의 설정 파일은 struts-test-config.xml 이므로... path에 "/test/mysubmit" 아님을 주의! -->
        <action
                path="/mysubmit"   
                type="login2.Welcome2"   
                validate="false"                 
        />
         
    </action-mappings>


이제는 login2.Welcom2라는 클래스가 실행 되겠죠^^

그 내용은 단순히 result.jsp로 포워딩 시키는 일을 합니다.

요기까지 입니다.

그럼 이젠 전체 소스를 확인 하도록 하죠….

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


-------------------------------
/Login/test/login.jsp
-------------------------------
<%@ page pageEncoding="euc-kr" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<html>
<body>

<html:form action="/toTest" focus="id">
        <table>             
                <tr>                       
                        <th align="right">ID</th>                                             
                        <td><html:text property="id" value=""/></td>
                </tr>
                <tr>
                        <th align="right">PASSWORD</th>                                             
                        <td><html:password property="pwd" redisplay="false"/></td>
                </tr>
                <tr>                     
                        <th></th>
                        <td>
                            <html:submit/>
                            <html:reset/>                             
                        </td>
                </tr>                               
        </table>
</html:form>
</body>
</html>


-------------------------------
/WEB-INF/struts-config.xml
-------------------------------

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">
<struts-config>
     
    <!-- ========== Form Bean Definitions ================================== -->
    <form-beans>
        <form-bean name="loginForm" type="login2.LoginForm">                 
            <form-property name="pwd" type="java.lang.String" />
            <form-property name="id" type="java.lang.String" />           
        </form-bean>           
    </form-beans>
   
 
    <!-- ========== Global Forward Definitions =============================== -->
    <global-forwards>
        <forward name="toTest"
                contextRelative="true"
                path="/test/mysubmit.do"
                redirect="true"/>
    </global-forwards>
   
    <!-- ========== Action Mapping Definitions =============================== -->
    <!-- valiedate를 true라고 함으로써 LoginForm의 validate가 호출 됩니다.            -->
    <action-mappings>           
        <action
                path="/toTest"
                type="login2.toTest"
                validate="false" 
                name="loginForm"             
        />         
    </action-mappings> 
       
</struts-config>



-------------------------------
/WEB-INF/struts-test-config.xml
-------------------------------

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">
<struts-config>
   
    <!-- ========== Global Forward Definitions =============================== -->
    <global-forwards>
        <forward name="success" path="/result.jsp"/>
    </global-forwards>
   
    <action-mappings>           
        <!-- 현재의 설정 파일은 struts-test-config.xml 이므로... path에 "/test/mysubmit" 아님을 주의!  메인 애플리케이션의 foreard에 기술한 /test/mysubmit에 의해 아래의 매핑과 연결됨, 결국 login2.Welcom2가 실행됨-->
        <action
                path="/mysubmit"   
                type="login2.Welcome2"   
                validate="false"                 
        />
         
    </action-mappings>                         
</struts-config>


-------------------------------
/WEB-INF/src/login2/toTest.java
-------------------------------
package login2;

import org.apache.struts.action.Action;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;


public class toTest extends Action {       
       
        public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) {
                               
                //sub application인 test로 보내기 위해 forward 이용
                return (mapping.findForward("toTest"));
               
        }
}


-------------------------------
/WEB-INF/src/login2/Welcome2.java
-------------------------------
package login2;

import org.apache.struts.action.Action;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import login2.Constants;

public class Welcome2 extends Action {       
       
        public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) {
                               
                //성공적으로 처리 되었음, test 애플리케이션의 result.jsp로 보내버림...                return (mapping.findForward(Constants.SUCCESS));
               
        }
}




-------------------------------
/Login/test/result.jsp
-------------------------------
OK~ 

2013년 8월 5일 월요일

[자바프레임워크,자바교육,오라클자바교육]Struts ActionForm(스트럿츠 액션폼), 오엔제이프로그래밍

Struts에서 ActionForm 처리 



오라클자바커뮤니티에서 설립한 오엔제이프로그래밍 실무교육센터
(오라클SQL, 튜닝, 힌트,자바프레임워크, 안드로이드, 아이폰, 닷넷 실무전문 강의) 
 www.onjprogramming.co.kr 


ActionForm 객체는 클라이언트에서 입력한 데이터를 비즈니스 계층으로 전달하는 역할을 합니다. Struts Framework에서는 사용자의 입력 화면에서 입력한 데이터를 자동으로 모아 ActionForm 인스턴스의 setter를 이용해 설정하며 이를 통해 비즈니스 계층으로 데이터를 전달 할 수 있습니다.

여기서 한가지 주의 할 점은 ActionForm을 비즈니스 계층으로 직접 전달 하기 보다는 적절한 DTO(Data Transfer Object)를 생성하는 것이 훨씬 효율적 입니다.

스트럿츠에서는 다음과 같이 ActionForm 을 처리 합니다.

1.        Action의 매핑 정보를 확인 하고 Action이 설정 되어 있는지 확인 합니다. Action 매핑의 name 속성에 해당 하는 <form-bean > 매핑이 있는지 확인 하는 겁니다.

<!-- ========== Form Bean Definitions ================================ -->
    <form-beans>
        <form-bean name="loginForm" type="login2.LoginForm">                 
            <form-property name="pwd" type="java.lang.String" />
            <form-property name="id" type="java.lang.String" />           
        </form-bean>           
    </form-beans>



<!-- ========== Action Mapping Definitions ============================ -->
    <!--valiedate를 true라고 함으로써 LoginForm의 validate가 호출됩니다.      -->
    <action-mappings>
            <!-- loginAction에 대한 정의 -->
        <action         
                path="/LoginSubmit"
                type="login2.LoginAction"
            name="loginForm"                       
            validate="true"
            input="/login.jsp"
        />
       
        <!-- logoffAction에 대한 정의 -->
        <action         
                path="/logoff"
                type="login2.LogoffAction"
            name="logoffForm"                       
            validate="false"         
        />                     
    </action-mappings>


2.        메모리에 ActionForm 인스턴스가 있는지 확인하여 이미 만들어진 타입이 같고 scope가 적당 한 것이 있으면 재사용하고 없으면 새로 인스턴스를 생성 합니다. 새 인스턴스를 만드는 경우엔 scope 속성이 있다면 속성에 따른 scope에 저장 합니다.

3.        ActionForm의 reset 메소드를 호출 합니다.
       
        public void reset(ActionMapping mapping, HttpServletRequest request) {
                pwd = "";
                id = "";
        }

4.        ActionForm의 setter를 통해 요청 파라미터 값을 ActionForm에 입력 합니다.

public void setId(String id) {
                this.id = id;
        }
       
        public void setPwd(String pwd) {
                this.pwd = pwd;
        }

5.        validate속성이 “true”로 설정 되어 있으면 validate() 메소드를 실행 하고 에러가 있다면 에러를 반환 합니다.

public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
                ActionErrors errors = new ActionErrors();
               
                if((id == null) || (id.length()<1)) {
                        errors.add("error.id.required", new ActionError("error.id.required"));
                }
               
                if((pwd == null) || (pwd.length()<1)) {
                        errors.add("error.pwd.required", new ActionError("error.pwd.required"));
                }
               
                return errors;                       
        }


폼 데이터를 전송 하는 모든 HTML 페이지에서 ActionForm 사용해야 하는데 HTML의 폼필드의 이름과 ActionForm의 속성의 이름이 일치한다면 ActionForm을 여러 페이지에서 사용 가능 합니다.

중요한 메소드는 reset(), validate() 메소드 인데 하나씩 보도록 하죠~

reset() 메소드의 원형은 다음과 같습니다.

public void reset(ActionMapping mapping, HttpServletRequest request);

스트럿츠의 ActionForm 클래스의 위 두메소드는 기본적으로 아무 기능도 수행 하지 않으므로 ActionForm을 상속한 하위 클래스에서 필요하다면 재정의(Override) 해야 합니다.

Controller는 요청 파라미터에 있는 ActionForm의 인스턴스에 입력 하기전에 reset() 메소드를 수행 합니다. 결국 reset이라는 것은 초기화의 의미이며 폼빈의 인스턴스를 공유하는 경우엔 중요한 부분 입니다.

Controller는 요청값들이 ActionForm의 setter에 의해 설정 되면 validate가 “true”로 설정 된 경우에는 valiedate() 메소드를 호출 하는데 이 메소드에서는 사용자의 입력 값에 대한 validation check를 수행 합니다. 오류가 있다면 ActionError 객체에 담아서 리턴 합니다. ActionForm에서의 validate()는 비즈니스 로직 이라기 보다는 입력 값의 단순한 검사 정도로 보시면 되며 실제 들어온 값에 대한 논리적인 타탕성등 여러가지 검사를 하기 위해서는 별도의 비즈니스 로직을 만들어 처리해야 합니다.

validate() 메소드의 원형은 다음과 같습니다.

public ActionErrors validate(ActionMapping mapping, HttpServletRequest request);