Struts 1 - 스트럿츠 1의 다양한 Action Class 들 part 3

Published on: 2009. 6. 30. 00:05 by louis.dev


1.SwitchAction




Context 내에 여러 개의 모듈이 있을 때  현재 작업중인 모듈에서 다른 모듈로 전환하고 새로운 모듈내의 포워드 하는 일을 수행한다. struts1 의 가장 핵심적인 Action중의 하나라고 할 수 있다.

[struts1의 Groupping 과 Module]
struts1에서의 그룹핑을 사용해서 하는 방법이 가장 쉬운 방법 중에 하나다 . web.xml에
-----------------------------------------------------------------------------------------------
<init-param>
  <param-name>config</param-name>  
  <param-value>
   /WEB-INF/struts-config.xml,
   /WEB-INF/struts-config-dispatch.xml,
   /WEB-INF/struts-config-mapping.xml,
   /WEB-INF/struts-config-lookup.xml  
  </param-value>  
 </init-param>
-----------------------------------------------------------------------------------------------
다음과 같은 방법으로 xml 파일을 모아두면 그룹핑 방식으로 struts를 구성하는 것이다. 또한 module로 나누는 방식은
web.xml에서
-----------------------------------------------------------------------------------------------
<init-param>
   <param-name>config</param-name>
   <param-value>/WEB-INF/config/struts-config.xml</param-value>
  </init-param>
  <init-param>
   <param-name>config/dispatchModule</param-name>
   <param-value>/WEB-INF/config/struts-dispatchModule.xml</param-value>
  </init-param>
  <init-param>
   <param-name>config/lookupModule</param-name>
   <param-value>/WEB-INF/config/struts-lookupModule.xml</param-value>
  </init-param>
  <init-param>
   <param-name>config/mappingModule</param-name>
   <param-value>/WEB-INF/config/struts-mappingModule.xml</param-value>
  </init-param>
  <init-param>
   <param-name>config/uploadModule</param-name>
   <param-value>/WEB-INF/config/struts-uploadModule.xml</param-value>
  </init-param>
-----------------------------------------------------------------------------------------------
이런식으로 한번에 선언하지 않고 나누어 선언 할 수 있다.

특징:
그룹핑을 하면 각 설정xml파일안의 이름들이 같으면 안되나 module별로 나누면 같은 이름이 있어도 된다.
즉 그룹핑 에서는 <action path="">의 path명이 모든 xml 파일이 같으면 안되나 module방식에서는 같아도 상관이 없다.

작성방법
1)web.xml 에 module별로 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">
  <display-name>struts1</display-name>
 
  <servlet>
   <servlet-name>action</servlet-name> <!-- 아무이름이나 하면 된다. -->
   <servlet-class>  <!-- 클래스 지정 -->
    org.apache.struts.action.ActionServlet
   </servlet-class>
   

 <!-- switch Action module types -->
  <init-param>
   <param-name>config</param-name>
   <param-value>/WEB-INF/config/struts-config.xml</param-value>
  </init-param>
  <init-param>
   <param-name>config/dispatchModule</param-name>
   <param-value>/WEB-INF/config/struts-dispatchModule.xml</param-value>
  </init-param>
  <init-param>
   <param-name>config/lookupModule</param-name>
   <param-value>/WEB-INF/config/struts-lookupModule.xml</param-value>
  </init-param>
  <init-param>
   <param-name>config/mappingModule</param-name>
   <param-value>/WEB-INF/config/struts-mappingModule.xml</param-value>
  </init-param>
  <init-param>
   <param-name>config/uploadModule</param-name>
   <param-value>/WEB-INF/config/struts-uploadModule.xml</param-value>
  </init-param>

  
   </servlet>
 
  <servlet-mapping> <!-- url 패턴 설정 -->
   <servlet-name>action</servlet-name> <!-- *.do로 들어오면 servlet-name이 action 실행 -->
   <url-pattern>*.do</url-pattern>
  </servlet-mapping>
 
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>
-----------------------------------------------------------------------------------------------
모듈화를 위해 다음과 같이 모듈로 설정한다.

여기서 중요한 부분은

<init-param>
   <param-name>config</param-name>
   <param-value>/WEB-INF/config/struts-config.xml</param-value>
  </init-param>
이부분과 같지 config는 기본적으로 있어야 하며

<init-param>
   <param-name>config/dispatchModule</param-name>
   <param-value>/WEB-INF/config/struts-dispatchModule.xml</param-value>
  </init-param>
위의 빨간색 이름은 동일해야 한다. 또한 param-name의 빨간색 부분은 jsp페이지의 이름이 prefix인 hidden값으로 보내는 value와 같아야 해당 모듈이 실행된다.

2) 각각의 config.xml파일을 생성한다.

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

이부분은 각각의 config.xml파일에 모두 존재해야 한다.

3) jsp페이지에서 name 이 prefix와 page인 hidden값을 생성하고 각각을 파라미터로 넘겨준다.

<input type="hidden" name="prefix" value="/mappingModule">
<input type="hidden" name="page"   value="/register.do">


prefix로 전달되는 value는 web.xml파일에 설정된 mappingModule을 사용하겠다는 것이고 page는 그 모듈안에 있는 어떠한 action을 사용할지를 적어 주면 된다.

