'Framework'에 해당되는 글 75건

struts 2 - JFree Chart plugin 2009.07.08
struts 2 - Tiles Plug in 2009.07.08
struts 2 - Interceptor 2009.07.06
struts 2 - properties 파일 2009.07.05
struts 2 - upload & download 2009.07.05

struts 2 - JFree Chart plugin

Published on: 2009. 7. 8. 16:52 by louis.dev


Java plug in 중 chart 를 쉽고 빠르게  만들 수 있게 해주는 JFree Chart Plugin을 소개한다.



다음과 같이 원형과 막대형의 그래프도 만들 수 있고 그외 만들수 있는 그래프의 숫자는 아주 많다. 지원되는 많은 차트를 확인 하려면
http://www.jfree.org/jfreechart/jfreechart-1.0.13-demo.jnlp

Library Download:

 http://www.jfree.org/ -->Download -->SourceForge Download page Click --> 하단의 jfreechart-1.0.13-javadocs.zip와 jfreechart-1.0.13.zip 받기


다음을 실행 시켜서 확인해 보면 된다.


작업순서

일단 차트를 만드는 기본적인 컨셉은 데이터가 있어야 차트로 변환할 수 있다는 점이다. 데이터가 들어가 있지 않으면 어떤것도 차트로 표현 할 수 없는 것은 당연한 일이다.


기본적인 Class의 구조는 다음과 같다.(API를 확인 하면서 보면 된다.)

가장 큰 밑바탕의 역할을 하는 JFreeChart Class가 존재 한다. JFreeChart class의 인스턴스를 생성하려면 Plot이라는 Class가 필요하다.
Plot은 정확하게 어떤 모양을 구현할지 선택하는 클래스 이다.(원형, 막대형, 꺽은선형...)
Plot은 모든 그래프 모형의 상위에 존재 하며 하위의 클래스들은 Plot을 상속하고 있다.
예를 들어 PiePlot 이라는 클래스는 원형 모델을 지원하며 PiePlot class로 구현한 그래프트는 맨 첫번째 그림의 왼쪽 모형이 되겠다.
PiePlot이라는 class는 또 다양한 형태의 class에 부모가 되며 하위 클래스 들은 3D형태의 클래스 부터 다양한 모양의 클래스가 존재 하며 예를 들면 PiePlot3D class가 원형이면서 3D형태로 구현된다.



                                                               Plot
                                                                ↑
                                                            PiePlot
                                                                ↑
                                                            PiePlot3D 

이런 형태가 된다.

이 Pie class에 데이터를 넣어 줘야 하는데 데이터를 저장하고 넣게 해주는 것은 PieDataset 이라는 interface가 존재 하고 이것을 구현하고 있는 다양한 class가 있는데 일반적으로 DefaultPieDataset class를 사용한다.

작업순서
                
                           
1) Library파일 추가

struts 2 에서 제공하는 다음과 같은 library를 추가한다.

struts2-jfreechart-plugin-2.0.14.jar
commons-digester-1.8.jar

위에서 다운받은 JFreeChart library를 추가 한다.

jcommon-1.0.16.jar
jfreechart-1.0.13.jar

2) action mapping 설정

extends="struts-default,jfreechart-default"

<action name="register"
           class="chart.actions.RegisterAction"
           method="execute">
          <result name="success" type="chart">
              <param name="width">500</param>
              <param name="height">400</param> 
          </result>   
 </action>

꼭 extends를 다음과 같이 설정해 주어야 하고 result type을 chart로 해주면 jFreeChart가 실행되어 차트가 보여지게 된다.
그러나 보통 웹페이지에서는 웹페이지에 전체 다 차트가 나오는 경우는 없으며 html 사이에 추가 되길 원한다.

그렇기 때문에 보통은 type="chart" 로 선언하지 않고 BusinussLogic상에서 차트를 이미지로 만들어 주어 저장한후 jsp페이지에서 링크를 걸어 주는 형식을 취하고 있다.

