■ 개발 순서

먼저 하이버네이트 툴을 설치 한다.

https://www.hibernate.org/ 에서 hibernate tool zip 파일을 다운 받아 압출을 풀고 features, plugins 폴더를 eclipse가 설된 폴더에 복사해 넣는다. 그러면 설치 끝.


1. log4j.xml 파일 만들기, library 파일 lib 폴더에 넣기(하이버네이트와 스프링을 사용하기 위한 기본적인 라이브러리들)



2. hibernate.cfg.xml 파일 만들기

- WEB-INF 폴더에서 새로운 파일 만들기를 클릭하여 Hibernate Configuration 파일을 선택한다.(하이버네이트 툴이 설취되어 있어야만 나타난다.)


- 파일이름 그대로 두고 다음.


- 자신에 맞는 DB를 선택, 설정 하고 넥스트(XE는 오라클 10g EX버전 ) 아래 Create a console configuration 을 체크한다.


- 이 부분은 하이버네이트 perspective 에서 만들 수 있지만 여기서 하면 한번에 다 만들 수 있다.(위에서 Create a console configuration  체크를 해야지만 된다.)


- 그러면 hibernate.cfg.xml 파일이 만들어 진 것을 볼 수 있다.


log4jdbc를 사용하기 위하여 아래와 같이 변경


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
  "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
  "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <property name="hibernate.connection.driver_class">net.sf.log4jdbc.DriverSpy</property>
        <property name="hibernate.connection.password">user01</property>
        <property name="hibernate.connection.url">jdbc:log4jdbc:oracle:thin:@localhost:1521:XE</property>       
        <property name="hibernate.connection.username">user01</property>
        <property name="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</property>
    </session-factory>
</hibernate-configuration>

- Hibernate perspective 로 이동


- 아래 그림과 같이 만들어 진 것을 볼 수 있다.


이제 부터 개발을 시작 한다.










struts1을 그대로 사용하는 것이 아니라 개발하기 좀 더 편한 방법으로 커스터마이징 해서 사용해본다.

1. lib 셋팅
생성한 프로젝트의 WEB-INF의 lib 폴더에 설정할 라이브러리 파일을 갖다 넣는다 : struts, log4j, struts-test, junit

- apache, sourceforge 사이트에서 각각 다운로드를 받는다.
Junit은 C:\eclipse\plugins\org.junit_3.8.2.v20090203-1005 에서 junit.jar  파일을 사용한다.

- struts의 lib 폴더안에 있는 라이브러리 파일을 사용한다.

- log4j는 라이브러리와 함께, log4j.properties나, log4j.xml 설정 파일을 src 폴더 아래에 넣는다.

- strutstest는 struts를 WAS를 띄우지 않고 테스트 하기 위해 필요하다. strutstest.jar 파일과 common-collection.jar 파일이 필요하다.



2. 서블릿 설정
web.xml 안에 서블릿을 설정한다.
- 다운 받아 압출을 해제한 struts 폴더 안에 struts-blank 안에 있는 web.xml 에서 복사하거나, Servlet을 하나 만들어서 web.xml 안에 생성하게 하고, 만든 Servlet은 삭제 한다.


/action -> *.do 바꾼다.



<servlet>
    <servlet-name>action</servlet-name>
    <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
 </servlet>
  <servlet-mapping>
    <servlet-name>action</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>


3. struts-config.xml 생성
struts-config.xml을 WEB-INF 아래 만들고 struts-blank 안에 있는 struts-config.xml 파일에서 dtd 설정을 복사해서 넣는다.

<!DOCTYPE struts-config PUBLIC
          "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
          "
http://struts.apache.org/dtds/struts-config_1_3.dtd">

나머지 설정(역시 struts-blank 참조)

<struts-config>
 <!-- 액션 폼 설정 파일 -->
 <form-beans>
 </form-beans>
 
 <!-- 공통 예외처리 -->
 <global-exceptions>
 </global-exceptions>
 
 <!-- 공통 링크 이동 처리 -->
 <global-forwards>
 </global-forwards>
 
 <!-- 액션 설정 -->
 <action-mappings>
 </action-mappings>
 
 <!-- 커스터마이징된 RequestProcessor -->
 <controller>
 </controller>
 
 <!-- 다국어 처리, 에러메시지 -->
 <!--  <message-resources parameter=""></message-resources>-->
 
 <!-- 외부 프레임웍, 라이브러리 연동 -->
 <!--  <plug-in className=""></plug-in> -->
 
</struts-config>



여기까지 작업을 하고, WAS를 띄워서 http://127.0.0.1:8081/struts1/*.do 해서 * 아무이름이나 넣고 접속이 되는지 확인한다. 500에러가 발생할 것이다. 그러면 성공.
그리고 struts-config.xml 에서 아래와 같이 설정하고

<action-mappings>
  <action path="/hello" forward="/hello.jsp"></action>
</action-mappings>


설정을 해주고 http://127.0.0.1:8081/struts1/hello.do 했을 때 hello.jsp 라고 뜨는지 확인한다.

log4j 설정을 해놨다면 콘솔창에 로그가 뜬다.

4. util 패키지 않에 기본적으로 구현할 Action을 추상 클래스로 만들어서 오버라이드 시킨다.
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

public abstract class BasicAction extends Action {
 
protected static Logger logger = Logger.getLogger(BasicAction.class); //log4j 설정
 
 public ActionForward execute(ActionMapping mapping,
            ActionForm form,
            HttpServletRequest request,
            HttpServletResponse response)throws Exception{
  
  logger.info("action path" + request.getRequestURI()); //log4j 설정
  
  return executeAction(mapping, form, request,response);
  
 }
 protected abstract ActionForward executeAction(ActionMapping mapping,
            ActionForm form,
            HttpServletRequest request,
            HttpServletResponse response)throws Exception;
}

5. struts에서 기본적으로 CRUD가 나오면 DispatchAction을 사용한다.
action을 만들고 테스트 한다.

public class BbsAction extends DispatchAction {
 private static Logger logger = Logger.getLogger(BbsAction.class);
 
 public ActionForward add(ActionMapping mapping,
            ActionForm form,
            HttpServletRequest request,
            HttpServletResponse response)throws Exception{
  
   return null;
 }
 
}

- test 패키지에서 BbsTest.java를 만들어서 테스트 한다. strutstest는 가짜로 request, response를 만들어서 테스트 할 수 있게 해준다. 아래와 같이 작성 하고, Junit으로 테스트 한다.

import java.io.File;
import servletunit.struts.MockStrutsTestCase;
public class BbsTest extends MockStrutsTestCase {
  public void setUp() throws Exception{
   super.setUp();
   this.setContextDirectory(new File("WebContent")); //반드시 WebContent가 들어가야 한다. WebContent아래 설정 파일들을 불러 오기 위해
  }
 
  public void testAdd() throws Exception{
   this.setRequestPathInfo("/bbs");
    this.actionPerform();
  }
  
  }

6. ActionForm을 안잡고 하는 방법.
ActionForm을 사용 할 경우 상당한 노가다를 해야한다. 그래서 LazyValidatorForm을 사용한다.
이것의 단점은 파라미터 검증을 할 수 없다는 것이다.(그래서 commons의 validation을 적용해서 사용한다.)
ActionForm은 타입이 똑같아야 들어가지만, BeanUtils는 타입이 달라도 들어간다.

- BbsVO 작성

- struts-config.xml 에서 추가.
 <form-beans>
  <form-bean name="lazyForm" type="org.apache.struts.validator.LazyValidatorForm"></form-bean>
 </form-beans>


<action path="/bbs"
 type="org.bnk.bbs.BbsAction"
 parameter="method"
 name="lazyForm"
 validate="false"></action> <!-- 검증을 할 수 없으므로 false -->

- BbsAction 추가

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.log4j.Logger;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.actions.DispatchAction;
import org.apache.struts.validator.LazyValidatorForm;
import org.bnk.bbs.vo.BbsCriteria;
import org.bnk.bbs.vo.BbsVO;
import org.bnk.util.VODisplayer;

public class BbsAction extends DispatchAction {
 private static Logger logger = Logger.getLogger(BbsAction.class);
 
 public ActionForward add(ActionMapping mapping,
            ActionForm form,
            HttpServletRequest request,
            HttpServletResponse response)throws Exception{
  
  LazyValidatorForm lazyForm = (LazyValidatorForm) form;
  
  BbsVO vo = new BbsVO();
  
  BeanUtils.copyProperties(vo, lazyForm);
  
  logger.info(VODisplayer.display(vo));
  
  return null;
 }
 
 public ActionForward update(ActionMapping mapping,
            ActionForm form,
            HttpServletRequest request,
            HttpServletResponse response)throws Exception{
  
  logger.info("update.......");
  return null;
 }
 public ActionForward list(ActionMapping mapping,
            ActionForm form,
            HttpServletRequest request,
            HttpServletResponse response)throws Exception{
  
  logger.info("list.......");
  
  LazyValidatorForm lazyForm =
   (LazyValidatorForm)form;
  
  BbsCriteria cri = new BbsCriteria();
  BeanUtils.copyProperties(cri, lazyForm);
  
  logger.info(VODisplayer.display(cri));
  
  return null;
 }
}

- BbsTest 에서 Junit 으로 테스트

import java.io.File;
import servletunit.struts.MockStrutsTestCase;
public class BbsTest extends MockStrutsTestCase {
  public void setUp() throws Exception{
   super.setUp();
   this.setContextDirectory(new File("WebContent"));
  }
 
  public void testAdd() throws Exception{
   this.setRequestPathInfo("/bbs");
   request.addParameter("method", "add");
  
   request.addParameter("title", "게시물제목");
   request.addParameter("content", "게시물내용");
   request.addParameter("writer", "작성자");  
  
   this.actionPerform();
  }
 
  public void testList()throws Exception{
   this.setRequestPathInfo("/bbs");
   request.addParameter("method", "list");
   
   request.addParameter("pageNo", "5");
   request.addParameter("keyword", "워드");
   request.addParameter("type", "title");
   this.actionPerform();
  }
}

7. BbsCriteria.java 를 만들어서 파라미터를 수집한다.
LazyValidatorForm은 파라미터를 수집한다. 그래서 페이징 할 때, 파라미터를 던지지 말고 객체를 던져서 사용한다. 만약에 파라미터가 변경이 된다면 다 고쳐야 하지만, 이렇게 따로 만들어 놓으면 여기만 고치면 된다.

- BbsTest에서 testList() 로 테스트 한다.

기본 적으로 이렇게 만들어서 개발을 하고, 여기다가 화면을 붙이면 개발 끝~

'FrameWork > Struts1' 카테고리의 다른 글

Struts1 FileDownload  (0) 2009.08.18
Struts1 fileUpload  (0) 2009.08.18
Struts1의 Action 4  (0) 2009.08.16
Struts1의 Action 3  (0) 2009.08.16
Struts1의 Action 2  (0) 2009.08.12
Struts1의 Action 1  (0) 2009.07.27
Struts1에서 ActionForm 사용하기.  (0) 2009.07.25
Struts1 에서 iBatis 사용하기  (0) 2009.07.05
Struts 1 을 사용하여 간단한 회원가입, 리스트 불러오기.  (0) 2009.07.05
Struts1 개발환경 설정.  (0) 2009.07.05
DownloadAction 추상클래스로서 상속시 getStreamInfo()메소드를 다운로드가 가능한 형태로 구현한다.


1. struts-config.xml : action path 추가

<action path="/download"
    type="com.myhome.upload.actions.FileDownloadAction"/>

2. FileDownloadAction.java 작성


package com.myhome.upload.actions;

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

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

/*download*/
import org.apache.struts.actions.DownloadAction;
import java.io.File;
import com.myhome.upload.util.UploadUtil;

public class FileDownloadAction extends DownloadAction {
 
 @Override
 protected StreamInfo getStreamInfo(ActionMapping mapping,
            ActionForm form,
            HttpServletRequest request,
            HttpServletResponse response)
            throws Exception {
  
        String filename = request.getParameter("clip");
       
        File file = new File(UploadUtil.SAVE + filename);
       
        /*한글파일일 경우 헤더타입이 다르므로 변경한다.*/
        String contentType = "application/octet-stream";
        response.setContentType(contentType);
       
        
        /*txt, image파일들은 브라우저가 직접 결과를 전달한다.  
         * 다음과 같이 설정하지 않을 경우 text파일 같은 경우는 브라우져에서
         * 해석이 가능함으로 브라우져에서 바로 열린다. 이것을 처리해 주면
         * 무조건 다운로드 된다.
         * */
       
        response.setHeader("Content-disposition",
                     "attachment;filename="+
                     toEng(file.getName()));
        response.setHeader("Content-Length", ""+file.length());
     
        return new FileStreamInfo(contentType, file);
   }
 