Struts 1 - 스트럿츠 1의 다양한 Action Class 들 part 2

Published on: 2009. 6. 29. 23:39 by louis.dev


1. LookupDispatchAction




getKeyMethodMap() 메서드를 구현하고 리소스 번들의 키와 메소드명을 매핑한다. 기본적으로 파라미터로 method 이름을 전달하여 그것을 통하여 method를 실행하것으로 DispatchAction과 유사한 방법으로 작동 된다.

작업순서

1)위의 클래스에서 getKeyMethodMap()에서 mapping을 해야 하기 때문에 .properties 로 확장자가 끝나는 메시지번들을 생성한다.

2)LookupDispatchAction Class를 상속받은 Class를 생성하고 LookupDispatchAction Class의 getKeyMethodMap()를 Override 하여 구현한다.

3)struts-config-lookup.xml 파일을 생성한다.

4)web.xml 에 struts-config-lookup.xml파일을 설정한다.

5)LookupDispatchAction 을 사용할 jsp 페이지 에서 DispatchAction에서 했던것과 동일 한방법으로 hidden으로 값을 숨기고 전달한다.


작업 방법
1)mapping을 위한 메시지 번들(.properties)를 생성한다.

-이클립스 자체에서 .properties파일을 생성하면 에러가 발생한다. 물론 플러그인을 추가하여 이클립스를 통해 properties파일을 생성 할 수 있지만 일단 메모장에서 작업하고 가져오는 방법을 취한다.

InfoMessageResource.properties(Original File)
------------------------------------------------------------------------------------------------
# struts1 lookup message bundle
# file name : InfoMessageResource.properties

lookup.register = 등록
lookup.list = 리스트
lookup.query = 쿼리
lookup.update = 갱신
lookup.delete = 삭제

# 국제회(Locale) 표준코드 (Unicode)로 변환
# native2ascii [-encoding 코드값] 원시파일 대상파일
# 코드값 : euc-kr, ksc5601, ms949, utf-16

# natice2ascii -encoding euc-kr InfoMessageResource.properties InfoMessageResource_ko.properties
------------------------------------------------------------------------------------------------
다음의 내용을 메모장을 통해 작성후 eclipse의 패키지에 끌어다 놓는다.
#은 주석이다.

가장 핵심 적인 부분은

lookup.register = 등록
lookup.list = 리스트
lookup.query = 쿼리
lookup.update = 갱신
lookup.delete = 삭제

이부분 인데 나중에 LookupDispatchAction Class를 상속한 파일에서 getKeyMethodMap() 메소드를 오버라이딩 하고 거기서 mapping시킬때 사용한다. 위와 같이 한글로 만들 수 있으며 한글로 저장하고 바로 properties파일을 이클립스에 끌어다 놓으면 한글이 깨진다..

------------------------------------------------------------------------------------------------
# struts1 lookup message bundle
# file name : InfoMessageResource.properties

lookup.register = µî·Ï
lookup.list = ¸®½ºÆ®
lookup.query = Äõ¸®
lookup.update = °»½Å
lookup.delete = »èÁ¦

# ±¹Á¦È¸(Locale) Ç¥ÁØÄÚµå (Unicode)·Î º¯È¯
# native2ascii [-encoding Äڵ尪] ¿ø½ÃÆÄÀÏ ´ë»óÆÄÀÏ
# Äڵ尪 : euc-kr, ksc5601, ms949, utf-16

# native2ascii -encoding euc-kr InfoMessageResource.properties InfoMessageResource_ko.properties
------------------------------------------------------------------------------------------------
그러므로 맨아래 부분에 처리된 주석과 같이 인코딩 타입을 euc-kr로 변환하는 작업을 해 주어야 하며 jdk/bin폴더 안에 있는 native2ascii 를 통해 변환 할 수 있다.

          [native2ascii를 통해 변환 하는 방법]
          1.콘솔창을 실행하고 맨처음 properties파일을 생성한 위치로 이동을 한다.
 

          2. 이동한 곳에서 native2ascii 사용하여 encoding타입을 euc-kr타입으로 변경한다.
          native2ascii [-encoding] [코드값] [원시파일] [목적파일]
          형식으로 작업하면 된다.
         
          예) native2ascii -encoding euc-kr InfoMessageResource.properties InfoMessageResource_ko.properties

          를 콘솔창에 쓴다.


          그러면 위와 같이 InfoMessageResource_ko.properties파일이 생성 된 것을 볼 수 있고 인코딩 되어 있는 것을 확인 할 수 있다.
          InfoMessageResource_ko.properties
          ----------------------------------------------------------------------------------------
          # struts1 lookup message bundle
          # file name : InfoMessageResource.properties

          lookup.register = \ub4f1\ub85d
          lookup.list = \ub9ac\uc2a4\ud2b8
          lookup.query = \ucffc\ub9ac
          lookup.update = \uac31\uc2e0
          lookup.delete = \uc0ad\uc81c

          # \uad6d\uc81c\ud68c(Locale) \ud45c\uc900\ucf54\ub4dc (Unicode)\ub85c \ubcc0\ud658
          # native2ascii [-encoding \ucf54\ub4dc\uac12] \uc6d0\uc2dc\ud30c\uc77c \ub300\uc0c1\ud30c\uc77c
          # \ucf54\ub4dc\uac12 : euc-kr, ksc5601, ms949, utf-16

          # native2ascii -encoding euc-kr InfoMessageResource.properties InfoMessageResource_ko.properties
          ----------------------------------------------------------------------------------------
          
         ※만약 natice2ascii에 대해서 찾을 수 없다는 에러가 나오면 환경변수중에 path를 설정하지 않은 것이다. path를 설정해 주면 바로 사용해 줄 수        있다.

          3) 만들어진 두개의 파일을 elipse의 원하는 곳으로 복사를 해서 가지고 온다.

          4) config.xml 파일에 .properties파일 경로를 설정해 준다.
          <message-resources parameter="com.myhome.lookup.InfoMessageResource" />