<action name="result"
           class="chart.actions.ResultAction"
           method="execute">
          <result name="success">/chart/result.jsp</result>    
</action>

다음과 같이 평범하게 결과 페이지로 이동시킨다.


3) Business Logic을 수행하고 JFreeChart class로 chart를 생성한다.

Logic을 수행할 class - 투표로직!
----------------------------------------------------------------------------------------------------------
package chart.actions;

import org.jfree.chart.JFreeChart;

import com.opensymphony.xwork2.ActionSupport;
import chart.model.dao.ChartDAO;
import chart.model.dto.ChartDTO;
import chart.poll.PollChart;

public class RegisterAction extends ActionSupport {

 public static final long serialVersionUID = 1L;
  
 /*property fields*/
 private int answer;
 private ChartDTO dto;
 private JFreeChart chart;
 
 public JFreeChart getChart(){          //action mapping 의 result로 데이터를 보내야 하기 때문에 JFreeChart로 리턴한다.
  return chart;
 }

 
 @Override
 public String execute()throws Exception {
  dto = new ChartDTO();
  calc();                                        //jsp페이지의 radio 버튼으로 들어오는 오는 값을 세팅 시켜준다.
  ChartDAO dao = new ChartDAO();
  dao.update(dto);                          //DB에 데이터 업데이트
  //list query
  dto = dao.list(dto);                        //DB에 있는 데이터 가져옴
  //chart 정보 가져옴
  chart = PollChart.getPie3dChart(dto);  // 실질적 차트를 생성하는 부분
  return SUCCESS;
 }

 public void calc(){
  switch(answer){
   case 1 : dto.setAnswer1(1);break;
   case 2 : dto.setAnswer2(1);break;
   case 3 : dto.setAnswer3(1);break;
   case 4 : dto.setAnswer4(1);
  }
  dto.setTot(1);
 }
 
 public int getAnswer() {
  return answer;
 }

 public void setAnswer(int answer) {
  this.answer = answer;
 }


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

PollChart class

----------------------------------------------------------------------------------------------------------
package chart.poll;

import org.jfree.chart.JFreeChart;
//import org.jfree.chart.ChartFactory;
import org.jfree.chart.plot.PiePlot3D;
import org.jfree.data.general.DefaultPieDataset;
import org.jfree.data.category.DefaultCategoryDataset;
//import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.ChartRenderingInfo;
import org.jfree.chart.entity.StandardEntityCollection;
import chart.model.dto.ChartDTO;
import java.io.File;

import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.axis.CategoryAxis3D;
import org.jfree.chart.axis.NumberAxis3D;
import org.jfree.chart.renderer.category.BarRenderer3D;

public class PollChart {
 
 
 
 /*pie 3D chart*/
 public static JFreeChart getPie3dChart(ChartDTO dto)throws Exception {
  
  String path="D://JAVA/java document/web 2/workspace/struts2/WebContent/chart_images/pie3d.png";  //이미지 파일을 저장할 경로 설정
  JFreeChart chart = null;
// 차트에 삽입할 데이터를 집어 넣는다.
  DefaultPieDataset dataset = new DefaultPieDataset();
  dataset.setValue("1번("+dto.getAnswer1()+"명)", dto.getAnswer1());
  dataset.setValue("2번("+dto.getAnswer2()+"명)", dto.getAnswer2());
  dataset.setValue("3번("+dto.getAnswer3()+"명)", dto.getAnswer3());
  dataset.setValue("4번("+dto.getAnswer4()+"명)", dto.getAnswer4());
  PiePlot3D plot = new PiePlot3D(dataset);         //값을 넣어서 3DChart를 생성한다.
  chart = new JFreeChart(
     "설문조사 통계",
     JFreeChart.DEFAULT_TITLE_FONT,
     plot,
     true
          ); //true는 범례설정
  plot.setOutlineVisible(false);  //사각 테두리 사용하지 않음
  chart.setBackgroundPaint(java.awt.Color.WHITE); //background color설정
  new PollChart().createImage(path, chart);   //png파일로 저장해서 저장한 폴더위치에 저장하자
  
  return chart;
 }
 