   public String toKor(String data){
     if(data == null)return null;
     String temp = "";
     try{
     temp = new String(data.getBytes("ISO8859_1"),"EUC-KR");
     }catch(java.io.UnsupportedEncodingException uee){}
     return temp;
   }
 
   public String toEng(String data){
     if(data == null)return null;
     String temp = "";
     try{
     temp = new String(data.getBytes("MS949"),"ISO-8859-1");
     }catch(java.io.UnsupportedEncodingException uee){}
     return temp;
   }

자세한 사항은 파일을 참조 한다. FileUploadDownload 다 포함.



'FrameWork > Struts1' 카테고리의 다른 글

struts1 커스터마이징하여 사용하기.  (0) 2009.11.11
Struts1 fileUpload  (0) 2009.08.18
Struts1의 Action 4  (0) 2009.08.16
Struts1의 Action 3  (0) 2009.08.16
Struts1의 Action 2  (0) 2009.08.12
Struts1의 Action 1  (0) 2009.07.27
Struts1에서 ActionForm 사용하기.  (0) 2009.07.25
Struts1 에서 iBatis 사용하기  (0) 2009.07.05
Struts 1 을 사용하여 간단한 회원가입, 리스트 불러오기.  (0) 2009.07.05
Struts1 개발환경 설정.  (0) 2009.07.05


- mmons project의
upload API를 사용한다.
(commons-fileupload-1.2.1.jar, commons-io-1.4.jar)

- Struts1의 파일 업로드는 FormFile class를 사용한다.

- File Upload에서 고려해야 할 사항 3가지는 
1) 저장할 디렉터리 위치
2) 파일 용량 제한
3) 동일한 파일 이름 해결(Rename Policy)
 : 1/1000초 로 계산하여 파일 이름 변경, 파일 명 뒤에 숫자 붙여서 저장

그리고 다 아는 것처럼 DB에는 파일이 저장되는게 아니라 파일 이름과 사이즈가 저장된다. 그걸 통해서 파일을 업로드 다운로드 한다.

1. struts-config.xml 파일 작성 (DispatchAction을 사용하였다.)



<?xml version="1.0" encoding="EUC-KR" ?>
<!DOCTYPE struts-config PUBLIC
          "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
          "http://struts.apache.org/dtds/struts-config_1_3.dtd">
<struts-config>
<!-- ================================================ Form Bean Definitions -->
<!-- form으로 들어오는 데이터를 bean객체에 담는다 -->
    <form-beans>
       <form-bean name="uploadBean" type="com.myhome.upload.beans.UploadFormBean"/> <!-- name은 아무거나 하고 type는 담을 object 객체를 써준다.(전달된 파라미터 데이터가 설정된 빈 - MyBean - 으로 저장이 된다) -->
    </form-beans>

<!-- ========================================= Global Exception Definitions -->
<!-- 어떤 Action에서 Exception이 발생되었는지 모를 때 정의된 곳으로 페이지 이동시킨다. -->
    <global-exceptions>
    </global-exceptions>

<!-- =========================================== Global Forward Definitions -->
<!--  -->
    <global-forwards>
       
    </global-forwards>

<!-- =========================================== Action Mapping Definitions -->
<!-- url패턴으로 맵핑 시킴 -->
  <action-mappings>
  <action path="/index"
    type="org.apache.struts.actions.ForwardAction"
    parameter="/upload/register.jsp"/>
 
  <action path="/upload"
    name="uploadBean"
    scope="request"
    parameter="method"
    unknown="true"
    type="com.myhome.upload.actions.UploadDispatchAction">
 
  <forward name="result" path="/upload/result.jsp"/>
  <forward name="fail" path="/upload/fail.jsp"/>
  <forward name="list" path="/upload/list.jsp"/>
  <forward name="query" path="/upload/modify.jsp"/>
  <forward name="update" path="/upload/template.jsp"/>
  <forward name="delete" path="/upload/template.jsp"/>
  </action>
 
  <action path="/download"
    type="com.myhome.upload.actions.FileDownloadAction"/>
 
 </action-mappings>
 
 <!-- controller processor Definition : Action으로 호출하지 전 처리할 부분-->
 <controller processorClass="com.myhome.info.processor.InfoRequestProcessor"/>
</struts-config>


2. 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">
  <display-name>Struts1FileUploadDownload</display-name>
  <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>
  </servlet>
  <servlet-mapping>
    <servlet-name>action</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>


- iBatis 설정 제외(파일 참조)

3. Bean 작성

package com.myhome.upload.beans;

import org.apache.struts.action.ActionForm;
import org.apache.struts.upload.FormFile;

@SuppressWarnings("serial")
public class UploadFormBean extends ActionForm implements java.io.Serializable{
 
/*form property*/
 private int    num;
 private String name;
 private String sex;
 private String tel;
 private String wdate;
 
 /*upload property*/
 private FormFile file;

 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;
 }

 public String getWdate() {
  return wdate;
 }
 
 public void setWdate(String wdate) {
  this.wdate = wdate;
 }

 public FormFile getFile() {
  return file;
 }

 public void setFile(FormFile file) {
  this.file = file;
 }
 
}



4. 데이터를 저장할 DTO 작성

package com.myhome.upload.dto;

public class UploadDTO{
 
 /*entity property*/
 private int    num;
 private String name;
 private String sex;
 private String tel;
 private String wdate;
 private String fileName;
 private long   fileSize;
 
 
 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;
 }
 public String getWdate() {
  return wdate;
 }
 public void setWdate(String wdate) {
  this.wdate = wdate;
 }
 public String getFileName() {
  return fileName;
 }
 public void setFileName(String fileName) {
  this.fileName = fileName;
 }
 public long getFileSize() {
  return fileSize;
 }
 public void setFileSize(long fileSize) {
  this.fileSize = fileSize;
 }
 
}

5. 데이타베이스에 데이터를 입력하기 위한 DAO 작성

package com.myhome.upload.dao;

import java.sql.SQLException;
import java.util.List;

import com.myhome.manager.SQLManager;
import com.myhome.upload.dto.UploadDTO;

public class UploadDAO extends SQLManager{
 
 public void insert(UploadDTO dto) throws SQLException{
  this.getSqlMap().insert("uploadInsert",dto);
 }

 @SuppressWarnings("unchecked")
 public List<UploadDTO> list() throws SQLException{
  return (List<UploadDTO>)this.getSqlMap().queryForList("uploadList");
 }
}

6. UploadSqlMap.xml

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

<sqlMap>
  <typeAlias alias="Upload"
      type="com.myhome.upload.dto.UploadDTO"/> <!-- alias : 별칭을 잡겠다는 의미 -->
 
  <insert id="uploadInsert" parameterClass="Upload"> <!-- typeAlias한 Info를 넣는다 없으면 com.. 그대로 넣어도 된다. -->
   INSERT INTO UPLOAD
    (NUM, NAME, SEX, TEL, WDATE, FILENAME, FILESIZE)
   VALUES
    (NUMSEQ.NEXTVAL, #name#, #sex#, #tel#, #wdate#,#fileName#,#fileSize#) <!-- ## Info 안에 가지는 프로퍼티 대소문자가 정확하게 맞아야 한다. -->
  </insert>
 
  <statement id="uploadList" resultClass="Upload">
   <![CDATA[
   SELECT NUM, NAME, SEX, TEL, WDATE, FILENAME, FILESIZE
   FROM UPLOAD
   WHERE NUM > 0
   ]]>
   ORDER BY NUM DESC
  </statement>
   
</sqlMap>



7.  UploadUtil.java를 만들어서 파일 경로와 사이즈를 관리한다.


package com.myhome.upload.util;

public final class UploadUtil {

 public static final String SAVE = "D://Java_webprogramming_2/Java_Web2/edu/upload/"; //경로
 
 public static final String SIZE = "1024*1024*20"; //사이즈 20M 지정
}


8. 비즈니스 로직을 수행할 UploadDispatchAction.java

package com.myhome.upload.actions;

import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

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.DispatchAction;
import org.apache.struts.upload.FormFile;

import com.myhome.upload.beans.UploadFormBean;
import com.myhome.upload.dao.UploadDAO;
import com.myhome.upload.dto.UploadDTO;
import com.myhome.upload.util.UploadUtil;

public class UploadDispatchAction extends DispatchAction{
 
 public ActionForward register(ActionMapping mapping,
          ActionForm form,
          HttpServletRequest request,
          HttpServletResponse response)
          throws Exception{
  
  UploadFormBean bean = (UploadFormBean)form;
  UploadDTO dto = new UploadDTO();
  BeanUtils.copyProperties(dto, bean);
  if(bean.getFile() != null){
   this.upload(bean.getFile());
   dto.setFileName(bean.getFile().getFileName());
   dto.setFileSize(bean.getFile().getFileSize());
  }else{
   dto.setFileName("");
   dto.setFileSize(0L);
   new NullPointerException("파일을 올려주세요!!");
  }
  dto.setWdate(this.getWdate());
  
  new UploadDAO().insert(dto);
  request.setAttribute("dto", dto);
  return mapping.findForward("result");
 }

 public void upload(FormFile ff) throws Exception {
     InputStream is = ff.getInputStream();
     OutputStream os = new FileOutputStream(UploadUtil.SAVE + ff.getFileName());
     byte buffer[] = new byte[8192];
     int n = 0;
     while((n = is.read(buffer,0,8192)) != -1){
          os.write(buffer, 0, n);
     }
     /*
     System.out.println("File Name: "+ff.getFileName());
     System.out.println("File Size: "+ff.getFileSize());
     System.out.println("[File Info]");
     System.out.println(new String(ff.getFileData()));
     */
     is.close();
     os.close();
 }
 
 /*리스트 부분*/
 public ActionForward list(ActionMapping mapping,
         ActionForm form,
         HttpServletRequest request,
         HttpServletResponse response)
         throws Exception{
  
  request.setAttribute("list", new UploadDAO().list());
  
  return mapping.findForward("list");
 }
 
 protected String getWdate(){
  return new java.text.SimpleDateFormat("yyyy-MM-dd").format(new java.util.Date());
 }
}


'FrameWork > Struts1' 카테고리의 다른 글

struts1 커스터마이징하여 사용하기.  (0) 2009.11.11
Struts1 FileDownload  (0) 2009.08.18
Struts1의 Action 4  (0) 2009.08.16
Struts1의 Action 3  (0) 2009.08.16
Struts1의 Action 2  (0) 2009.08.12
Struts1의 Action 1  (0) 2009.07.27
Struts1에서 ActionForm 사용하기.  (0) 2009.07.25
Struts1 에서 iBatis 사용하기  (0) 2009.07.05
Struts 1 을 사용하여 간단한 회원가입, 리스트 불러오기.  (0) 2009.07.05
Struts1 개발환경 설정.  (0) 2009.07.05

■ SwitchAction

 Context 내에 여러 개의 모듈이 있을 때  현재 작업중인 모듈에서 다른 모듈로 전환하고 새로운 모듈내의 포워드 하는 일을 수행
.


일반적인 그룹핑은 web.xml 안에서 설정해 놓은 xml 파일들을 아래와 같이 추가하여 사용한다.

  <!-- groupping module -->
 <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>  <!-- /WEB-INF/(기본베이스 - 다른폴더일때는 경로를 설정해주어야 함)폴더 안에 struts-config.xml파일 위치 지정  - 여기까지 작성후 struts-config.xml파일을 생성 -->
 </init-param>

그러나 SwitchAction을 사용하면 아래와 같이 모듈별로 설정을 할 수 있다.

<!-- 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>
  <init-param>
   <param-name>config/validatorModule</param-name>
   <param-value>/WEB-INF/config/struts-validatorModule.xml</param-value>
  </init-param>
   <init-param>
   <param-name>config/tilesModule</param-name>
   <param-value>/WEB-INF/config/struts-tilesModule.xml</param-value>
  </init-param>

web.xml 에 위와 같이 설정을 해주고 각각의 모듈별 xml을 만든다.

위에 보이는 경로대로

/WEB-INF/config/ 폴더 안에 각각의 모듈 xml 파일을 만든다. 여기서 중요한것은 

<init-param>
   <param-name>config</param-name>
   <param-value>/WEB-INF/config/struts-config.xml</param-value>
  </init-param>

config 가 기본적으로 있어야한다.


그림에서 같이 WEB-INF에(SwitchAction을 사용하지 않은 경우) 있는 xml 파일들이 config 폴더에 모듈별로 들어가 있는 것을 볼 수 있다.

그리고 config 폴더 안에 있는 모든 xml 파일 안에는 아래와 같은 설정이 있어야 한다.

<!-- switchAction을 사용할때는 모든 config파일에 SwitchAction설정이 되어있어야 한다. -->
     <action path="/toModule"
                type="org.apache.struts.actions.SwitchAction"/>

- strus-dispatchModule.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>

    <!-- Form Bean Definitions -->
    <form-beans>
     <form-bean name="infoBean" type="com.myhome.info.beans.InfoFormBean"/>
    </form-beans>

 <!-- Global Exception Definitions -->
 <global-exceptions>
 </global-exceptions>
 
 <!-- Global Forward Definitions -->
 <global-forwards>
 </global-forwards>
 
    <!-- dispatch action mappings -->
 <action-mappings>
 
    <action path="/toModule"
               type="org.apache.struts.actions.SwitchAction"/>
      
    <action path="/index"
         type="org.apache.struts.actions.ForwardAction"
          parameter="/register.jsp"/>
        
    <action path="/dispatchModule"
            name="infoBean"
          scope="request"
          parameter="method"
          unknown="true"
          type="com.myhome.dispatch.InfoDispatchAction">
       <forward name="result"  path="/result.jsp"/>
       <forward name="list"    path="/list.jsp"/>
       <forward name="query"   path="/modify.jsp"/>
       <forward name="update"  path="/template.jsp"/>
       <forward name="delete"  path="/template.jsp"/>
    </action>       
    </action-mappings>
   
 <!-- Controller Processor Definition --> 
 <controller processorClass="com.myhome.info.processor.InfoRequestProcessor"/>

 <!-- Message Resources Definitions -->
 
 <!-- Plug Ins Configuration -->
 <!-- Tiles plugin -->
 <!-- Validator plugin -->
 
</struts-config>


모듈을 변경하는 방법은 URI가 아래와 같다면

http://localhost:8080/toModule.do?prefix=/moduleB&page=/index.do

prefix 가 어느 모듈을 사용하는지를 결정하고, page가 그 모듈에서 어떤 액션을 사용할지를 결정한다.

- jsp 페이지에서 prefix와 page로 파라미터를 전송한다.

<script type="text/javascript">
    function module(prefix, page){
          document.indexform.prefix.value=prefix;
          document.indexform.page.value=page;
          document.indexform.submit();
    }      
 </script> 

<form method="POST" name="indexform" action="toModule.do">
    <input type="hidden" name="prefix">
    <input type="hidden" name="page">  

이렇게 설정을 하고 사용할 모듈과 액션을 보내주면 그에 맞는 모듈이 실행된다.

'FrameWork > Struts1' 카테고리의 다른 글

struts1 커스터마이징하여 사용하기.  (0) 2009.11.11
Struts1 FileDownload  (0) 2009.08.18
Struts1 fileUpload  (0) 2009.08.18
Struts1의 Action 3  (0) 2009.08.16
Struts1의 Action 2  (0) 2009.08.12
Struts1의 Action 1  (0) 2009.07.27
Struts1에서 ActionForm 사용하기.  (0) 2009.07.25
Struts1 에서 iBatis 사용하기  (0) 2009.07.05
Struts 1 을 사용하여 간단한 회원가입, 리스트 불러오기.  (0) 2009.07.05
Struts1 개발환경 설정.  (0) 2009.07.05



 LookupDispatchAction은 getKeyMethodMap() 메서드를 구현하고 리소스 번들의 키와 메소드명을 매핑한다.
파라미터로 메소드 이름을 전달하면 그와 같은 메소드 명을 찾아서 실행하는 것이다.
 HTML 폼에서 동일한 이름을 가진 여러 개의 버튼을 사용하는 경우에 유용하다. 이 버튼의 이름은 해당하는 ActionMapping의 매개 변수 속성에 의해 지정된다.

작업 순서

1) mapping 할 메시지번들을 생성한다.
2) LookupDispatchAction을 상속받는 Class를 만들고 getKeyMethodMap() 메소들를 Override한다.
3) struts-config-lookup.xml 파일을 작성한다.
4) web.xml 파일에 struts-config-lookup.xml 파일 설정을 추가한다.