2)LookupDispatchAction Class를 상속한 InfoLookupDispatchAction Class(임의)를 생성한다.

----------------------------------------------------------------------------------------
package com.myhome.lookup;

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

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

import org.apache.commons.beanutils.BeanUtils;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.actions.LookupDispatchAction;


import com.myhome.info.beans.InfoFormBean;
import com.myhome.info.dao.InfoDAO;
import com.myhome.info.dto.InfoDTO;

public class InfoLookupDispatchAction  extends LookupDispatchAction {
 
 @Override
 protected Map<String,String> getKeyMethodMap() {
  
  Map<String,String> map = new HashMap<String, String>();
  map.put("lookup.register", "register");  //메시지번들에 있는 키와 같아야 한다. 뒤에는 메소드 명이다.
  map.put("lookup.list", "list");
  map.put("lookup.query", "query");
  map.put("lookup.update", "update");
  map.put("lookup.delete", "delete");
  return map;
 }

 public ActionForward register(ActionMapping mapping,
     ActionForm form,
     HttpServletRequest request,
     HttpServletResponse response)
     throws Exception{

 /*form parameter를 bean으로 받는다*/
  InfoFormBean bean = new InfoFormBean();
  bean.setName(request.getParameter("name"));
  bean.setSex(request.getParameter("sex"));
  bean.setTel(request.getParameter("tel"));
  
  /*bean property 를 dto로 복사한다.*/
  InfoDTO dto = new InfoDTO();
  BeanUtils.copyProperties(dto, bean);
  dto.setWdate(this.getWdate());
  
  /*info table에 연동한다.*/
  
  new InfoDAO().register(dto);
  
  /*result.jsp로 포워드하기 위해 리퀘스트 영역에 dto를 binding한다
  * */
  request.setAttribute("dto", dto);
  
  
  return mapping.findForward("result");
 }
 
 public ActionForward list(ActionMapping mapping,
     ActionForm form,
     HttpServletRequest request,
     HttpServletResponse response)
     throws Exception{
  
  List<InfoDTO> list = null;
  
  list = new InfoDAO().getAllQuery();
  
  request.setAttribute("list", list);
  
  return mapping.findForward("list");
 }
 
 public ActionForward query(ActionMapping mapping,
     ActionForm form,
     HttpServletRequest request,
     HttpServletResponse response)
     throws Exception{
  InfoFormBean bean = (InfoFormBean)form;
  InfoDTO dto = new InfoDTO();
  BeanUtils.copyProperties(dto, bean);
  
  //쿼리된 object를 리퀘스트 영역에 바인딩 한다.
  
  request.setAttribute("dto", new InfoDAO().getQuery(dto));
  
  return mapping.findForward("query");
 }
 
 public ActionForward update(ActionMapping mapping,
      ActionForm form,
      HttpServletRequest request,
      HttpServletResponse response)
      throws Exception{
  /*form parameter를 InfoFormBean으로 받는다*/
  
  /**
  *  ActionForm의 역할
  *   Form parameter의 정보를 참조하기 위해
  *   ActionForm의 객체를 초기화 한다 - reset()
  * 
  *   form parameter의 정보를 받아 유효성 검사를 실시한다 - validate()
  * 
  *   참조한 폼 정보를 form-bean에 설정도니 bean으로 전달한다.
  * */
 
  InfoFormBean bean = (InfoFormBean)form;
  
  /*bean의 객체를 Entity(DTO)로 property를 복사한다.*/
  InfoDTO dto = new InfoDTO();
  BeanUtils.copyProperties(dto, bean);
  
  new InfoDAO().update(dto);
  
  
  return mapping.findForward("update");
 }
 
 public ActionForward delete(ActionMapping mapping,
      ActionForm form,
      HttpServletRequest request,
      HttpServletResponse response)
      throws Exception{
 
  InfoFormBean bean = (InfoFormBean)form;
  
  /*bean의 객체를 Entity(DTO)로 property를 복사한다.*/
  InfoDTO dto = new InfoDTO();
  BeanUtils.copyProperties(dto, bean);
  new InfoDAO().delete(dto);
  return mapping.findForward("delete");
 }
 protected String getWdate(){
  return new java.text.SimpleDateFormat("yyyy-MM-dd").format(new java.util.Date());
 }

}
----------------------------------------------------------------------------------------