 /*bar 3D chart*/
 public static JFreeChart getBar3dChart(ChartDTO dto)throws Exception {
  String path="D://JAVA/java document/web 2/workspace/struts2/WebContent/chart_images/bar3d.png";
  JFreeChart chart = null;
  DefaultCategoryDataset dataset = new DefaultCategoryDataset();
  dataset.setValue(dto.getAnswer1(), "1번", "1번("+dto.getAnswer1()+"명)");
  dataset.setValue(dto.getAnswer2(), "2번", "2번("+dto.getAnswer2()+"명)");
  dataset.setValue(dto.getAnswer3(), "3번", "3번("+dto.getAnswer3()+"명)");
  dataset.setValue(dto.getAnswer4(), "4번", "4번("+dto.getAnswer4()+"명)");
  /*
  chart = ChartFactory.createBarChart3D(
    "설문조사 통계",
    "선택항목",
    "인원수",
    dataset,
    PlotOrientation.VERTICAL,
    true, false, false);
  */
  CategoryAxis3D axis = new CategoryAxis3D("선택항목");
  NumberAxis3D numAxis = new NumberAxis3D("인원수");
  BarRenderer3D renderer = new BarRenderer3D(35.0,10.0);
  renderer.setItemMargin(0.10);
  renderer.setShadowVisible(true);
  CategoryPlot plot = new CategoryPlot(dataset,axis,numAxis, renderer);
  chart = new JFreeChart(
    "설문조사 통계",
    JFreeChart.DEFAULT_TITLE_FONT,
    plot,
    false
  );
  chart.setBackgroundPaint(java.awt.Color.WHITE);
  new PollChart().createImage(path, chart);
  return chart;
 }
 
 /*image 생성부분*/
 public void createImage(String file, JFreeChart chart)throws Exception {
  ChartRenderingInfo info = new ChartRenderingInfo(
                      new StandardEntityCollection());
  ChartUtilities.saveChartAsPNG(new File(file), chart, 380, 300, info);
 }

}

----------------------------------------------------------------------------------------------------------
사진 파일을 저장할 위치를 프로젝트가 접근 가능한 폴더에 넣어야 jsp페이지에서 링크 걸때 정확하게 걸린다.

'Framework > STRUTS 2' 카테고리의 다른 글

struts2 - struts 2의 Exception 처리  (2) 2009.08.09
struts 2 - 스트러츠2 + spring 연동하기  (2) 2009.07.12
struts 2 - Tiles Plug in  (6) 2009.07.08
struts 2 - Interceptor  (3) 2009.07.06
struts 2 - properties 파일  (1) 2009.07.05

struts 2 - Tiles Plug in

Published on: 2009. 7. 8. 15:05 by louis.dev




진행순서

① 사용자로부터 요청이 들어오면 Interceptor를 지나 Action 에서 Business Logic을 수행 후 action mapping 에 의해 result로 결과가 보내지게 된다.
② 이때 result 의 type="tiles" 로 설정하게 되면 Result에서는 web.xml에 설정한 Tiles Listener를 수행하고 WEB-INF 폴더 아래에 있는(web.xml 파일과 경로가 같은) tiles.xml(tiles의 설정이 들어있는 xml파일 - 이름은 어떠한 것이라도 상관 없다)을 로딩한다.
③ 그결과를 다시 Interceptor에 전달하여 사용자로 결과를 보내주게 된다.

작업순서

1) Tiles Plug-in을 수행하기 위한 Library파일을 설정한다.

struts 2의 스펙에 있는 다음의 Library파일을 추가 한다.
commons-digester-1.8.jar                  :  플러그인을 사용하기 위해서 꼭 필요한, 플러그인을 이용하겠다고 정의해주는 Library
struts2-tiles-plugin-2.0.14.jar               :  아래서부터는 tiles를 사용하기 위한 library 
tiles-api-2.0.4.jar
tiles-core-2.0.4.jar
tiles-jsp-2.0.4.jar