1. mapping 할 메시지 번들 파일(.properties)를 만든다.

메모장에 아래와 같이 추가하고 InfoMessageResource.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

이 파일을 이클립스 안으로 복사해서 붙여 넣는다.(이클리스 안에서 properties 파일을 오류를 발생하기 때문이 이렇게 한다.)

그리고 이 파일을 이클립스에서 열을 경우 한글이 깨져서 나오는것을 알 수 있다. 이 문제를 해결하기 위해서 인코딩 타입을 euc-kr로 파일을 native2ascii 변환하는 작업을 해주어야 한다.

변화작업은 다음 글을 참조한다.
http://thinkingblog.tistory.com/14

InfoMessageResource.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

2. InfoLookupDispatchAction.java 파일 작성.

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());
 }

}

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">
<!-- method 라는 value를 받아서 type에 선언된 클래스로 이동하고 getKeyMethodMap() 메소드를 통해서 InfoMessageResource.properites 파일안에 맵핑 되는 메소드를 실행하게 된다.-->
   
   <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>

4. web.xml 에 struts-config-lookup.xml 파일을 추가한다.

<init-param>
 <param-name>config</param-name> 
 <param-value>
 
  /WEB-INF/struts-config-lookup.xml 
</param-value>   /WEB-INF/(기본베이스 - 다른폴더일때는 경로를 설정해주어야 함)폴더 안에 struts-config.xml파일 위치 지정  - 여기까지 작성후 struts-config.xml파일을 생성-->
</init-param>

5. jsp 파일에서 값을 넘겨 줄때

 <form method="POST" name="listform" action="lookup.do">
     <input type="hidden" name="method" value="쿼리">

lookup.query = 쿼리

InfoMessageResource_ko.properties  파일에서 한글로 설정 쿼리 부분과 일치하고, 그 일치한 메소드를 실행한다.

자세한 내용은 파일을 참조 한다.





'FrameWork > Struts1' 카테고리의 다른 글

struts1 커스터마이징하여 사용하기.  (0) 2009.11.11
Struts1 FileDownload  (0) 2009.08.18
Struts1 fileUpload  (0) 2009.08.18
Struts1의 Action 4  (0) 2009.08.16
Struts1의 Action 2  (0) 2009.08.12
Struts1의 Action 1  (0) 2009.07.27
Struts1에서 ActionForm 사용하기.  (0) 2009.07.25
Struts1 에서 iBatis 사용하기  (0) 2009.07.05
Struts 1 을 사용하여 간단한 회원가입, 리스트 불러오기.  (0) 2009.07.05
Struts1 개발환경 설정.  (0) 2009.07.05
■ Static Parameters Interceptor


클라이언트가 보내는 파라미터를 무시하고 미리 설정해 놓은 파라미터로 값을 넣는다.

struts.xml
에 정의된 파라미터 값들을 액션에저장한다. <action> 태그 의 직속 자식으로<param> 태그가 있다.


- xml 파일에 아래와 같이 태그를 추가한다.

 <param name="name">홍길동</param>
          <interceptor-ref name="staticParams"/>

- action class 에서

param 네임으로 getter, setter를 생성한다.

■ 
Timer Interceptor


인터셉터와
처리를 포함하여 액션의 작업 처리 시간을 출력한다.


- xml 파일 안에 아래와 같이 추가

 <interceptor-ref name="timer"/>  <!-- 작업시간에 대한 결과를 출력한다. -->

이렇게 추가해 주고 실행하면 작업 시간이 콘솔 창이 나타난다.

■ MappingDispatchAction

 하나의 Action에서 두개 이상의 ActionMapping를 구현할 때 사용된다. DispatchAction 은 하나의 parameter에 실행할 메소드를 넣는 방식에다가 하나의 액션네임에 하나의 ActionClass를 사용한다. 그러나 MappingDispatchAction은 여러개의 액션네임에 하나의 ActionClass를 사용한다.



- DispatchAction과 <action-mappings> 부분이 다르다.

    <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"> <!-- parameter 는 Class의 Method이름이다 -->
            <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>


자세한 내용은 파일 참조




'FrameWork > Struts1' 카테고리의 다른 글

struts1 커스터마이징하여 사용하기.  (0) 2009.11.11
Struts1 FileDownload  (0) 2009.08.18
Struts1 fileUpload  (0) 2009.08.18
Struts1의 Action 4  (0) 2009.08.16
Struts1의 Action 3  (0) 2009.08.16
Struts1의 Action 1  (0) 2009.07.27
Struts1에서 ActionForm 사용하기.  (0) 2009.07.25
Struts1 에서 iBatis 사용하기  (0) 2009.07.05
Struts 1 을 사용하여 간단한 회원가입, 리스트 불러오기.  (0) 2009.07.05
Struts1 개발환경 설정.  (0) 2009.07.05


Struts1의 다양한 Action들


struts-extras-1.3.8.jar에서 지원하며 다양한 액션을 구현 할 수 있다.

■ Action 상속 관계도



1. ForwardAction



 struts-config.xml 의 ActionMapping에서 action 요소에 parameter 속성으로 지정한 URL로 forward 하게 된다. 직접 해당 URL을 호출하면 RequestProcessor을 통해 바로 View page로 이동하지만
ForwardAction을 사용하게 되면 스트럿츠 컨트롤러 서블릿의 기능(폼 빈의 처리 등)을 사용 할 수 있다는 장점이 있다.

<!--직접 해당 URL 호출-->
<action path="/info/index" forward="/info/register.jsp"/>

<!-- ForwardAction을 사용해서 ViewPage요청 -->
<action path="/info/index"
            type=“org.apache.struts.actions.ForwardAction”
            parameter="/info/register.jsp” />


2. IncludeAction.

 

 ForwardAction과 동일한 방식이며 비즈니스 로직에서 처리 후 RequestProcessor로 진입하지 않고 바로 페이지로 이동한다. View page로의 빠른 이동이 가능하다는 장점이 있지만, Request Prcessor를 통과 하지 않기 때문에 page Encoding,validator 등 을 사용할 수 없다.

<!-- IncludeActiond 사용 -->
<action path="/index"
type = "org.apache.struts.actions.IncludeAction"
parameter = "/info/register.jsp"/>

3. DispatchAction

 하나의 Action에서 두개 이상의 ActionForward를 구현할 때 사용된다.


 JSP form 페이지에서 name이 struts-config.xml 에서 설정해논 parameter의 이름과 일치해야 실행된다.

- struts-config.xml

.... 생략 ....

    <action-mappings>
   
   <action path = "/dispatchIndex"
    type = "org.apache.struts.actions.ForwardAction"
    parameter = "/dispatch/register.jsp"/>
    
  <!-- unknow 은 input 속성을 대체하기 위한 속성이다. 입력 폼이 여러개 발생할 때 사용된다.  -->
  <action path = "/dispatch"
    name = "bean"
    scope = "request"
    unknown = "true"
    parameter = "method"
    type = "com.myhome.dispatch.InfoDispatchAction">
    
<!-- forward 이름이 메소드 마다 달라야 한다 -->
   <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>

.... 생략 ....

- InfoDispatchAction .java

//하나의 Action에서 여러개의 action을 구현했다.

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.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());
 }
 
}


자세한 내용은 파일을 참조한다.





'FrameWork > Struts1' 카테고리의 다른 글

Struts1 FileDownload  (0) 2009.08.18
Struts1 fileUpload  (0) 2009.08.18
Struts1의 Action 4  (0) 2009.08.16
Struts1의 Action 3  (0) 2009.08.16
Struts1의 Action 2  (0) 2009.08.12
Struts1에서 ActionForm 사용하기.  (0) 2009.07.25
Struts1 에서 iBatis 사용하기  (0) 2009.07.05
Struts 1 을 사용하여 간단한 회원가입, 리스트 불러오기.  (0) 2009.07.05
Struts1 개발환경 설정.  (0) 2009.07.05
Struts(스트럿츠) 란?  (0) 2009.06.27
http://thinkingblog.tistory.com/4
에서 update와 delete를 추가하면서 설명. Struts1.war 파일에 추가 됨.



1. InfoFormBean.java 에서 ActionForm을 상속 받는다.

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;

...... 생략 ......

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

<!-- Form Bean Definitions -->
<!-- form으로 들어오는 데이터를 bean객체에 담는다 -->

    <form-beans> 
        <form-bean
            name="bean"  
            type="com.myhome.info.beans.InfoFormBean"/>  <!-- name은 아무거나 하고 type는 담을 object 객체를 써준다.(전달된 파라미터 데이터가 설정된 빈 으로 저장이 된다) -->
       
        <!--
         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>