이 클래스 에서 가장 중요한 부분은 getKeyMethodMap() 부분이다.
Map을 한개 선언한 뒤에 위의 properties에서 선언한 대로 map에 집어 넣으면 된다.

  map.put("lookup.register", "register");  
  map.put("lookup.list", "list");
  map.put("lookup.query", "query");
  map.put("lookup.update", "update");
  map.put("lookup.delete", "delete");

앞의 lookup.~~ 는 properties파일에 정의된 부분과 같아야 되며 뒤에는 실행될 메소드 이름이다.


3)struts-config-lookup.xml 을 생성한다.

-----------------------------------------------------------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC
          "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
          "http://struts.apache.org/dtds/struts-config_1_3.dtd">

<struts-config>
 <action-mappings>
  <action path = "/lookupIndex"
    type = "org.apache.struts.actions.ForwardAction"
    parameter="/lookup/register.jsp"/>
  
  <!--
   unknown은 input속성을 대체하기 위한 속성이다.
   입력폼이 여러개 발생할 때 사용된다.
   template.jsp는 list.do로 보내면 어디로 가야 할지 모르기때문에
  -->
  
  <action path = "/lookup"
    name = "bean"
    scope = "request"
    unknown = "true"
    parameter = "method"
    type = "com.myhome.lookup.InfoLookupDispatchAction">
   
   <forward name="result" path = "/lookup/result.jsp"/>
   <forward name="list" path = "/lookup/list.jsp"/>
   <forward name="query" path = "/lookup/modify.jsp"/>
   <forward name="update" path = "/lookup/template.jsp"/>
   <forward name="delete" path = "/lookup/template.jsp"/>
  
  </action>
 </action-mappings>
 
 <!-- Message Resources Definitions -->
 <!-- .property 파일을 설정 -->
 <message-resources parameter="com.myhome.lookup.InfoMessageResource" />
 
</struts-config>
-----------------------------------------------------------------------------------------
가장 핵심적인 부분은 굵은 선의 <action></action>이 핵심이다. DispatchAction 과 같은 형태로 선언 되어 있으며 jsp 페이지 에서 hidden name이 method인 것을 value를 받아 type로 선언된 class로 이동하여 getKeyMethodMap() 를 실행하고 mapping을통해 메소드가 실행된다.

4. web.xml에 config파일을 등록한다

-----------------------------------------------------------------------------------------
<param-value>
   /WEB-INF/struts-config.xml,
   /WEB-INF/struts-config-dispatch.xml,
   /WEB-INF/struts-config-mapping.xml,
   /WEB-INF/struts-config-lookup.xml  
  </param-value>
-----------------------------------------------------------------------------------------

5. jsp페이지에서 hidden값으로 넘겨준다.

<input type="hidden" name="method" value="등록">

이렇게 선언을 하고 submit이 되면
properties파일을 거쳐 lookup.register = 등록 과 같은 맵핑을 수행하게 된다. 이렇게 맵핑된 것은 LookupDispatchAction class의 getKeyMethodMap() 부분에서 map.put("lookup.register", "register"); 를 통해 register method가 실행 되게 된다.

           

Struts 1 - 스트럿츠 1의 다양한 Action Class 들 part 1

Published on: 2009. 6. 26. 17:16 by louis.dev

1. ForwardAction Class


만약 기본타입처럼 Request Process를 거치지 않고 바로 뷰 페이지를 요청 할때는 다음과 같이 선언 할 수 있다.

<action path = "/index"  forward = "/info/register.jsp"/>

하지만 이렇게 action을 설정 하게 되면 위의 그림에서 보듯이 ActionServlet 에서 들어와서 Request processor를 거쳐 바로 ViewPage로 이동 하게 된다. 하지만 ForwardAction 을 쓰게 되면 Request Processor에서 ActionForm으로 넘어가 모든 로딩을 거쳐 ViewPage를 요청하게 할 수 있다.

<action path="/index"
          type = "org.apache.struts.actions.ForwardAction"
          parameter = "/info/register.jsp"/>

- type : 여기서 struts에서 제공하는 ForwardAction Class를 설정한다.
- parameter : 보여줄 view page의 경로를 설정 한다.

2.IncludeAction Class


defalte를 사용하면 Action에서 로직을 실행한후 ActionMapping을 통해 ActionForward로 이동후 Request Processor로 이동한후 view Page로 이동하는데 IncludeAction Class를 사용하면 ActionForward 에서 RequestProcessor를 거쳐서 View Page로 이동하는 것이아니라 바로 View Page로 이동할 수 있다.

- 장점 : ViewPage로 빠른 이동이 가능하다(검색 등에 사용)
- 단점 : Request Prcessor를 거쳐 가지 않기 때문에 processe method에서 실행하는 page Encoding이라 던가 validator를 사용할 수 없다.

예)
<action path="/index"
          type = "org.apache.struts.actions.IncludeAction"
          parameter = "/info/register.jsp"/>

3. DispatchAction Class
일반적으로 Action class를 상속받아 사용하게 되면 하나의 로직당 하나의 Class만을 생성 해야 하기 때문에 Class Over Head가 발생하기 쉽다. 이럴때는 Action Class를 상속 받지 않고 DispatchAction Class를 상속받고 그안에 메소드 형식으로 구현 하기 때문에 클래스 한개에서 모두 처리 할 수 있다.
하나의 클래스에서 이름이 다른 여러개의 ActionForward를 사용 할 수 있다.