2) web.xml 파일에 Tiles Listener를 설정한다.

<listener>
    <listener-class>
      org.apache.struts2.tiles.StrutsTilesListener 
    </listener-class>
</listener>

3) Tiles의 설정이 들어있는 tiles.xml파일을 생성(파일의 이름은 아무거나 상관이 없으며 WEB-INF폴더 에 있어야 한다.)

------------------------------------------------------------------------------------------------------
<?xml version="1.0" encoding="EUC-KR" ?>

<!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">
        <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"/>
    </definition>
 
 <definition name="menu2" extends="index">
        <put-attribute name="body"   value="/tiles/body-menu2.jsp"/>
    </definition>
</tiles-definitions>

------------------------------------------------------------------------------------------------------
template로 설정한 jsp페이지는 기본레이아웃이 되는, 즉 index 파일이라고 말할수 있다.

하위 정으로 부터 menu1일때는 상단에 선언한 index 에서 body부분만 다음과 같은 jsp페이지로 변경하겠다는 뜻이다.

4) action mapping을 수행한다.
 tiles.xml이라는 파일에서 action mapping을 수행한다.

------------------------------------------------------------------------------------------------------
<struts>
    <package name="tiles" namespace="/tiles" extends="struts-default, tiles-default">
        <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>
------------------------------------------------------------------------------------------------------
extends="tiles-default"      : tiles 에서 기본적으로 사용하는 Interceptor를 수행하겠다는 설정으로 다음의 설정을 꼭해주어야 Tiles를 사용할 수 있다.

만약 주소창에 index.action으로 들어오면 action name="index" 가 수행한다. 그리고는 result type="tiles" 인것을 확인하고 tiles설정이 되어있는 곳으로가 줄쳐진 index라는 곳으로 이동한다. 즉 위의 index는 tiles설정이 들어가 있는 tiles.xml(web.xml과 같은 경로에 있는 tiles설정 파일) 로 들어가 definition name="index" 인것을 찾아 들어가 실행 시킨다.

5) jsp의 레이아웃 설정하기
Tiles에서 지원하는 tag library를 통해 jsp페이지 끼워 넣을 수 있다.

<%@ taglib prefix="tiles"  uri="http://tiles.apache.org/tags-tiles"%>

다음과 같은 테그 라이브러리를 추가 해주고

<tiles:getAsString name="title" /> 선언하면

tiles-difinition 문서에서 이름이 title인것을 찾아 문자 형으로 리턴해 준다.
즉 
               <put-attribute name="title"  value="Struts2 Tiles Example"/>
이기 때문에

결국 화면엔
"Struts2 Tiles Example" 이렇게 출력 된다.

<tiles:insertAttribute name="header"/>

이것도 마찬가지로 tiles-difinition 문서에서 header인 것을 찾아와 insert시킨다. 즉 다음의 태그가 입력된 곳에

                <put-attribute name="header" value="/tiles/header.jsp"/>
이렇게 설정되어 있기 때문에 header.jsp가 입력이 된다.





'Framework > STRUTS 2' 카테고리의 다른 글

struts 2 - 스트러츠2 + spring 연동하기  (2) 2009.07.12
struts 2 - JFree Chart plugin  (0) 2009.07.08
struts 2 - Interceptor  (3) 2009.07.06
struts 2 - properties 파일  (1) 2009.07.05
struts 2 - upload & download  (0) 2009.07.05

struts 2 - Interceptor

Published on: 2009. 7. 6. 17:35 by louis.dev


위의 그림은 Interceptor의 로직 그림이다
Interceptor는 4가지로 구분되며 각각 하는일은 다음과 같아