3. struts-config.xml 에서 <action-mapping> 설정한다.

 <!--
         [action Attributes]
         path = "request 경로"
         name = "폼정보를 받아 줄 빈 클래스 이름" - form-bean에 정의 된 이름
         scope = "request|session|application" - 다음의 영역으로 들어오는 정보
         input = "/info/modify.jsp" - 입력받은 폼 페이지 명 명시
                                             - 정의된 곳에서 들어오는 데이터를 사용하겠다.
         
         forward 부분에서 path만 잡아 주면 주소창은 변하지 않고 페이지만 변경 시킨다.
         그래서 redirect를 true를 설정하면 주소 까지 바뀌어 버린다.
         -->


        <!-- 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>
        
        <!-- 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>
  
  <!--
   path - 다음과 같은 url패턴으로 들어왔을때
   type - 다음에 실행 될  액션을 설정한다.
   forward - 다음페이지로 이동되어질 곳을 정한다.
   -->


4. Action Class 에서 설정.

//ActionForm을 상속한 경우
public class InfoUpdateAction extends Action{

 @Override
 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");
 }
 
}

//DynaActionForm을 사용한 경우
public class InfoDeleteAction extends Action {

 @Override
 public ActionForward execute(ActionMapping mapping,
         ActionForm form,
         HttpServletRequest request,
         HttpServletResponse response)
         throws Exception {
  
  DynaActionForm dyna = (DynaActionForm)form;
  InfoDTO dto = new InfoDTO();
  dto.setNum((Integer)dyna.get("num"));
  new InfoDAO().delete(dto);
  return mapping.findForward("success");
 }
 
}

5. InfoDAO.java, SqlMap.xml에 update, delete 추가.

6. jsp 페이지 수정.


자세한 내용은 war 파일을 참조 한다.

'FrameWork > Struts1' 카테고리의 다른 글

Struts1 FileDownload  (0) 2009.08.18
Struts1 fileUpload  (0) 2009.08.18
Struts1의 Action 4  (0) 2009.08.16
Struts1의 Action 3  (0) 2009.08.16
Struts1의 Action 2  (0) 2009.08.12
Struts1의 Action 1  (0) 2009.07.27
Struts1 에서 iBatis 사용하기  (0) 2009.07.05
Struts 1 을 사용하여 간단한 회원가입, 리스트 불러오기.  (0) 2009.07.05
Struts1 개발환경 설정.  (0) 2009.07.05
Struts(스트럿츠) 란?  (0) 2009.06.27

 spring의 장점 중하나는 다양한 데이타베이스 모델에 대한 자체적인 api를 가지고 있다는 것이다. 하나의 프레임워크 만을 사용하면 확장성에 문제가 있기 때문에 필요에 따라 다양한 프레임워크를 사용한다.



■ spring library 다운 받기.

 http://www.springsource.org/  에서 다운로드로 이동 후 Spring Framework 2.5.6.SEC01 is the current production release (requires Java 1.4+) 아래 Download 를 클릭 한다. 페이지 이동 후 Download Now를 클릭한다.
 페이지 이동 후에 More를 클릭하여 2.5.6 을 클릭하면 spring-framework-2.5.6-with-dependencies.zip spring-framework-2.5.6-with-docs.zip 파일을 다운로드 한다. (개인 정보를 입력하는 부분이 나오면 대충 입력해도 된다.)


 다운로드 받은 파일을 압축을 해제하고 spring-framework-2.5.6-with-dependencies\dist(여기가 spring의 핵심 부분) 으로 간다. dist 폴더에 보이는 spring library 파일을 프로젝트의 lib 폴더에 추가한다.
 다시 spring-framework-2.5.6-with-dependencies\dist\modules 폴더로 이동해서 spring-aop, spring-beans, spring-core, spring-jdbc, spring-orm, spring-tx, spring-web, spring-webmvc, spring-webmvc-struts 라이브러리 파일을 추가한다.
 마지막으로 spring-framework-2.5.6-with-dependencies\lib\log4j 폴더에서 log4j-1.2.15 라이브러리를 추가한다.

 그리고 Struts2 library에서 struts-2.0.14\lib 폴더에 있는 struts2-spring-plugin-2.0.14 라이브러리를 추가 한다.(Strust1에서는 Spring으로 가는 플러그인이 없다)

■ applicationContext.xml 을 만들어서 작업을 진행하는 동안 계속 추가해 난간다.

작업 내용이 추가된 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:tx="http://www.springframework.org/schema/tx"
 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-2.5.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
      
 
  <!-- DataSource JDBC type -->
  <bean id="dataSource"
        class="org.apache.commons.dbcp.BasicDataSource"
        p:driverClassName="oracle.jdbc.driver.OracleDriver"
        p:url="jdbc:oracle:thin:@localhost:1521:XE"
        p:username="user01"
        p:password="user01" />
 
  <!-- iBatis SQL-Map config -->
  <bean id="sqlMapClient" <!-- 아이디는 임으로 지어낸다 -->
        class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"
        p:dataSource-ref="dataSource" <!-- dataSource 참조 -->
        p:configLocation="classpath:SqlMapConfig.xml" /> <!-- default 경로는 scr 이고, src 하위 아무 디렉토리나 참조하기 위해서는 classpath를 써주는게 좋다 --<
  
  <bean id="template"
        class="org.springframework.orm.ibatis.SqlMapClientTemplate"
        p:sqlMapClient-ref="sqlMapClient"/>
       
  <bean id="scheduleDao"
    class="com.myhome.schedule.model.ScheduleDAOImpl"
    p:template-ref="template"/> <!-- p는 property다.-->
    <!-- <property name="template" ref="template"/> 이렇게 써도 된다. 같은 방법  bean id="template"가 p:template-ref="template"의 template다 -->
                 
  <bean id="service"
        class="com.myhome.service.ScheduleServiceImpl"
        p:scheduleDao-ref="scheduleDao"/>
    
  <bean id="dto" class="com.myhome.schedule.model.ScheduleDTO"/>
 
   <bean id="scheduleModel"
        class="com.myhome.schedule.api.ScheduleModel"/>    
</beans>

※ DB와 연동하기 위해 여기서는 SqlMapClientTemplate 을 사용하는데 bean 주입을 이용한다. iBatis에서 SqlMapConfig.xml 트랜잭션을 정의한 부분이 applicationContext.xml으로 온다. 
 
 SqlMapConfig.xml을 참조하고 있는 bean이 필요한데, 이런 객체들을 컨테이너가 가지고 있다가 서비스를 한다. 

<bean id="sqlMapClient
        class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"
        p:dataSource-ref="dataSource
        p:configLocation="classpath:SqlMapConfig.xml" /> 

 이 부분에서 SqlMapConfig.xml 을 id가 참조하도록 지시한다. 이게 바로 bean 주입 방식이다. 개발자가 객체를 만들지 않고 bena에서 id만 정의 해주면 컨테이너가 이 객체를 다 가지고 있다. 그리고 컨테이너에 의해서 객체 서비스가 이루어 진다.

 그리고(예를 들어) DAOImpl Class 에서 

/*setter injection*/
 private SqlMapClientTemplate template; //이게 bean 주입 방식 으로, applicationContext.xml(빈설정문서 프로퍼티가 동일해야 된다)를 로딩해서 이 template 객체를 만들어 준다.
 public void setTemplate(SqlMapClientTemplate template){
  this.template = template;
 }

이런 식으로 사용한다. 이렇게 다른 곳에서 객체가 필요할 때도 이런 방법으로 만들어 낸다.
 
■ struts.properties

# struts2 + spring Factory
   struts.objectFactory=org.apache.struts2.spring.StrutsSpringObjectFactory
//applicationContext.xml을 가지고 있는게 factory다. 여기서 스트럿츠가 스프링으로 간다는 것을 알려주고 연결한다. objectFactory를 설정해 주면 applicationContext를 이 factory가 갖게 된다. DI를 할 때, 인위적으로 applicationContext를 로드해서 리소스를 읽어 id를 참조해서 만들지 않는다. 
   struts.objectFactory.spring.autoWire=type // applicationContext.xml에 들어있는 각각의 bean 들을 설정하는데 그 bean은 autoWire 라는 뜻으로 우리가 설정하는 타입데로 알아서 처리하라는 뜻.

(이 때 factory를 적용하기 위해서는 struts가 spring으로 간다는 것을 알려주어야 하는데 이때 필요한 library가 struts2-spring-plugin-2.0.14 이다.)

이 두줄을 struts.properties 에 추가한다. 


■ web.xml

<!-- spring scope (context parameter) -->

<!-- applicationContext.xml을 로딩하는 역할을 한다. -->

  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/applicationContext.xml</param-value> 
  </context-param>

  <listener>
     <listener-class>
        org.springframework.web.context.ContextLoaderListener
     </listener-class>
  </listener>
 
  <!-- spring scope ended -->

이 부분 까지 Strut2 + Spring + iBatis 연결 설정 부분에 대한 간략한 설명이다.

Spring에서 Simpleformbankingobject

JSP에서 데이타를 입력해서 보여주는게 아니라. Action에서 데이터를 제공해 주는 것으로 데이타를 보호 할 수 있다.

- IndexAction.java

package person.actions;

import java.util.List;
import java.util.ArrayList;
import com.opensymphony.xwork2.ActionSupport;

@SuppressWarnings("serial")
public class IndexAction extends ActionSupport {
 
 private List<String> list;
 
 @Override
 public String execute()throws Exception {
  list = new ArrayList<String>();
  list.add("서울");
  list.add("부산");
  list.add("대구");
  list.add("대전");
  list.add("광주");
  list.add("인천");
  list.add("울산");
  return SUCCESS;
 }
 
 public List<String> getList(){
  return list;
 }

}

* list에있는 서울, 부산, 대구, 대전, 광주, 인천, 울산 데이터를 JSP 페이지에 보여줄 것이다.

- write.jsp

<%@ page language="java"
         contentType="text/html; charset=EUC-KR"
         pageEncoding="EUC-KR"%>