다음 그림과 같이 jsp 페이지 에서는 form 태그 안에 hidden 으로 사용할 method 이름을 value로 넘겨 준다. value가 DispatchAction 을 상속 받은 클래스의 method 와 이름이 같아야 클래스에서 method가 실행 된다.

다음으로는 struts-config.xml 파일의 <action mapping>안의 내용이다
여기서 눈여겨 볼 내용은 type 과 parameter 이다.

- type : DispatchAction을 상속 받은 클래스의 위치를 지정
- parameter : jsp page의 hidden 태그의 name과 parameter 의 값과 같아야 한다.

즉 jsp페이지에서 히든으로 넘겨주는 value가 각각의 메소드 이름일때 다음의 것들이 실행 된다는 것이다.

ex)struts-config.xml

<struts-config>
 <action-mappings>
  <action path = "/dispatchIndex"
    type = "org.apache.struts.actions.ForwardAction"
    parameter="/dispatch/register.jsp"/>
  
  <!--
   unknown은 input속성을 대체하기 위한 속성이다.
   입력폼이 여러개 발생할 때 사용된다.
   template.jsp는 list.do로 보내면 어디로 가야 할지 모르기때문에
  -->
  
  <action path = "/dispatch"
    name = "bean"
    scope = "request"
    unknown = "true"
    parameter = "method"
    type = "com.myhome.dispatch.InfoDispatchAction">
   
   <forward name="result" path = "/dispatch/result.jsp"/>
   <forward name="list" path = "/dispatch/list.jsp"/>
   <forward name="query" path = "/dispatch/modify.jsp"/>
   <forward name="update" path = "/dispatch/template.jsp"/>
   <forward name="delete" path = "/dispatch/template.jsp"/>

  
  </action>
  
 </action-mappings>

위와 같이 forward 이름이 각 method마다 달라야 한다.


구현은 jsp 페이지 에서

1) DispatchAction을 상속 받은 클래스 생성
EX)
package com.myhome.dispatch;

import java.util.List;

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

import org.apache.commons.beanutils.BeanUtils;
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 org.apache.struts.actions.DispatchAction;

import com.myhome.info.beans.InfoFormBean;
import com.myhome.info.dao.InfoDAO;
import com.myhome.info.dto.InfoDTO;

 

public class InfoDispatchAction extends DispatchAction{
 
 public ActionForward register(ActionMapping mapping,
          ActionForm form,
          HttpServletRequest request,
          HttpServletResponse response)
          throws Exception{
  
  /*form parameter를 bean으로 받는다*/
  InfoFormBean bean = new InfoFormBean();
  bean.setName(request.getParameter("name"));
  bean.setSex(request.getParameter("sex"));
  bean.setTel(request.getParameter("tel"));
  
  /*bean property 를 dto로 복사한다.*/
  InfoDTO dto = new InfoDTO();
  BeanUtils.copyProperties(dto, bean);
  dto.setWdate(this.getWdate());
  
  /*info table에 연동한다.*/
  
  new InfoDAO().register(dto);
  
  /*result.jsp로 포워드하기 위해 리퀘스트 영역에 dto를 binding한다
   * */
  request.setAttribute("dto", dto);
  
  
  return mapping.findForward("result");
 }
 
 public ActionForward list(ActionMapping mapping,
         ActionForm form,
         HttpServletRequest request,
         HttpServletResponse response)
         throws Exception{
  
  List<InfoDTO> list = null;
  
  list = new InfoDAO().getAllQuery();
  
  request.setAttribute("list", list);

  return mapping.findForward("list");
 }
 
 public ActionForward query(ActionMapping mapping,
         ActionForm form,
         HttpServletRequest request,
         HttpServletResponse response)
         throws Exception{
  InfoFormBean bean = (InfoFormBean)form;
  InfoDTO dto = new InfoDTO();
  BeanUtils.copyProperties(dto, bean);
  
  //쿼리된 object를 리퀘스트 영역에 바인딩 한다.
  
  request.setAttribute("dto", new InfoDAO().getQuery(dto));

  return mapping.findForward("query");
 }
 
 public ActionForward update(ActionMapping mapping,
         ActionForm form,
         HttpServletRequest request,
         HttpServletResponse response)
         throws Exception{
  /*form parameter를 InfoFormBean으로 받는다*/
  
  /**
   *  ActionForm의 역할
   *   Form parameter의 정보를 참조하기 위해
   *   ActionForm의 객체를 초기화 한다 - reset()
   * 
   *   form parameter의 정보를 받아 유효성 검사를 실시한다 - validate()
   * 
   *   참조한 폼 정보를 form-bean에 설정도니 bean으로 전달한다.
   * */
  
  InfoFormBean bean = (InfoFormBean)form;
  
  /*bean의 객체를 Entity(DTO)로 property를 복사한다.*/
  InfoDTO dto = new InfoDTO();
  BeanUtils.copyProperties(dto, bean);
  
  new InfoDAO().update(dto);
  

  return mapping.findForward("update");
 }
 