- preparable : 사용자로부터 전달된 데이터가 이곳을 통해 들어와 여기서 bean 객체에 담겨 stack에 쌓이게 된다.
- stack : stack의 환경에 맞춰 들어오는 데이터를 처리한다.
- Action : stack 의 결과로 execute method를 수행한다.
- ModelDriven : 결과를 result로 전달하는 역할을 한다.
   getModel() result로 보내질 객체를 생성한다. getModel로 vo를 보낸다 하면 jsp 페이지 에서 &{vo.name} 이런식으로 데이터를 받는게 아니라
다음과 같이 &{name} property이름만 해주면 된다.(actionsupport 를 사용하면 &{vo.name} 으로 해야 한다)

위 4가지 단계중 preparable, action,modeldriven은 Interface형태로 제공되기 때문에 implements해서 사용한다.

일반적으로 struts 2를 구현할때 ActionSupport Class를 상속받아 사용한다 이렇게 되면 위의 3가지를 사용자가 구현할 필요가 없지만 ActionSupport를 상속 받지 않으면 다음과 같은 interface를 구현하고 execute() method를 override 해야 한다.

action mapping을 수행하고 있는 xml 파일에서 package를 설정하는 부분이 있는데 이부분이

extends="struts-default"

이렇게 선언되어 있다면 기존에 구현된 interception을 수행하는 것이다.


<Intercepter의 종류>


공통적 사항
Preparable, Action, ModelDriven을 구현한 class 생성

------------------------------------------------------------------------------------------------------------
package person.actions;

import person.model.PersonVO;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.Preparable;
import com.opensymphony.xwork2.ModelDriven;


@SuppressWarnings("unchecked")
public class WriteAction implements Action,
                                                    Preparable,
                                                   ModelDriven{
 private PersonVO vo;

 @Override
 public String execute()throws Exception {
  return SUCCESS;
 }
 //홈 요청이 들어오면 파라미터의 값을 받기 위해 객체를 생성하고
 //각 파라미터의 값을 프로퍼티에 저장한다.

 @Override
 public void prepare() {
  vo = new PersonVO();
    }
 //execute 메소드를 수행하고 결과를 Result로 전달하는 부분
 @Override
    public Object getModel() {
  return vo;
    }
}
------------------------------------------------------------------------------------------------------------
기본적인 class의 틀은 다음과 같다.
 - Preparable Interface의 prepare method를 구현한다.
 
public void prepare() {
  vo = new PersonVO();
    }

다음과 같은 틀로서 jsp페이지에서 들어온 데이터가 상단 property로 정의한 vo에 객체를 생성하고 초기화 하며 자동 맵핑되어 데이터가 들어가게 된다.

 - Action Interface의 execute method의 Business Logic을 구현한다.

 - 마지막으로 result로 데이터를 보내주기 위한 ModelDriven 의 getModel method를 통해 result로 데이터를 전달해 준다.
result를 통해 jsp페이지에서는 데이터를 EL테그를 사용한 ${vo.property name} 으로 접근하지 않고 ${Property name} 으로 접근할 수 있게 한다.


1) checkbox : jsp페이지의 체크박스에서 체크한 것만 데이터가 들어오게 된다.

① checkbox.xml 에서 action을 선언해 주고 intercepter-ref를 선언해 준다.

------------------------------------------------------------------------------------------------------------
<?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">
      <action name="index"
              class="person.actions.IndexAction">
        <result>/person/write.jsp</result>
      </action>
      <action name="write"
              class="person.actions.WriteAction">
         <!-- struts2에서 지원하는 interceptor이름 -->
         <interceptor-ref name="checkbox">
         <!-- uncheckedValue는 예약어 :체크되지 않은 데이터는 오지 않는다.-->
          <param name="uncheckedValue">false</param>
         </interceptor-ref>
         <!-- 아래 세개는  default 이다-->
         <!-- Intercepter를 구현한 intercepor의 이름을 적어준다. -->

         <interceptor-ref name="prepare"/>
         <interceptor-ref name="modelDriven"/>
         <interceptor-ref name="params"/>
         <result>/person/result.jsp</result>
        
        
      </action>
   </package>