<%@ taglib prefix="s" uri="/struts-tags"%>        
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "
http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>struts2::interceptor</title>
<style type="text/css">
     td {font-size: 11pt; text-decoration: none; color: #000000}
    </style>
</head>
<body>
  <center>
    <br /><br />
    <h3><b>struts2 interceptor(checkbox)</b></h3>
    <form method="post" name="myform" action="write.action">
      <table border=0 cellpadding=0 cellspacing=1
             bgcolor="#000000">
        <tr height=30 bgcolor="#ffffff">
          <td bgcolor="#f0f0f0" width=100 align="center">성명</td>
          <td width=300 align="left">&nbsp;
            <input type="text" name="name">
          </td>
        </tr>    
        <tr height=30 bgcolor="#ffffff">
          <td bgcolor="#f0f0f0" width=100 align="center">이메일</td>
          <td width=300 align="left">&nbsp;
            <input type="text" name="email">
          </td>
        </tr> 
        <tr height=30 bgcolor="#ffffff">
          <td bgcolor="#f0f0f0" width=100 align="center">주소</td>
          <td width=300 align="left">&nbsp;
            <select name="addr">
              <s:iterator value="list">
                <option value="<s:property />">
                  <s:property/>
                </option>
              </s:iterator>
            </select>
          </td>
        </tr> 
        <tr height=30 bgcolor="#ffffff">
          <td bgcolor="#f0f0f0" width=100 align="center">취미</td>
          <td width=300 align="left">&nbsp;
            <input type="checkbox" name="travel" value="여행" checked>여행
            <input type="checkbox" name="climbing" value="등산" >등산
            <input type="checkbox" name="game" value="게임">게임
          </td>
        </tr>
        <tr height=30 bgcolor="#ffffff">
          <td bgcolor="#f0f0f0" width=100 align="center">성별</td>
          <td width=300 align="left">&nbsp;
            <input type="radio" name="sex" value="남" checked>남
            <input type="radio" name="sex" value="여">여
          </td>
        </tr>
        <tr height=30 bgcolor="#f0f0f0">
          <td align="right" colspan=2>
            <input type="submit" value="등록...">&nbsp;
          </td>
        </tr>
      </table>       
    </form>
  </center>
</body>
</html>

* 아래 부분에서 IndexAction.java 의 리스트 부분의 데이타를 보여 줄 수 있다.

<select name="addr">
    <s:iterator value="list">
           <option value="<s:property />">
              <s:property/>
           </option>
      </s:iterator>
 </select>

■ Interceptor의 종류



■ Checkbox Interceptor, Parameters Interceptor.

체크되지 않는 값을 다 막아내고 그 값을 출력하더라고 비어있기 때문에 빼버린다.

- checkbox.xml

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

<!DOCTYPE struts PUBLIC
   "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
   "
http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
   <package name="interCheckbox" namespace="/checkbox" extends="struts-default">
   <!-- 자신이 만든 interceptor은 action 밖에서 사용하고, 존재하는 interceptor의 사용은 action에서 사용한다 -->
   
      <action name="index"
              class="person.actions.IndexAction">
        <result>/person/write.jsp</result>
      </action>
   
      <action name="write"
              class="person.actions.WriteAction">
         
          <param name="name">홍길동</param>
          <interceptor-ref name="staticParams"/> <!-- param을 가질 수 없기 때문에 위로 뺀다. -->
                          
<!-- Checkbox Interceptor 부분 -->
             <interceptor-ref name="checkbox">
              <param name="uncheckedValue">false</param>
<!-- uncheckedValue 예약어다. 체크하지 않은 값은 오지 않는다.-->            
             </interceptor-ref>
             <interceptor-ref name="prepare"/> <!--세개를 써주는게 좋다. default라서 안써도 되지만.-->
             <interceptor-ref name="modelDriven"/>
             <interceptor-ref name="params"/>
         <result>/person/result.jsp</result>
      </action>
     
   </package>

- WriteAction.java

package person.actions;

import person.model.PersonVO;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.Preparable;
import com.opensymphony.xwork2.ModelDriven;
import com.opensymphony.xwork2.interceptor.ParameterNameAware; //특정 파라메터의 값을 받지 않을 경우
import com.opensymphony.xwork2.interceptor.NoParameters; //Interface NoParameters클라이언트가 보내주는 파라미터를 다 차단하겠다.

@SuppressWarnings("unchecked")
public class WriteAction implements Action,
         Preparable,
         ModelDriven,
         ParameterNameAware //Parameters Interceptor 부분 : 특정 파라미터를 안받을 경우
         //NoParameters //Parameters Interceptor 부분 : 모든 파라미터를 안받을 경우
         {
 private String name;
 private PersonVO vo;
 
 //비즈니스 로직 수행 부분
 @Override
 public String execute()throws Exception { //Ation은 execute 메소드를 가지고 있다
  //business logic
  return SUCCESS;
 }
 
 //폼 요청이 들어오면 파라메터의 값을 받기 위해 객체를 생성하고, 각 파라메터의 값을 프로퍼티에 저장한다.
 @Override
 public void prepare() { //preparable, 객체의 초기와 생성
  vo = new PersonVO();
    }

 //execute 메소드를 수행하고 결과를 Result로 전달하는 부분
 @Override
    public Object getModel() { //ModelDriven 데이타를 result로 객체를 넘기는 역할
  return vo;
    }

 //특정 파라메터를 받지 않기 위해 설정한다.
// @Override
 public boolean acceptableParameterName(String parameterName) {
  
  if("name".equals(parameterName)){ //name과 같은 property가 넘어오면 값을 받지 않겠다.
   return false;
  }

  
  return true;
 }

 public String getName() {
  return name;
 }

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

}

- 결과 보기

테이터를 입력 한다.


ParameterNameAware 을 사용하여 name 을 받지 않은 경우.


NoParameters 를 사용하여 모든 데이터를 받지 않은 경우.


■ Exception Interceptor.

- upload.xml

 exception 에는 알 수없는 action에서 error가 발생했을 때 잡는 global exception과, 특정 action에서 error가 발생했을 잡아주는 local Interceptor exception이 있다.

<?xml version="1.0" encoding="euc-kr"?>
<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
        "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>

    <package name="upload" namespace="/upload" extends="struts-default">
     
  <!-- 알 수 없는 action에서 error가 발생 했을 경우 global exception을 발생한다. -->
     <!-- global exception은 action 위에서 는다. -->

    <global-results>
          <result name="exception">/exception/exception.jsp</result>
    </global-results>
     
     <global-exception-mappings> <!-- 여기서 exception이 발생하면 result name의 exception을 요구하고 위의 name 이 exception 인 result 페이지로 이동한다 -->
      <exception-mapping result="exception" exception="java.lang.Exception"/> <!-- exception 잡을 때 최상위를 잡는게 좋다 -->
     </global-exception-mappings>
     
     <action name="index" class="com.myhome.upload.actions.UploadIndexAction">
                  <result>/WEB-INF/upload/register.jsp</result>
     </action>
     
     <action name="register"
       class="com.myhome.upload.actions.UploadMultiAction"
       method="register">

       <!-- local interception exception은 action 안에서 잡는다. -->
      <!-- 특정 액션에서 예외가 발생할 때 인터셉터를 적용한다. -->

      <exception-mapping result="exception" exception="java.lang.NullPointerException"/> <!-- 여기서는 직접 구현한 익셉션을 사용하는게 좋다 -->
      
       <result name="success" type="dispatcher">/WEB-INF/upload/result.jsp</result>
      <result name="input" type="dispatcher">/WEB-INF/upload/register.jsp</result>
      <result name="error" type="dispatcher">/WEB-INF/upload/register.jsp</result>
      <result name="exception">/exception/exception.jsp</result>
     </action>

... 생략 ...

* UploadMultiAction 에 설정해 놓은 NullPointerException 이 발생 할 경우 result name이 exception인 곳으로 데이터를 보내고 exception.jsp에서는 <s:actionerror/>, <s:actionmessage/>, <s:fielderror/>, ${exception.message}, ${exceptionStack} 이런 식으로 데이타를 보여준다.

- exception.jsp

<%@ page contentType="text/html; charset=EUC-KR"%>
<%@ taglib prefix="s" uri="/struts-tags" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
  <head>
 <meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
 <title>exception page</title>
  </head>
 
  <body>
 <h2>예기치 않는 오류 발생</h2>
    <p>
              현재 많은 접속자로 인해  시스템의 과부하가 발생하였습니다.
             잠시 후 다시 접속을 시도해 주십시오.
    </p>
    <p>        
             문의사항이 있으시면 admin@myhome.com으로 메일을 보내주십시오.              
    </p>
    <hr/>
     <h3>에러 메시지</h3>
      <s:actionerror/> <!-- action에서 알 수 없는 error 가 걸렸을 때 보기위해 찍는다. -->
      <s:actionmessage/>
      <s:fielderror/>
      <p>
       ${exception.message}
      </p>
    <hr/>
    <h3>에외 상세정보</h3>
    <p>
      ${exceptionStack}
    </p>
 </body>
</html>

- action class

 action class 안에서 다음과 같이 error message 를 추가 할 수 있다.

/*exception handle*/
this.addActionMessage(bean.getName() + " 님이 파일 오류를 발생하였음"); //이렇게 에러 메세지 추가가 가능하다.
throw new NullPointerException("파일을 올려주셈~~");

■ Servlet Config Interceptor


 HtteServletRequest와 HttpServletResponse를 다루는 맵을 엑세스할 수 있게 한다. 

 Servlet-Config Interceptor는 액션들의 Servlet API에서 다양한 객체들을 주입하는 좋은 방법을 제공한다. Struts2는 Servlet API를 제공하지 않기 때문에 servlet 객체에 접근하기 위해 Map을 사용한다. Map의 종류로는 

 ServletContextAware  : ServletContext 객체를 받을 수 있다.

 ServletRequestAware  : HttpServeltRequest 객체를 받을 수 있다.

 ServletResponseAware : HttpServeltResponse 객체를 받을 수 있다.

 ParameterAware       : Parameter Map을 받을 수 있다.

 RequestAware         : Request Map을 받을 수 있다.

 SessionAware         : Session Map을 받을 수 있다.

 ApplicationAware     : Application Map을 받을 수 있다.

맵을 받기 위해서는 각각의 Aware 인터페이스를 구현해야 한다.


- LoginAction.java


package servletConfig.action;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;

import org.apache.struts2.interceptor.RequestAware;

import org.apache.struts2.interceptor.ServletRequestAware;

import org.apache.struts2.interceptor.SessionAware;

import servletConfig.dao.LoginDAO;

import servletConfig.interceptor.LoginDAOAware;

import servletConfig.model.UserInfo;

import com.opensymphony.xwork2.Action;

import com.opensymphony.xwork2.ModelDriven;

import com.opensymphony.xwork2.Preparable;


public class LoginAction implements Action, 

                     Preparable, 

     ModelDriven, 

     LoginDAOAware, 

     SessionAware, 

     ServletRequestAware, 

     RequestAware {


    //도메인 오브젝트

    UserInfo userInfo;

    LoginDAO dao;

    Map sessionMap;

    Map requestMap;

    HttpServletRequest request;

    Log log = LogFactory.getLog(LoginAction.class);


    public String execute() throws Exception {

     if (dao.loginChk(userInfo)) {

           sessionMap.put("userInfo", userInfo);

           log.info("----> requestURI : " + request.getRequestURI());

           log.info("----> request ID : " + requestMap.get("id").toString());

           log.info("----> request PWD : " + requestMap.get("pwd").toString());

           return SUCCESS;

        } else {

           return LOGIN;

        }

    }

    

    //Preparable인터페이스의 prepare 구현

    public void prepare() throws Exception {

        userInfo = new UserInfo();

    }

           

    //ModelDriven 인터페이스의 getModel 구현

    public Object getModel() {

        return userInfo;

    }


    //LoginDAUInterceptor에서 LoginDAO를 주입한다.

    public void setLoginDAO(LoginDAO loginDAO) {

        this.dao = loginDAO;

    }


    //SessionAware의 setSession 구현

    public void setSession(Map session) {

        this.sessionMap = session;

    }


    //RequestAware의 setRequest 구현

    public void setRequest(Map requestMap) {

        this.requestMap = requestMap;

    }


    //ServletRequestAware의 serServletRequest 구현

    public void setServletRequest(HttpServletRequest request) {

        this.request = request;

    }


}


- interServletConfig.xml

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

<!DOCTYPE struts PUBLIC

    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"

    "http://struts.apache.org/dtds/struts-2.0.dtd">

    

<struts>

<package name="interServlet" namespace="/login" extends="struts-default">

<!-- <interceptors>는 자신이 만든 interceptor를 사용하기 위해 정의하는 부분이다. -->

<!-- 더 필요한 정보가 없을 경우 <interceptor-ref name="servletConfig"/> 만 써도 된다. -->

<interceptors>

<interceptor name="loginDao" class="servletConfig.interceptor.LoginDAOInterceptor"/>

</interceptors>

<action name="login" class="servletConfig.action.LoginAction">

<interceptor-ref name="prepare"/>

<interceptor-ref name="modelDriven"/>

<interceptor-ref name="params"/>

<interceptor-ref name="loginDao"/>

<interceptor-ref name="servletConfig"/>

<result>/login/logout.jsp</result>

<result name="login">/login/login.jsp</result>

</action>

<action name="logout" class="servletConfig.action.LogoutAction">

<result>/login/login.jsp</result>

</action>

</package>

</struts>


- LoginDAO.java

package servletConfig.dao;

import servletConfig.model.UserInfo;

public class LoginDAO{

public boolean loginChk(UserInfo userInfo){

//login을 할 때, 아이디를 test로 넣어주어야 홍길동이라는 이름을 보내준다. (test로 넣어주어야 홍길동을 쿼리 해오겠다는 의미)

if("test".equals(userInfo.getId())){

userInfo.setName("홍길동");

return true;

}else{

return false;

}

}

}


- LoginDAOAware.java

package servletConfig.interceptor;

import servletConfig.dao.LoginDAO;

public interface LoginDAOAware{

public void setLoginDAO(LoginDAO loginDAO);

}


- LoginDAOInterceptor.java


package servletConfig.interceptor;

import servletConfig.dao.LoginDAO;

import com.opensymphony.xwork2.ActionInvocation;

import com.opensymphony.xwork2.interceptor.Interceptor;


@SuppressWarnings("serial")

public class LoginDAOInterceptor implements Interceptor{

LoginDAO loginDAO;

//인터셉터는 라이프 사이클을 가지고 있다.

@Override

public void init() {

loginDAO = new LoginDAO(); //객체 생성

}

@Override

public void destroy() {

loginDAO = null; //객체 소멸

}


//로그인을 셋팅 해주는 과정

@Override

public String intercept(ActionInvocation invocation) throws Exception {

               Object action = invocation.getAction(); //오브젝트로 액션을 얻어 온다.

if(action instanceof LoginDAOAware){ //instanceof는 이게 어느 클래스의 인스턴스인지를 물어볼때 쓰는 키워드이다.

LoginDAOAware loginDAOAware = (LoginDAOAware)action;

loginDAOAware.setLoginDAO(loginDAO);

}

//System.out.println("***************" + invocation.invoke()); //성공시 success를 return 한다.

return invocation.invoke();

}

}


- 실행 모습

http://localhost:8989/Struts2_ServletConfigInterceptor/login/login.action 으로 접속한다.



test라는 아이디를 넣고 로그인을 한다.


그러면 홍길동 이라는 이름으로 로그인 한 모습을 볼 수 있다. LoginDAO.java 에서 test라는 아이디로 들어오면 홍길동이라는 이름을 리턴하게 구현하였기 때문이다. 다른 아이디를 입력 하면 로그인이 되지 않을 것이다.



자세한 내용은 파일을 참조 한다.






 Struts2에서 차트 예제를 실행 하기위해서 freemarker-2.3.8.jar와 ognl-2.6.11.jar library가 필요한 합니다.
 무슨 library 인지 알고 써야 할 것 같아 찾아 봤습니다.(왠지 이 모를 궁금함과 찜찜함...^^;)

 freemarker-2.3.8.jar 는 "template engine"으로 템플릿 기반으로 테스트 결과물을 만들어네는 일반적인 툴 이라고 합니다. 템플릿 파일과 자바 객체들이 FreeMarker를 통과하면 텍스트 결과물을 만들어 내는 그림을 볼 수 있습니다. 그리고 Strtus 에서는 Struts 태그의 output을 생성하는데 사용된다고 하네요.


freemarker 사이트 주소는
http://freemarker.org/  입니다. 참고 하세요.

ognl-2.6.11.jar 의 OGNL - Object Graph Navigation Library 의 약자로 Object-Graph Navigation Language의 표준으로, OGNL은 자바 오브젝트의 프로퍼티들을 get, set 하기위한 표현 언어라고 합니다.
OGNL은 Struts2 태그가 속성을 읽고 계산하기 위한 기능을 제공한다고 합니다.

그리고 이것들을 검색하다 특이한 사이트 하나를 찾았습니다. findJAR 이라고 JAR search engine 이라고 하네요. 참고하세요.

 

Tiles에 대한 자세한 내용은

http://tiles.apache.org/

참조 한다.

■ Tiles를 사용하는 이유.

 1. 매 페이지마다 include를 시키게 되면 나중에 그 파일이 변경 됐을 때 문제가 발생한다. 다 뜯어 고쳐야 한다. 그래서 따로 설정문서에다가 include 파일들을 준비해두고 필요시 가져다 쓰라는 것이다. 나중에 페이지 include할 파일 이름이 바뀔 경우 설정문서에서 만 바꿔주면 된다.
 2. 레이아웃을 지원해 준다. 레이아웃패턴을 이용해서 Tiles를 사용할 수 있도록 지원해 준다.

■ Tiles의 진행 순서.



 Action에서 결과를 전달하는데 Result가 tiles로 가라고 알려준다. 그럼 Interceptor에서 Plugin인 web.xml에 정의 되어있는 listener에게 알려준다. 그럼 listener는 현재 tiles.xml을 받아서 Plugin에게 알려준다. 그럼 그 Plugin은 tiles.xml 에 정의 되어 있는 각각의 정의 문서를 통해서 적절할 페이지로 이동시킨다. 그러기 위해서는 web.xml에서 tiles-definitions으로 정의하고 있는 그 문서를 참조하기 위한 event listener를 반드시 정의해줘야 한다.

■ 필요한 library

Struts2 library의 lib 폴더(struts-2.0.14\lib) 에서 아래 네개 파일을 추가한다.

struts2-tiles-plugin-2.0.14, tiles-api-2.0.4, tiles-core-2.0.4, tiles-jsp-2.0.4

■ web.xml

<!-- title plug in listener 리스너를 정의 해준다.-->
 <listener>
  <listener-class>
   org.apache.struts2.tiles.StrutsTilesListener
  </listener-class>
 </listener>

■ tiles.xml(정의문서 : web.xml과 같은 위치에 있다)

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

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

<tiles-definitions>
    <definition name="index" template="/tiles/classicLayout.jsp"> <!-- index를 요구하면 이 페이지로 전달하겠다. -->
        <put-attribute name="title"  value="Struts2 Tiles Example"/> 
        <put-attribute name="menu"   value="/tiles/menu.jsp"/>
        <put-attribute name="header" value="/tiles/header.jsp"/>
        <put-attribute name="body"   value="/tiles/body.jsp"/>
        <put-attribute name="footer" value="/tiles/footer.jsp"/>
    </definition>
   
    <definition name="menu1" extends="index">
        <put-attribute name="body"   value="/tiles/body-menu1.jsp"/> <!-- "/tiles/body.jsp"/ 이 페이지를 /tiles/body-menu1.jsp"/ 페이지로 바꿔라 -->
    </definition>
 
 <definition name="menu2" extends="index">
        <put-attribute name="body"   value="/tiles/body-menu2.jsp"/>
    </definition>
</tiles-definitions>

*  즉 include해야할 파일을 설정 문서에다가 설정해두고 각각의 페이지에서는 그 속성의 이름만을 쓴다.
 
■ classicLayout.jsp

<%@ page contentType="text/html; charset=euc-kr"%>
<%@ taglib prefix="tiles"  uri="http://tiles.apache.org/tags-tiles"%> <!-- 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>

* title, header, menu, body 등의 속성은 tiles.xml(정의문서)에 꼭 정의가 되어있어야 한다.

■ tiles.xml

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

<struts>
    <package name="tiles" namespace="/tiles" extends="struts-default,tiles-default"> <!-- tiles-default이게 정의 되어 있어야 type에서 tiles를 인식한다 -->
        <action name="index">
            <result type="tiles">index</result>
        </action>
        <action name="menu1">
            <result type="tiles">menu1</result>
        </action>
        <action name="menu2">
            <result type="tiles">menu2</result>
        </action>
    </package>
</struts>   

* Client가 index을 요구하면 tiles.xml(정의문서)에서 정의하고 있는 index라고 정의 되어있는 속성 이름을 전달하겠다고 알려준다.

파일 참조



Struts2 에서 Tiles Plugin 사용하기 끝!


Interceptors에 대한 자세한 내용은 struts.apache.org를 참조한다.

http://struts.apache.org/2.0.14/docs/interceptors.html



■ Interceptor의 내부적인 구조를 간단하게 그린 그림이다.

1) preparable : Client로 부터 전달된 모든 데이타 들은 모두 preparable로 들어오며,
    form의 파라미터로 정의 되어있는 그 파라미터의 이름을 통해서 다음 구현할 액션 각각
    의 setter를 정의하고 거기에 있는 객체를 생성, 초기화 해주는 역할을 한다.