 public ActionForward delete(ActionMapping mapping,
         ActionForm form,
         HttpServletRequest request,
         HttpServletResponse response)
         throws Exception{

  InfoFormBean bean = (InfoFormBean)form;
  
  /*bean의 객체를 Entity(DTO)로 property를 복사한다.*/
  InfoDTO dto = new InfoDTO();
  BeanUtils.copyProperties(dto, bean);
  new InfoDAO().delete(dto);
  return mapping.findForward("delete");
 }
 protected String getWdate(){
  return new java.text.SimpleDateFormat("yyyy-MM-dd").format(new java.util.Date());
 }
 
}


4.MappingDispatchAction Class

DispatchAction은 각 사용할 method를 hidden값으로 받아서 xml에서 세팅 해주어야 한다. 그리고 DispatchAction을 사용하면 input 테그에서 데이터를 받을때 다양한 값을 받을 수 없기 때문에 MappingDispatchAction을 사용한다.

1)MappingDispatchAction을 상속받아 클래스를 생성한다.
(DispatchAction Class와 다를 것이 없다)

2)xml을 설정한다.
<action-mappings>
  <action path="/mappingIndex"
    type = "org.apache.struts.actions.ForwardAction"
    parameter="/mapping/register.jsp" />
  
  <action path="/mappingRegister"
    parameter="register"
    type="com.myhome.dispatch.InfoMappingDispatchAction">
   <forward name="result" path="/mapping/result.jsp"/>
  </action>
  
  <action path="/mappingList"
    parameter="list"
    type="com.myhome.dispatch.InfoMappingDispatchAction">
   <forward name="list" path="/mapping/list.jsp"/>
  </action>
  
  <action path="/mappingQuery"
    parameter="query"
    type="com.myhome.dispatch.InfoMappingDispatchAction"
    name="bean"
    scope="request"
    input="/mapping/modify.jsp">
   <forward name="query" path="/mapping/modify.jsp"/>
  </action> 
  
  <action path="/mappingUpdate"
    parameter="update"
    type="com.myhome.dispatch.InfoMappingDispatchAction"
    name="bean"
    scope="request"
    input="/mapping/modify.jsp">
   <forward name="update" path="/mappingList.do" redirect="true"/>
  </action>
  
  <action path="/mappingDelete"
    parameter="delete"
    type="com.myhome.dispatch.InfoMappingDispatchAction"
    name="bean"
    scope="request"
    input="/mapping/modify.jsp">
   <forward name="delete" path="/mappingList.do" redirect="true"/>
  </action>

  
 </action-mappings>

-paramether : MappingDispatchAction Class의 method 이름이다.

이렇게 구현하면 jsp 페이지에서 hidden으로 넘겨줄 필요가 없다.

Struts 1 - ActionForm 사용하기

Published on: 2009. 6. 26. 16:31 by louis.dev


1.ActionForm Class를 상속받아 FormBean Class를 만든다.
ex)InfoFormBean.java
package com.myhome.info.beans;

import org.apache.struts.action.ActionForm;

@SuppressWarnings("serial")
public class InfoFormBean extends ActionForm{
 
 private int num;
 private String name;
 private String sex;
 private String tel;

 //사용자 jsp페이지에서 파라미터로 넘어오는 파라미터 네임과 같아야 한다.
 public int getNum() {
  return num;
 }
 public void setNum(int num) {
  this.num = num;
 }
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public String getSex() {
  return sex;
 }
 public void setSex(String sex) {
  this.sex = sex;
 }
 public String getTel() {
  return tel;
 }
 public void setTel(String tel) {
  this.tel = tel;
 }
 
}

2.struts-config.xml 에서 form-bean을 설정한다.

1) 기본적인 ActionForm을 사용할때
<form-beans> 

        <form-bean
            name="bean"  
            type="com.myhome.info.beans.InfoFormBean"/>
</form-beans>

- name : 다른 config파일에서 사용할 이름을 사용자 편의 대로 정의 한다.
- type: 처음의 ActionForm Class를 상속받은 클래스의 패키지명과 클래스 이름을 설정한다.(InfoFormBean은 사용자 임의의 Class)

2) DynaActionForm 을 사용할때

- 사용자로 부터 파라미터로 넘어오는 값이 bean Class안에 정의 되어 있지 않거나 사용자로부터 어떠한 값이 넘어 올지 알 수 없을때 사용한다.
- ActionForm 처럼 ActionForm Bean Class를 만들 필요는 없고 xml 상에 선언만 해주면 된다.

<form-beans> 
        <!--
         DynaActionForm은 예측할 수 없는 파라미터를 참조할때 사용한다.
        -->
        <form-bean
         name="dyna"
         type = "org.apache.struts.action.DynaActionForm">
         <!--
          form bean에 존재하지 않는 파라미터를 참조하기 위해 property를 설정한다.
          -->
          <form-property name="num" type="java.lang.Integer"/>
          <form-property name="name" type="java.lang.String"/>
          <form-property name="sex" type="java.lang.String"/>
          <form-property name="tel" type="java.lang.String"/>
          <form-property name="wdate" type="java.lang.String"/>
        </form-bean>
         
    </form-beans>