</struts>
------------------------------------------------------------------------------------------------------------

2) exception
exception Interceptor에는 2가지 방식이 있다.
 ① global Interceptor exception
     - 어디에서 일어나는지 모르는 exception이 발생할때

package 바로 아래 action 보다 위에 설정한다.

<global-results>
      <result name="exception">/exception/exception.jsp</result>
</global-results>
     
<global-exception-mappings>
      <!-- result에 정의되어있는 위쪽의 globla-results의 name이랑 똑같은데 찾아 들어간다. -->
      <exception-mapping result="exception" exception="java.lang.Exception"/>
</global-exception-mappings>



 ② local Interceptor exception
     - 어떠한 action에서 발생하는 에러를 처리할때
        <action>태그 사이에 기술한다.

<action name="register"
           class="com.myhome.upload.actions.UploadMultiAction"
           method="register">
      <!-- 특정액션에서 예외가 발생할 때 인터셉터를 적용한다. -->
      <exception-mapping result="exception" exception="java.lang.NullPointerException"/> 
      
      <result name="success" type="dispatcher">/WEB-INF/upload/result.jsp</result>
      <result name="error" type="dispatcher">/WEB-INF/upload/fail.jsp</result>
      <result name="exception">/exception/exception.jsp</result>
     </action>

다음과 같이 선언한 UploadMultiAction class의 register method 에서 NullPointerException이 발생할 경우 exception 이라는 result name으로 데이터가 반환된다.

에러 메시지는 ExceptionStack 라는 곳에 쌓이게 되며 jsp page 에서 ${exceptionStack} 라는 EL태그로 에러의 LOG 내용을 확인 할 수 있다.
또 struts 2 태그인 <s:actionerror/>,<s:actionmessage/>,<s:fielderror/> 들로도 Exception message를 출력할 수 있다.

Exception Message의 추가는 Actionclass의
this.addActionMessage(bean.getName() + "님이 파일 오류를 발생하였음.");
throw new NullPointerException("파일을 올려주세요");

다음과 같이 에러메시지를 추가 할 수있다.

3) parameters Interceptor

사용자로 부터 전달되는 어떠한 파라미터를 선택적으로 제어 하거나 모두 받지 않을 수 있다.

- ParameterNameAware interface : 선택적으로 파라미터를 받지 않을 수 있다.
ParameterNameAware Interface를 implements 하고 acceptableParameterName method를 구현한다.

acceptableParameterName method

public boolean acceptableParameterName(String parameterName) {       // 파마리터 이름이 name인 것을 받지 않겠다.
  if("name".equals(parameterName)){
   return false;
  }
  return true;
 }

- NoParameters Interface
  다음의 Interface를 implements 하는 것만으로 전달되는 파라미터 들을 막을 수 있다


4) Static Parameters Interceptor
jsp 페이지에서 전달되는 파라미터 값 말고 xml파일에서 데이터를 넘겨줄 수 있다.

xml 의 action 안에 다음과 같이 설정한다.

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


action class에서 param name 으로 getter와 setter를 생성해 준다.

5) time Interceptor
action 이 실행 되는 시간을 구한다.
action 태그 내에

<interceptor-ref name="timer"/>

다음과 같이 설정하면 된다.









'Framework > STRUTS 2' 카테고리의 다른 글

struts 2 - JFree Chart plugin  (0) 2009.07.08
struts 2 - Tiles Plug in  (6) 2009.07.08
struts 2 - properties 파일  (1) 2009.07.05
struts 2 - upload & download  (0) 2009.07.05
struts 2 - session 사용하기  (1) 2009.07.05

struts 2 - properties 파일

Published on: 2009. 7. 5. 16:22 by louis.dev

확장자가 properties로 끝나는 파일은 xml이 로딩될때 그에 대항하는 option값을 적용하는데 사용한다.