2) stack : preparable으로 넘어온 데이타에 대해 렌더링을 수행하고 그 결과를 Action으로 호출한다.

3) Action : execute method 메소드 만을 수행한다.(비즈니스 로직 수행)

4) ModelDriven : 결과를 result로 주는 역할을 담당한다.

 Interceptors 에 대한 간단한 설명.

 

1) 액션 실행 주위로 실행될 수 있는 코드를 인캡슐레이션 할 수 있게 한다.
2) 액션 실행에 투명성을 제공할 수 있는 커맨드 패턴의 추가 서비스이다.
3) 인터페이스는 액션 외부에 정의되고, 런타임 시에 액션과 액션 실행 환경을 엑세스할
    있어
, 관심사
분리와 크로스 커팅 코드를 할 수 있게 해준다
4) 인터셉터는 액션이 호출되기 전과 후에 명령코드를 실행할 수 있다. 대부분의 프레임워크
    핵심 기능들
인터셉터로 구현되어있다.

5) 모든 인터셉터는 플러그인 방식이며, 인터셉터 스택으로 적용될 수 있다.

 인터셉터의
대표적인 기능

    
 타입 변환, 객체 파퓰레이션, 유효성 검사, 파일 업로드, 출력 페이지 준비
등과 같은 기능들은 모두 인터셉터의 도움으로 구현된다.


default interceptor
struts-default.xml에서 정의되어있다.


 Struts2는 Interface기반 이다. Interceptors를 implements 구현하기 위해서는 preparable, action, modeldriven 이 세가지를 꼭 구현해야 한다.

 간단한 소스 보기 : Class에서 적용된 경우

package interceptor1.action;

import interceptor1.dao.SumDAO;
import interceptor1.model.NumberForAdd;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ModelDriven;
import com.opensymphony.xwork2.Preparable;

public class SumAction implements Action, Preparable, ModelDriven { // 3가지만 구현하면 다양하게 구현할 수 있다.

    //도메인 오브젝트
    NumberForAdd num;
    private int sum = 0;

    @Override
    public String execute() throws Exception { // 2단계
        SumDAO dao = new SumDAO();             
        sum = dao.add(num);
        return SUCCESS;
    }

    //Preparable인터페이스의 prepare 구현
    @Override
    public void prepare() throws Exception {
        num = new NumberForAdd(); //1단계 : form에서 넘오는 값들을 property가  같은 곳에다가(stack에서 온) 넣어준다.
    }

    //ModelDriven 인터페이스의 getModel 구현
    @Override
    public Object getModel() { //3단계 리턴
        return num;
    }

    //result.jsp 에서 sum 값을 참조시키기 위해
    public int getSum() {
       return sum;
    }

}

맨 위의 Interceptors가 내부적으로 돌아가는 그림 처럼 1, 2, 3 단계로 수행한다.

 interceptor1.xml 보기 : xml에서 적용될 때.

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

<!DOCTYPE struts PUBLIC
   "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
   "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
   <package name="struts2" extends="struts-default">

<!-- 자신이 만든 interceptor는 action 밖에서 사용하고, 존재하는 interceptor의 사용은 action에서 사용한다 -->      
     <interceptors> <!-- 직접 만든 interceptor -->
        <interceptor name="mytimer" class="interceptor.Timer"/>
      </interceptors> 

      <action name="add" class="interceptor1.action.SumAction">
        <interceptor-ref name="mytimer"/> <!-- 제공되는 interceptor 들-->
        <interceptor-ref name="prepare"/>
        <interceptor-ref name="modelDriven"/>
        <interceptor-ref name="params"/>
        <result>/result.jsp</result>
      </action>
   </package>
</struts>

자세한 내용은 소스 참조. 간단한 예제 포함.


Struts2 Interceptor 1.



■ 파일 삭제 및 업데이트.

1. UploadMultiAction.java

//삭제
public String delete() throws Exception{
  
  dto = new UploadDTO();
  BeanUtils.copyProperties(dto, bean);
  
  if(dto.getFileSize() > 0){
     new File(UploadUtil.SAVE + dto.getFileName()).delete(); //파일 저장위치, 이름만 불러와서 delete를 하면 바로 삭제 된다.
  }
  
  new UploadDAO().delete(dto); //DB 내용 삭제

 return SUCCESS;
 }

//업데이트

public String update() throws Exception{
  
  dto = new UploadDTO();
  
  BeanUtils.copyProperties(dto, bean);
    
  if(this.isState()){
   new File(UploadUtil.SAVE + dto.getFileName()).delete();
   //파일만 삭제 됐을 경우나 파일이 업데이트 됐을경우 파일을 삭제 시켜주고 파일 이름과 사이즈만 초기화 시켜준다.
   dto.setFileName("");    
   dto.setFileSize(0L);
  }
  
  if(bean.getFile() != null){ //파일이 업데이트 됐을 경우 다시 업로드 시켜준다.
   upload();
  }
  
  new UploadDAO().update(dto); //DB를 업데이트 시켜준다.
  
  return SUCCESS;
  
 }

2. modify.jsp

 view 작업이 더 힘든것 같다.-_-;;
체크 박스를 클릭하지 않으면 파일은 변경없이 다른 내용만 변경된다.


체크 박스를 체크하고 업데이트를 할 경우, 새로운 파일을 추가하지 않으면 파일은 삭제된 상태로 업데이트가 되고, 새로운 파일을 올리면 파일이 변경되서 업데이트 된다.


주의 할 점은 name 에 bean.name 과 value 에 dto.name 처럼 써줘야 데이터가 제대로 맵핑된다. 그리고 업데이트 action 부분에 enctype="multipart/form-data"  이 부분을 꼭 써줘야 파일이 업로드 된다.

<%@ page contentType="text/html;charset=euc-kr"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<s:bean id="bean" name="com.myhome.upload.beans.UploadFormBean"/>

<html>
  <head>
    <title>struts2::upload</title>
    <script type="text/javascript">
    function delProc(){
     if(!confirm('개인정보와 파일을 삭제하시겠습니까?')){
      return;
     }
     //document.modifyform.method.value="delete";
     //document.modifyform.action="delete.action";
     //document.modifyform.submit();
     document.delform.submit();
    }

    function fileCheck(){
           var v = document.modifyform;
           if(v.state == null)return;
           var doc = document.getElementById("fileState");
           var fileChk = document.getElementById("fchk"); 

           fileForm = "<br/>&nbsp;&nbsp;<input type='file' name='bean.file'>";

           if(v.state.value == 'false'){
               v.state.value='true';
               fileChk.innerHTML='파일삭제 또는 변경';
               doc.innerHTML = fileForm;
            }else if(v.state.value == 'true'){
             v.state.value='false';
             fileChk.innerHTML='파일유지';
                doc.innerHTML = '';
           }    
        } 
       
   </script>
   <style type="text/css">
     td  {font-size: 10pt;}
    </style>
  </head>

  <body>
    <center><br><br>
    <h3><b>Struts2 Upload_Download(modify,delete)</b></h3>
   
    <form method="post" name="delform" action="delete.action">
     <input type="hidden" name="bean.num" value="${dto.num }">
     <input type="hidden" name="bean.fileName" value="${dto.fileName }">
     <input type="hidden" name="bean.fileSize" value="${dto.fileSize }">
    </form>
   
    <form method="post" name="modifyform" enctype="multipart/form-data" action="update.action">