- name : ActionForm 와 같은 용도
- type : struts에서 제공되는 클래스를 사용하는 것이기 때문에 직접 DynaActionForm을 설정해 준다.
- <form-property> : 저장될 이름을 선언해 준다.



3.struts-config.xml 파일의 <action-mapping>에 <action>태그와 함께 설정한다.

1) ActionForm을 상속한 bean을 사용할때
예)
<action path = "/update"
          name = "bean"
          scope = "request"
          input = "/info/modify.jsp"
          type = "com.myhome.info.actions.InfoUpdateAction">
     <forward name="success" path="/list.do" redirect="true"/>
</action>

- path : 주소창에 들어오는 URL 패턴, 이때 web.xml에 선언한 .do는 제거 하고 선언한다.
- name : 상단의 <form-beans>태그에 선언된 form-bean중 사용할 form-bean name을 적어 준다.
- scope : "request|session|application" - 다음의 영역으로 들어오는 정보
- input : 입력받은 폼 페이지 명 명시 - 정의된 곳에서 들어오는 데이터를 사용하겠다.
- type: Bussiness Logic을 수행할 Action Class 선언
- <forward> : Action class에서 actionForward로 'success' 를 보내면 path로 선언된 곳으로 보내겠다.
                    redirect = forward 부분에서 path만 잡아 주면 주소창은 변하지 않고 페이지만 변경 시킨다. 그래서 redirect를 true를 설정하면 주소 까지 바뀌어 버린다.

2)DynaActionForm 을 사용할 때
예)
<action path="/delete"
          name = "dyna"
          scope = "request"
          input= "/info.modify.jsp"
          type = "com.myhome.info.actions.InfoDeleteAction">
   <forward name = "success" path = "list.do" redirect="true" />
</action>

※참고 : ActionForm 을 사용할때 꼭 필요한 attribute 들은 name, scope, input 이다.

 4. Action에서 사용 방법

public ActionForward execute(ActionMapping mapping, ActionForm form,
   HttpServletRequest request, HttpServletResponse response)
   throws Exception {
  
  /*form parameter를 InfoFormBean으로 받는다*/
  
  /**
   *  ActionForm의 역할
   *   Form parameter의 정보를 참조하기 위해
   *   ActionForm의 객체를 초기화 한다 - reset()
   * 
   *   form parameter의 정보를 받아 유효성 검사를 실시한다 - validate()
   * 
   *   참조한 폼 정보를 form-bean에 설정된 bean으로 전달한다.
   * */
  
  InfoFormBean bean = (InfoFormBean)form;
  
  /*bean의 객체를 Entity(DTO)로 property를 복사한다.*/
  InfoDTO dto = new InfoDTO();
  BeanUtils.copyProperties(dto, bean);
  
  new InfoDAO().update(dto);
  
  return mapping.findForward("success");
 }


만약 ActionForm을 상속한 form객체를 사용하면 위와 같은 방식으로 하되 config.xml파일에서 bean을 DynaActionForm으로 구현 했다면 물론 위의
코드중
InfoFormBean bean = (InfoFormBean) form;
이코드는
DynaActionForm bean = (DynaActionForm)form;

으로 타입 케스팅을 해주어야 캐스팅 에러가 나지 않는다.

iBatis - 기본 설정

Published on: 2009. 6. 25. 16:42 by louis.dev


1. iBatis Library를 추가한다.

2. SqlMapConfig.xml 파일을 생성한다.

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

<sqlMapConfig>
    <settings
  cacheModelsEnabled="true"
  enhancementEnabled="true"
  lazyLoadingEnabled="true"
  maxRequests="32"
  maxSessions="10"
  maxTransactions="5"
  useStatementNamespaces="false"
 />
 
<!-- JNDI사용 -->
   <transactionManager type="JDBC" >
 <dataSource type="JNDI">
   <property name="DataSource"
      value="java:comp/env/jdbc/XE"/>
 </dataSource>
   </transactionManager>
 <sqlMap resource="com/myhome/info/sql/SqlMap.xml" />
</sqlMapConfig>

/////////////////////////////////////////////////////////////////
위의 설정은 JNDI를 사용하기 때문에 JNDI설정을 해 주어야 한다.

1. Server 의 server.xml파일에 다음을 추가한다.
(33번째 줄 <GlobalNamingResources> 태그 안에 선언한다)

<Resource auth="Container"
        driverClassName="oracle.jdbc.driver.OracleDriver"
        factory="org.apache.commons.dbcp.BasicDataSourceFactory"
        maxActive="20"
        maxIdle="10" 
        maxWait="-1"
        name="jdbc/XE"
        username="user01"
        password="user01"
        type="javax.sql.DataSource"
        url="jdbc:oracle:thin:@localhost:1521:XE" />

2. Server 의 context.xml 파일의 가장 하단에 다음을 추가 한다.

<ResourceLink global="jdbc/XE"
                  name="jdbc/XE"
                  type="javax.sql.DataSource"/>


※JNDI말고 다른 방법으로 사용 할 수 있다. SqlMapConfig.xml 파일에 다음을 추가 한다.
1.simple datasource type  사용
<transactionManager type="JDBC" commitRequired="false">
        <dataSource type="SIMPLE">
            <property name="JDBC.Driver"
                      value="oracle.jdbc.driver.OracleDriver"/>
            <property name="JDBC.ConnectionURL"
                      value="jdbc:oracle:thin:@localhost:1521:XE"/>
            <property name="JDBC.Username" value="user01"/>
            <property name="JDBC.Password" value="user01"/>
        </dataSource>
    </transactionManager>

