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