<!--      <input type="hidden" name="method" value="update">-->
      <input type="hidden" name="bean.num" value="${dto.num}">
      <input type="hidden" name="bean.fileName" value="${dto.fileName}">
      <input type="hidden" name="bean.fileSize" value="${dto.fileSize }">
      <table border=0 cellpadding=0 cellspacing=1 bgcolor="#000000">
       <tr height=30 bgcolor="#ffffff">
         <td width=100 align="right"><b>번호</b>&nbsp;</td>
         <td width=300 align="left">&nbsp;&nbsp;${dto.num}</td>
       </tr>
       <tr height=30 bgcolor="#ffffff">
         <td width=100 align="right"><b>이름</b>&nbsp;</td>
         <td width=300 align="left">&nbsp;
            <input type="text" name="bean.name" value="${dto.name}">
         </td>
       </tr>
    <tr height=30 bgcolor="#ffffff">
   <td width=100 align="right"><b>성별</b>&nbsp;</td>
   <td width=300 align="left">&nbsp;
            <input type="radio" name="bean.sex" value="남" <c:if test="${dto.sex == '남'}">checked</c:if>>남
            <input type="radio" name="bean.sex" value="여" <c:if test="${dto.sex == '여'}">checked</c:if>>여
         </td>
    </tr>     
    <tr height=30 bgcolor="#ffffff">
      <td width=100 align="right"><b>연락처</b>&nbsp;</td>
   <td width=300 align="left">&nbsp;
   <input type="text" name="bean.tel" value="${dto.tel}">
   </td>
    </tr>
    <tr height=30 bgcolor="#ffffff">
      <td width=100 align="right"><b>등록일자</b>&nbsp;</td>
   <td width=300 align="left">&nbsp;&nbsp;${dto.wdate}</td>
    </tr>
    <tr height=30 bgcolor="#ffffff">
      <td width=100 align="right"><b>첨부파일</b>&nbsp;</td>
   <td width=300 align="left">&nbsp;
    <c:if test="${dto.fileSize > 0}">
           ${dto.fileName}
          <span style="font-size:10pt; color:#90a087">
           (<fmt:formatNumber value="${dto.fileSize}" type="number"/>bytes)
          </span>
          <input type="checkbox" name="state" value="false" onclick="javascript:fileCheck()">
          <span id="fchk" style="font-size:9pt;color:#908756"></span>
        </c:if>
        <span id="fileState"></span>
         <c:if test="${dto.fileSize < 1}"><!-- 파일이 없는 경우 -->
          
          <input type="file" name="bean.file">
         
         </c:if>
   </td>
    </tr>
     <tr height=30 bgcolor="#ffffff">
      <td align="left" colspan=2>
        <span style="font-size:9pt; color:red">
    <s:fielderror />
     </span> 
   </td>
    </tr>
       <tr height=30 bgcolor="#f0f0f0">
    <td align="center" colspan=2>
   <input type="submit" value="갱신...">
   <input type="button" value="삭제..." onclick="delProc()">
   <input type="button" value="등록하기"
     onclick="javascript:location.href='index.action'">
            <input type="button" value="리스트"
              onclick="javascript:location.href='list.action'">
    </td>
   </tr>
    </table>
  </form>
 </center>
 </body>
</html> 

자세한 내용은 파일 참조

이 파일은 이전 까지 한 모든 작업이 포함된 파일이다. (이 파일은 학습 용입니다.)


struts2 삭제, 업데이트 끝!


■ 파일 이름 겹치는 문제 해결.

1. 파일 이름 중복 문제 해결 정책 작성.

package com.myhome.upload.policy;

import java.io.File;
import java.io.IOException;

public class FileRenamePolicy {
 
  public File rename(File f) {  //File f는 원본 파일
    if (createNewFile(f)) return f; //생성된 f가
   
    //확장자가 없는 파일 일때 처리
    String name = f.getName();
    String body = null;
    String ext = null;

    int dot = name.lastIndexOf(".");
    if (dot != -1) { //확장자가 없을때
      body = name.substring(0, dot);
      ext = name.substring(dot);
    } else {   //확장자가 있을때
      body = name;
      ext = "";
    }

    int count = 0;
    //중복된 파일이 있을때
    while (!createNewFile(f) && count < 9999) {  
      count++;
      String newName = body + count + ext;
      f = new File(f.getParent(), newName);
    }
    return f;
  }

  private boolean createNewFile(File f) { 
    try {
      return f.createNewFile();  //존재하는 파일이 아니면
    }catch (IOException ignored) {
      return false;
    }
  }
}


2. 적용

import com.myhome.upload.policy.FileRenamePolicy;

.... 생략 ....

protected void upload() throws Exception{
  File file = new File(UploadUtil.SAVE + bean.getFileFileName()); //bean이 참조하고 있는 파일을 실제 파일로 얻어온다
  
  /* file rename policy 적용
   * a.txt가 중복일 경우  -> a1.txt(중복이라면) -> a2.txt........
   * */

  
  file = new FileRenamePolicy().rename(file); //적용!
  
  log.info("template file : " + bean.getFile().toString());
  log.info("original file : " + file.toString());
  
FileUtils.copyFile(bean.getFile(), file); //bean에 있는 파일은 template 파일이다. templete의 파일을 실제파일로 복사여 폴더에 저장한다.
  FileUtils.forceDelete(bean.getFile()); //templete에 있는 파일을 삭제한다. 계속 쌓아 두기 때문에 삭제 해줘야 한다.
  
  dto.setFileName(file.getName()); //DB에 저장하기 위해 빈으로 부터 파일과 크기를 받는다.
  dto.setFileSize(file.length());
  
 }

..... 생략 .....


■ download

property를 구별하기 위해 DownloadAction.java 를 별도로 만들었다.

1. DownloadAction Class 만들기

package com.myhome.upload.actions;

import com.opensymphony.xwork2.ActionSupport;

import com.myhome.upload.util.UploadUtil;
import java.io.File;
import java.io.InputStream;
import java.io.FileInputStream;

public class DownloadAction extends ActionSupport {
 
 private static final long serialVersionUID = 1L;
 
 /*form property fields*/
 private String filename;
 
 /*result property fields*/
 private InputStream inputStream;
 private int   contentLength;
 private String   contentDisposition;

 
 @Override
 public String execute()throws Exception {
  if(filename != null){
   download();
  }
  return SUCCESS;
 }

 public void download()throws Exception {
    /*encFile를 실제 파일로 객체를 생성한다.*/
    File file = new File(UploadUtil.SAVE + filename);
   
    /*contentLength를 설정한다.*/
    setContentLength((int)file.length());
   
    /*어떤 파일이든지 다운로드가 되도록 어터치한다.*/
    setContentDisposition("attachment;filename=" + toEng(file.getName())+";");
   
    /*실제 다운로드를 받기 위해 스트림한다.*/
    setInputStream(new FileInputStream(UploadUtil.SAVE + file.getName()));
 }
 
 public String getFilename() {
  return filename;
 }

 public void setFilename(String filename) {
  this.filename = filename;
 }

 public InputStream getInputStream() {
  return inputStream;
 }

 public void setInputStream(InputStream inputStream) {
  this.inputStream = inputStream;
 }

 public int getContentLength() {
  return contentLength;
 }

 public void setContentLength(int contentLength) {
  this.contentLength = contentLength;
 }

 public String getContentDisposition() {
  return contentDisposition;
 }

 public void setContentDisposition(String contentDisposition) {
  this.contentDisposition = contentDisposition;
 }
 
 /*decode (MS949 -> ISO8859_1)*/
 protected String toEng(String data){
  try{
   data = new String(data.getBytes("MS949"), "ISO8859_1");
  }catch(java.io.UnsupportedEncodingException uee){}
  return data;
 }

}

2. upload.xml 에 download action 추가.

<action name="download"
       class="com.myhome.upload.actions.DownloadAction">
       <result name="success" type="stream"> <!-- strem으로 설정하면 Action Class의 InputStream으로 받아온다 -->
            <param name="contentType">application/octet-stream</param> <!-- 이렇게 설정 안해주면 한글 다운로드가 안된다. -->
             <param name="contentLength">${contentLength}</param> <!-- 파일 크기 -->
            <param name="contentDisposition">${contentDisposition}</param> <!--파일의 이름을 설정하기 위한 컨텐츠 헤더값 지정-->
           <param name="bufferSize">4096</param> <!-- 한번에 다운로드 할 수 있는 버퍼 사이즈 -->

          </result> 
     </action>


3. jsp 만들기

list.jsp

<%@ page contentType="text/html;charset=euc-kr"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%@ taglib prefix="s" uri="/struts-tags"%>