struts 2에 각각 xml에 대한 properties파일의 작명은

(xml파일이름)+.properties

형식으로 하게 된다.
예 ) xml파일이 upload.xml 이라고 한다면 properties 파일의 이름은 upload.properties 여야 한다.

그래야 was 가 실행이 될때 xml을 로딩하면서 이름이 같은 properties 파일의 이름을 찾아 함께 로딩하게 된다. 물론 xml과 properties 파일이 같은 패키지에 존재 해야 한다.

하지만 만약 properties 파일의 이름이 global.properties 혹은 package.properties라면 xml문서와 상관없이 어느 위치에 있던 상관없이 properties파일을 읽어 들일수 있다.

'Framework > STRUTS 2' 카테고리의 다른 글

struts 2 - Tiles Plug in  (6) 2009.07.08
struts 2 - Interceptor  (3) 2009.07.06
struts 2 - upload & download  (0) 2009.07.05
struts 2 - session 사용하기  (1) 2009.07.05
struts 2 - action을 선언한 xml에서 result property 들  (0) 2009.07.05

struts 2 - upload & download

Published on: 2009. 7. 5. 16:17 by louis.dev


작업순서
1. upload 하기 위한 library 파일을 추가한다.
www.apache.org --> commons --> io 와 FileUpload library를 다운받아 추가 한다.

2. FormBean class를 생성한다

--------------------------------------------------------------------------------------------------
package com.myhome.upload.beans;

import java.io.File;

 

public class UploadFormBean {

 //form property 설정
 private int      num;
 private String name;
 private String sex;
 private String tel;
 
 /*file upload property*/
 private File   file;
 private String fileFileName;
 private long   fileFileSize;
 private String fileContentType;

 
 
 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 File getFile() {
  return file;
 }
 public void setFile(File file) {
  this.file = file;
 }
 public String getFileFileName() {
  return fileFileName;
 }
 public void setFileFileName(String fileFileName) {
  this.fileFileName = fileFileName;
 }
 public long getFileFileSize() {
  return fileFileSize;
 }
 public void setFileFileSize(long fileFileSize) {
  this.fileFileSize = fileFileSize;
 }
 public String getFileContentType() {
  return fileContentType;
 }
 public void setFileContentType(String fileContentType) {
  this.fileContentType = fileContentType;
 }
 
 
}
--------------------------------------------------------------------------------------------------
file 을 저장하는 property 부분을 오면
private File   file;
private String fileFileName;
private long   fileFileSize;
private String fileContentType;
다음과 같이 선언되어 있는데 fileName,fileSiz,ContentType의 이름은 private File file + property 이름을 하면 자동으로 파일에 대한 정보가 맵핑이 된다.
즉 file + FileName
         + FileSize
         + Contenttype
으로 선언해야 자동으로 파일에 대한 정보가 들어가게 된다.

3. DTO를 생성한다.

4. DB에 접근할 DAO를 생성한다.

5. SqlMap 파일 생성

[option]
6. properties 파일을 만든다.
# 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

다음과 같이 생성한 후에 jsp 페이지에서 <s:text name="register.name" /> 접근하면 properties파일에 생성된 register.name이란 키 값으로 텍스트를 출력한다.

properties파일은 xml 파일의 옵션을 설정함으로서 xml파일이름+.properties 란 이름으로 지정된다. 이렇게 되었을때 xml을 로딩할때 같은 패키지에 같은 이름의 properties파일이 있게 되면 이때 같이 로딩이된다.
여기서 properties 파일 이름을 global.properties나  package.properties 파일로 지정하게 면 was가 실행될때 자동으로 로딩되어 설정을 사용할 수 있게 된다.


7. upload.xml파일 생성 후 struts.xml에 추가

8. UploadUtil class 생성

package com.myhome.upload.util;

public final class UploadUtil {
 
 public static final String SAVE = "D://JAVA/Java Web2/edu/uploadTest/";
 