2.DBCP datasource type 사용
<properties resource=" info/model/dao/db.properties " />
     
   <transactionManager type="JDBC" >
  <dataSource type="SIMPLE">
  <property name="JDBC.Driver" value="${driver}"/>
  <property name="JDBC.ConnectionURL" value="${url}"/>
  <property name="JDBC.Username" value="${username}"/>
  <property name="JDBC.Password" value="${password}"/>
  <property name="JDBC.DefaultAutoCommit" value="true" />
  <property name="Pool.MaximumActiveConnections" value="10"/>
  <property name="Pool.MaximumIdleConnections" value="5"/>
  <property name="Pool.MaximumCheckoutTime" value="120000"/>
  <property name="Pool.TimeToWait" value="500"/>
  </dataSource>
  </transactionManager> 
////////////////////////////////////////////////////////////////

3.SqlMap.xml 파일을 생성 한다.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
 "http://ibatis.apache.org/dtd/sql-map-2.dtd">

<sqlMap>
  <typeAlias alias="Info" type="com.myhome.info.dto.InfoDTO"/><!-- alias : 별칭을 잡겠다는 의미 -->
 
  <insert id="infoInsert" parameterClass="Info"><!-- typeAlias한 Info를 넣는다 없으면 com.. 그대로 넣어도 된다. -->
   INSERT INTO INFO
    (NUM, NAME, SEX, TEL, WDATE)
   VALUES
    (NUMSEQ.NEXTVAL, #name#, #sex#, #tel#, #wdate#)<!-- ## Info 안에 가지는 프로퍼티 대소문자가 정확하게 맞아야 한다. -->
  </insert>
 
  <statement id="infoList" resultClass="Info">
   SELECT NUM, NAME, SEX, TEL, WDATE
   FROM INFO
  </statement>
 
</sqlMap>

4.SQLManager.java 파일 생성
package com.myhome.manager;

import com.ibatis.common.resources.Resources;
import com.ibatis.sqlmap.client.SqlMapClient;
import com.ibatis.sqlmap.client.SqlMapClientBuilder;

public abstract class SQLManager {
 
 private SqlMapClient sc = null;
 
 public SQLManager(){
  try{
   sc = SqlMapClientBuilder.buildSqlMapClient(
            Resources.getResourceAsReader(
              "com/myhome/info/sql/SqlMapConfig.xml"));
  }catch(java.io.IOException ie){
   ie.printStackTrace();
  }
 }
 
 public SqlMapClient getSqlMap(){
  return sc;
     }
}

5.DAO에서 다음과 같이 사용
package com.myhome.info.dao;

import com.myhome.info.dto.InfoDTO;
import com.myhome.manager.SQLManager;
import java.sql.SQLException;
import java.util.List;

public class InfoDAO extends SQLManager{
 /*등록부분*/
 public void register(InfoDTO dto) throws SQLException{
  this.getSqlMap().insert("infoInsert",dto);
 }
 
 /*회원 리스트 부분*/
 @SuppressWarnings("unchecked")
 public List<InfoDTO> getAllQuery(){
  List<InfoDTO> list = null;
  try {
   list = (List<InfoDTO>)this.getSqlMap().queryForList("infoList");
  } catch (SQLException e) {
   e.printStackTrace();
  }
  return list;
 }
}


☆SqlMapConfig.xml의 추가 사항

1.전체적인 내용
 
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE sqlMapConfig

 PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0 //EN"

 "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">

<sqlMapConfig>

    <settings/>

    <properties resource=" db.properties " />

    <transactionManager></transactionManager>

    <sqlMap></sqlMap>

</sqlMapConfig>

위에서 가장 중요한 것은 transactionManager 와 sqlMap부분이며 setting과 properties resource 는 선택 사항이다.

2. settings의 내용들
cacheModelsEnalbe ="true" : SqlMapClient를 위한 모든 캐쉬모델을 가능하게 하거나 가능하지 않게 한다.
이것은 디버깅시 도움이 된다.
enhancernetEnable="true" : 향상된 lazy로딩처럼 최적화된 자바빈즈 속성 접근을 위해 런타임시 바이트코드 향상을 가능하게 한다.
lazyLoadingEnabled="true" : SqlMapClient 를 위한 모든 lazy로딩ㅇ르 가능하게 하거나 가능하지 않게 한다.
maxRequests="32" : 한꺼번에 SQL을 실행할 스래드 수이고 2에n승으로 확장할 수 있고 128이 맥시멈이다.
maxSession="10" : 주어진 시간동안 활성화 될 수 있는 세션 수
maxTransaction="5" : 한꺼번에 SqlMapClient.startTransaction()에 들어갈 수 있는 스레드의 최대 갯수
useStatementNamespaces ="false"
 

3. db.properties 파일 설정
 


driver=oracle.jdbc.driver.OracleDriver


url=jdbc:oracle:thin:@localhost:1521:XE


username=user01

password=mypwd