<html>
  <head>
    <script type="text/javascript">
      function query(num){
      var v = document.listform;
      v.num.value=num;
      v.action="query.action";
      v.submit();  
      }
     
      function download(fn){
        var v = document.listform;
        v.filename.value=fn;
        v.submit();
      }
    </script>
 
 <style type="text/css">
     a:active  {font-size: 10pt; text-decoration: none; color: #000000}
  a:link    {font-size: 10pt; text-decoration: none; color: #000000}
  a:visited {font-size: 10pt; text-decoration: none; color: #000000}
  a:hover   {font-size: 10pt; text-decoration: none; color: #000000}
  td     {font-size: 10pt;}
    </style> 
  </head>  
  <body>
    <center><br />
    <h3><b>Struts2 Upload_Download(list)</b></h3>
    <form method="POST" name="listform" action="download.action">
     <input type="hidden" name="num">
     <input type="hidden" name="filename">
     <table border=0 cellpadding=0 cellspacing=1 bgcolor="#000000">
      <tr height=30 bgcolor="#f0f0f0">
        <td width=50 align="center"><b>번호</b></td>
        <td width=100 align="center"><b>회원명</b></td>
        <td width=60 align="center"><b>성별</b></td>
        <td width=120 align="center"><b>연락처</b></td>
  <td width=120 align="center"><b>가입일자</b></td>
  <td width=250 align="center"><b>첨부파일(크기)</b></td>   
      </tr>
     <s:iterator value="list">
      <tr height=30 bgcolor="#ffffff">
        <td align="center">&nbsp;<s:property value="num"/></td>
        <td align="center">
           <a href="javascript:query('${num}')">&nbsp;${name}</a> 
      </td>
      <td align="center">&nbsp;<s:property value="sex" /></td>
      <td align="center">&nbsp;${tel}</td>
      <td align="center">&nbsp;${wdate}</td> 
      <td align="left">&nbsp;
        <c:if test="${fileSize > 0}">
           <a href="javascript:download('${fileName}')">${fileName}</a>
            <span style="font-size:10pt; color:#90a087">
             (<fmt:formatNumber value="${fileSize/1024.}"
                                type="number"
                                pattern="#,##0.00"/>KB)
            </span> 
        </c:if> 
      </td>
      </tr>
     </s:iterator>
      <tr height=30 bgcolor="#f0f0f0">
        <td align="center" colspan=6>
          <input type="button" value="등록하기"
              onclick="javascript:location.href='index.action'">
        </td>
     </tr>
     </table>
    </form> 
   </center>
  </body>
</html>

struts2를 이용한 다운로드 끝!

Struts2 에서 upload & download 하기 3에서 파일 참조.

 Strtus2 에서는 client가 form에서 보내주는 데이타를 bean으로 받으면 bean에 file을 써주기만 하면 그냥 데이터가 들어와 있다! 처리해줘야 할 일은 중복을 제거해 주어야 한다. commons에서 제시하고 있는 FileUpload, IO를 참조해서 upload를 수행하기 때문에 commons의 FileUpload는 중복을 해결하기 위한 정책이 없다. 그래서 이것을 처리해 주어야 한다.
 그리고 commons의 FileUpload는 client가 업로드한 파일을 template으로 파일을 주고, 저장한다. 그런데 template는 실제 올린 이름과 완전히 다른 이름으로 저장되어있다. 이 부분도 처리해 주어야 한다.

순서 : 다운로드에 필요한 library 파일 다운로드 --> jsp 페이지 만들기 --> FormBean Class 만들기 --> DTO  Class 만들기 --> DB에 데이타를 넣기 위한 DAO 설정 및 iBatis 설정(UploadSqlMap.xml, SQLManager.java, SqlMapConfig.xml) --> pacakge_ko.properties 설정 --> upload.xml --> UploadIndexAction Class 만들기
--> UploadUtil Class 만들기 --> UploadMultiAction Class 만들기


1. 파입 업로드에 필요한 library 파일 다운로드 하기.
http://commons.apache.org/ 에서 IO, FileUpload 에서 library 파일을 다운로드 하여 lib 폴더에 추가한다.

2. jsp 페이지 만들기.

<%@ page contentType="text/html;charset=euc-kr"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<s:bean id="bean" name="com.myhome.upload.beans.UploadFormBean"/>
<html>
  <body>
    <center><br><br>
    <h3><b><s:text name="register.title" /></b></h3><!-- 번들 설정 해서 사용 : package_ko.properites -->
    <form method="post" action="register.action" enctype="multipart/form-data">
<!-- fileupload는 form에서 multipart로 나간다고 반드시 명시해줘야 한다. enctype="multipart/form-data" -->
     <table border=0 cellpadding=0 cellspacing=1 bgcolor="#000000">
       <tr height=30 bgcolor="#ffffff">
         <td width=100 align="right">
           <b><s:text name="register.name" /></b>&nbsp;
         </td>
         <td width=300 align="left">&nbsp;
            <input type="text" name="bean.name">
.......................... 생략..................................................................

3. FormBean Class 만들기.

package com.myhome.upload.beans;
import java.io.File;
public class UploadFormBean {
 
 /*form parameter*/
 private int num;
 private String name;
 private String sex;
 private String tel;
 
 /*file upload property*/
// 파일을 올릴 때, 네개의 property 는 반드시 있어야 한다. 배열로 잡으면 다중 파일을 받을 수 있다.

 private File file;  
 private String fileFileName; 
 private long fileFileSize;
 private String fileContentType; // 어떤 file type 인지 알려 준다.(text, imag 등...)
................. getter, setter 부분 생략.................................................

여기서 주의해야 할 점은 이름을 정할 때, private File file; 의 file 이름과 나머지 아래 세 property의 file의 접두사가 일치해야 한다는 것이다. 그리고 file 다음에 오는 문자는 대문자가 와야 한다. ex) file -> fileFile -> fileFileName(fileFileSize, fileContentType) 이런식으로 이름을 만들어 주어야 한다.

3. DTO 만들기.(파일 참조)

4. DAO 만들기.(파일 참조)

5. iBatis 설정.(파일 참조)
쿼리를 수행할 UploadSqlMap.xml 만들고, SQLManager.java, SqlMapConfig.xml 만들기

6. 번들을 사용하기 위하 package.properties 만들기

 spring에서는 번들을 일일이 설정해줘야 사용할 수 있다. 하지만 struts2에서는 번들을 사용할 때, 패키지 안에 package.properties 파일만 놓아주면 자동 인식(번들 파일들이)이 된다. 전체에 적용할려면 classes에 packages.properties, global.properties(공동으로 메세지를 정의할 때) 만들면 된다.
 
 1) 메모장에서 아래 내용을 입력한다.
# upload project message bundle
# file name ; package.properties
register.title=Struts2 File Upload (Register)
register.name=성 명
register.sex=성 별
register.tel=연락처
register.file=첨부
error.name=성명은 필수 입력항목입니다.
error.name.length=잘못 입력된 성명입니다.
error.tel=연락처를 입력하세요!!!
error.tel.length=사용할 수 없는 번호 입니다.
# native2ascii -encoding euc-kr package.properties package_ko.properties

#은 주석이다.

package.proeerties 파일 이름으로 upload package 가 이는 곳에다 저장한다.(파일 형식에서 모든 파일 선택 후) ex.C:\workspace\struts2\src\com\myhome\upload 여디가 저장

2) 콘솔 창에서 upload 폴더가 있는가 있는 곳으로 이동한다. ex)C:\workspace\struts2\src\com\myhome\upload 


 패스가 잡혀 있지 않을 경우 패스를 잡아주어야 한다.(자신의 Java SDK를 설치한 경로로)

콘솔 창에서 아래와 같이 입력한다.
set path=%path%;C:\Program Files\Java\jdk1.6.0_12\bin


그런다음 다음과 같이 입력한다.
native2ascii -encoding euc-kr package.properties package_ko.properties
native2ascii [-encoding] [코드값] [원시파일] [목적파일] 순으로 작성하며 euc-kr 타입으려 변경한다.

그러면 폴더 안에 package_ko.properties 파일이 생성된것을 확인 할 수 있다.

# upload project message bundle
# file name ; package.properties
register.title=Struts2 File Upload (Register)
register.name=\uc131 \uba85
register.sex=\uc131 \ubcc4
register.tel=\uc5f0\ub77d\ucc98
register.file=\ucca8\ubd80
error.name=\uc131\uba85\uc740 \ud544\uc218 \uc785\ub825\ud56d\ubaa9\uc785\ub2c8\ub2e4.
error.name.length=\uc798\ubabb \uc785\ub825\ub41c \uc131\uba85\uc785\ub2c8\ub2e4.
error.tel=\uc5f0\ub77d\ucc98\ub97c \uc785\ub825\ud558\uc138\uc694!!!
error.tel.length=\uc0ac\uc6a9\ud560 \uc218 \uc5c6\ub294 \ubc88\ud638 \uc785\ub2c8\ub2e4.
# native2ascii -encoding euc-kr package.properties package_ko.properties

이렇게 인코딩 되어 있는것을 확인 할 수 있다.

7. upload.xml 을 만들고 struts.xml 에 include 한다.

8. UploadIndexAction Class 만들고,
 index.jsp <%response.sendRedirect("upload/index.action");%> 설정.

9. UploadUtil Class 만들기

package com.myhome.upload.util;
public final class UploadUtil {
 public static final String SAVE = "D://Java_webprogramimng_2/Java Web2/edu/upload/"; //실제 파일이 저장될 위치
 
 public static final long SIZE = 1024*1024*20; //파일 사이즈 20M 로 제한.
}

10. UploadMultiAction Class 만들기

package com.myhome.upload.actions;
import com.myhome.upload.util.UploadUtil;
import com.myhome.upload.dao.UploadDAO;
import com.myhome.upload.dto.UploadDTO;
import com.myhome.upload.beans.UploadFormBean;
import com.opensymphony.xwork2.ActionSupport;
/*file spec*/
import java.io.File;
import org.apache.commons.io.FileUtils;
/*log4j*/
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/*commons bean utils*/
import org.apache.commons.beanutils.BeanUtils; //폼에 있는 값을 DTO로 보내기 위해
public class UploadMultiAction extends ActionSupport{
 
 //Log 셋팅
 public static final Log log = LogFactory.getLog(UploadMultiAction.class);
 
 private UploadFormBean bean;
 private UploadDTO dto;
 
 /**
  * 등록부분
  */
 public String register() throws Exception{
  dto = new UploadDTO();
  BeanUtils.copyProperties(dto, bean);
  if(bean.getFile() != null){
   upload();
  }else{
   dto.setFileName("");
   dto.setFileSize(0L);
  }
  
  new UploadDAO().insert(dto);
  
  return SUCCESS;
 }
 
 protected void upload() throws Exception{
  File file = new File(UploadUtil.SAVE + bean.getFileFileName());
  
//bean이 참조하고 있는 파일을 실제 파일로 얻어온다
  log.info("template file : " + bean.getFile().toString());
  log.info("original file : " + file.toString());
  FileUtils.copyFile(bean.getFile(), file); //bean에 있는 파일은 template 파일이다. templete의 파일을 실제파일로 복사여 폴더에 저장한다.
  FileUtils.forceDelete(bean.getFile());
   //templete에 있는 파일을 삭제한다. 계속 쌓아 두기 때문에 삭제 해줘야 한다.
  
  //DB에 저장하기 위해 빈으로 부터 파일과 크기를 받는다  
  dto.setFileName(file.getName()); 
  dto.setFileSize(file.length());
  
 }
 public UploadFormBean getBean() {
  return bean;
 }
 public void setBean(UploadFormBean bean) {
  this.bean = bean;
 }
 
 public UploadDTO getDto(){
  return dto;
 }
}

자세한 내용은 Struts2 에서 upload & download 하기 3 에서 파일을 참조 한다.

struts2 를 이용한 Upload 끝!



 Struts2의 action에서는 servlet을 사용하지 않기 때문에 자체적으로 ActionContex를 이용해서 session을 처리한다. 그 session 자체가 원래는 Map 방식을 정의하고 있다. 그래서 일명 session data를 만들어서 Map방식을 이용하여 session을 저장하도록 지시한다. session에 저장할 때, Map 방식이기 때문에 앞에는 name 값(key), 뒤에는 value가 들어가야 한다. 로그인 시에 user이름으로 user라는 오브젝트를 저장해 놓고 result로 보낸다. result는 적절할 페이지를 Template를 통해 지정하고, Interceptor로 이동한다. Interceptor에서는 Interceptor의 1단계로 이동하고, 이 때 뷰페이지를 선택해서 데이타들을 세션영역에 생성 시켜 놓는다.


순서 : jsp 만들기 -> action class 만들기 -> login.xml 만들기 -> struts.xml 추가

1. action class 만들기

package com.myhome.login.actions;

import java.util.Map;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ActionContext;;

@SuppressWarnings("serial")
public class LoginMultiAction extends ActionSupport{

 private String id;
 private String passwd;
 
 /**
  * index 부분
  */
 public String index() throws Exception{
  if(ActionContext.getContext().getSession().get("id") == null)//id를 뽑아내서 비교할 수 도 있다.
  //if(ActionContext.getContext().getSession() == null)
   return LOGIN;
  else
   return SUCCESS;
 }
 
 /**
  * login 부분
  */

 @SuppressWarnings("unchecked")
 public String login() throws Exception{
  ActionContext context = ActionContext.getContext();//session을 생성하기 위해
  Map<String, String> session = (Map<String, String>)context.getSession();// Map 사용시
  session.put("id", id);
  session.put("passwd", passwd);
  context.setSession(session);
  
return SUCCESS;
 }
 
 /**
  * logout 부분
  */
 @SuppressWarnings("unchecked")
 public String logout() throws Exception{
  ActionContext context = ActionContext.getContext();
  Map<String, String> session = (Map<String, String>)context.getSession();

  if(session.get("id") != null){
   session.remove("id");
   session.remove("passwd");

  }
  context.setSession(session);//다시 session을 적용 시켜서 초기화 시켜야 한다. 
 
 return SUCCESS;
 }

 public String getId() {
  return id;
 }

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

 public String getPasswd() {
  return passwd;
 }

 public void setPasswd(String passwd) {
  this.passwd = passwd;
 }
 
}

2. login.xml 만들기.

<?xml version="1.0" encoding="euc-kr"?>
<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
        "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
 
    <package name="login" namespace="/login" extends="struts-default"><!-- struts-default 는 Interceptor 정의 문서로 이게 없으면 Interceptor를 타지 않는다 -->
     <action name="index"
                class="com.myhome.login.actions.LoginMultiAction"
                 method="index"><!-- index method 실행 -->

      <result name="success" type="dispatcher">
            /WEB-INF/login/logout.jsp
      </result>

      <result name="login" type="dispatcher">
       /WEB-INF/login/login.jsp
      </result>
     </action>
     
     <action name="login"
                 class="com.myhome.login.actions.LoginMultiAction"
                 method="login">(!-- inogin method 실행 -->
      <result name="success" type="chain">index</result>
     </action>
     
     <action name="logout"
                class="com.myhome.login.actions.LoginMultiAction"
                method="logout"><!-- logout method 실행 -->
      <result name="success" type="chain">index</result>
     </action>
      
    </package>
   
</struts>


3. struts.xml 문서에 추가

<struts>
   <!-- include files -->
     <include file="login.xml"/>  
</struts>

* jsp 페이지에서

<%@ page language="java" contentType="text/html; charset=EUC-KR"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
  <head>
   <meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
   <title>Logout</title>
  </head>
  <body>
    <center><br /><br />
      <table border=0 cellpadding=1 cellspacing=1 bgcolor="#a0a0a0">
       <tr height=50 bgcolor="#ffffff">
         <td width=400 align="center">
           <b>${id}님 반갑습니다.</b><!-- action class에서의 property 이름과 같아야 한다. 이러면 바로 로그인한 아이디가 표시된다.-->
         </td>  
       </tr>

자세한 내용은 파일 참조. 지금까지 한 작업과 업로드 까지 포함. 이 파일은 학습용입니다!


Struts2에서 session을 이용한 로그인 로그아웃 해보기 끝!

+ Recent posts