 public static final long SIZE = 1024 * 1024 *20;
}


9.uploadAction class 생성
--------------------------------------------------------------------------------------------------
package com.myhome.upload.actions;

import java.io.File;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


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

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

 public static final Log log = LogFactory.getLog(UploadMultiAction.class);
 
 private UploadFormBean bean;
 private UploadDTO dto;
 /*
  * 등록부분
  * */
 public String register() throws Exception{

//jsp페이지로 들어온 정보는 bean에 저장된다.

  dto = new UploadDTO();
  BeanUtils.copyProperties(dto, bean);      //bean의 정보를 dto에 저장한다.
  if(bean.getFile() != null){
   upload();
  }else{
   dto.setFileName("");
   dto.setFileSize(0L);
  }
  new UploadDAO().insert(dto);
  return SUCCESS;
 }

 protected void upload() throws Exception{
/*bean이 참조하고 있는 파일을 실제 파일로 얻어온다.*/
  File file = new File(UploadUtil.SAVE + bean.getFileFileName());       
/*templete에는 파일을 실제파일로 복사여 폴더에 저장한다.*/
  FileUtils.copyFile(bean.getFile(), file);
   /*templete에 있는 파일을 삭제한다.*/
FileUtils.forceDelete(bean.getFile());
 
/*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;
 }
 
 
}
--------------------------------------------------------------------------------------------------


2. File Download

File Download 는 일반 html 처럼 <a>태그로 파일의 주소를 링크걸어 사용하는 것이 아니라 FileInputStream을 이용하여 사용자에게 직접 Stream을 쏴주는 방법을 채택하고 있다.

1) jsp 페이지에서 download Action 요청
jsp페이지로부터 Download Action을 요청하면 xml의 ActionMapping을 통하여 ActionClass가 실행된다.

2) ActionMpping을 수행할 xml문서를 생성한다.

<action name="download"
       class="com.myhome.upload.actions.DownloadAction"
       method = "execute">
     
      <!-- type : stream으로 설정하면 Action class의 InputStream을 받아온다  --> 
      <result name="success" type="stream">
          <param name="contentType">application/octet-stream</param> <!-- 이렇게 하지 않으면 다운로드 안된다 -->
          <param name="contentLength">${contentLength}</param>
          <param name="contentDisposition">${contentDisposition}</param>
          <param name="bufferSize">4096</param>  <!-- 버퍼사이즈 적용 -->
      </result>
     </action>
 
param-name의 이름으로 다음과 같은 값을을 jsp페이지로 리턴하게 된다. 위의 값은 Action class에서 정의한 property들이다.

3) Actios Class 생성

File을 InputStream으로 쏴줄 Class 파일이다.
이중에서 다음과 같은 프로퍼티와 getter 와 setter는 반드시 설정되어 있어야 한다.
private InputStream inputStream;
private int              contentLength;
private String          contentDisposition;

다음과 같은 프로퍼티와 getter와 setter가 있어야 Action의 다음단계인 Result로 데이터를 쏴줄수가 있게 된다.

--------------------------------------------------------------------------------------------------
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 {
     /*form param으로 설정된 파일을 받는다.*/
    String encFile = filename;
   
    /*encFile를 실제 파일로 객체를 생성한다.*/
    File file = new File(UploadUtil.SAVE+encFile);
   
    /*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;
 }
 /*decoding 처리 해줌(MS949 -> ISO 8859_1)*/
 protected String toEng(String data){
  try{
   data = new String(data.getBytes("MS949"),"ISO8859_1");
  }catch(Exception e){
   
  }
  return data;
 }
}

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

'Framework > STRUTS 2' 카테고리의 다른 글

struts 2 - Interceptor  (3) 2009.07.06
struts 2 - properties 파일  (1) 2009.07.05
struts 2 - session 사용하기  (1) 2009.07.05
struts 2 - action을 선언한 xml에서 result property 들  (0) 2009.07.05
struts 2 - validator  (0) 2009.07.03