2014년 1월 10일 금요일

[전자정부] XmlView 사용설정하기

1. Maven - pom.xml 설정

 org.springframework
 spring-oxm
 3.0.5.RELEASE


 com.thoughtworks.xstream
 xstream
 1.4.4

2. egov-com-servlet.xml 설정








    
     
      
          
      
     
        
        
    


3. XmlVO 생성
Annotation설정만으로 XML태그명을 설정할 수 있다.@XStreamImplicit(itemFieldName="item")로 선언된 ArrayList의 변수들은 하위의 childNode로 <변수명>값</변수명>으로 자동변환된다.
package kr.kca.olap.bp.service;

import java.util.ArrayList;
import java.util.List;

import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamImplicit;

@XStreamAlias("items")  //XML의 Root Node명
public class TplanDemdChartVO {
 
 @XStreamImplicit(itemFieldName="item")
 List chartVOList = new ArrayList();

 public List getChartVOList() {
  return chartVOList;
 }

 public void setChartVOList(List chartVOList) {
  this.chartVOList = chartVOList;
 }
 
}
4. Controller에서 사용하기
@RequestMapping(value="/olap/bp/getXmlTplanDemdSurvSttsList.do")
public ModelAndView getXmlTplanDemdSurvSttsList(@ModelAttribute("searchVO") TplanDemdSurvSttsDefaultVO searchVO, 
  ModelMap model) throws Exception {
 
 ModelAndView modelAndView = new ModelAndView("xmlView");  //xmlView로 선언된 ModelAndView를 생성한다.
 
 TplanDemdChartVO chartVO = new TplanDemdChartVO();
 chartVO.setChartVOList(tplanDemdSurvSttsService.selectTplanChartList(searchVO));
 
    modelAndView.addObject("xmlData", chartVO);
    
    return modelAndView;
}
5. XmlView 결과

 
  Jan
  900
 
 
  Feb
  1400
 
 
  Mar
  1500
 
 
  Apr
  1900
 
 
  May
  1400
 

이와같이 간단한 설정으로 XmlView를 사용할 수 있다.

[전자정부] Spring i18n 국제화 Locale Resolver

Spring 국제화 Locale 설정 시 유의사항



    



 


 
 
  1
 
 
    
        
       


2014년 1월 3일 금요일

[전자정부] 동시접속 제한을 위한 SessionListener #2

#properties 파일은 /WEB-INF/classes/session.properties.

#Max 동접자수
maxSessionValidCount=1000


WEB.xml에 Listener 등록 /WEB-INF/web.xml에 #1 의 SessionListener 등록


   
   SessionRetrieveListener
   kr.kca.pm.main.SessionListener


Java 단에서 예외사항 처리
//로그인 세션정보 Listener에 전달
HttpSession session = request.getSession();
sessionListener.setLoginSession(session);

//로그아웃 세션정보 Listener에 전달
HttpSession session = request.getSession();
sessionListener.setLogoutSession(session);

/** 동시접속자 접속(대기)를 위한 Listener 생성 */
SessionListener sessionListener = new SessionListener();

//로그인 세션 갯수를 호출하는 메소드로 동시접속자를 제한하자!
if(sessionListener.isMaxLoginSessions()) {
   
   /* 로그인 시 maxLoginSession 갯수보다 많을경우 예외사항 처리 */
   ctx.makeErrorResult("현재 동시접속자수가 많습니다. 잠시후에 이용하기시 바랍니다.");
   return;
}

[전자정부] 동시접속 제한을 위한 SessionListener #1

package kr.kca.pm.main;

import java.io.InputStream;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Properties;

import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

/**
 * 동시 접속자 세션관리 HttpListener
 * /WEB-INF/classes/session.properties 설정파일을 참조
 * 동시접속자 허용수를 setting 할 수 있도록 함. (제한접속자 수를 늘려야 할 경우 클래스 Compile없이 사용하도록)
 * Site 접속시점 세션생성 
 * Site 로그인시점 세션생성을 분리하여 접속자 수 Counting!
 * 
 * @author bcchung
 * @since 2013.07.15
 * @version 1.0
 * @see
 * 
 * 개정이력(Modification Information) >>
 *   
 *   수정일         수정자           수정내용
 *  -------       --------    ---------------------------
 *  2013.07.15    정백철          최초 생성
 * 
 */
public class SessionListener implements HttpSessionListener {
 public static SessionListener sessionManager = null;
 public static Hashtable sessionMonitor;
 public static Hashtable loginSessionMonitor;
 public static int maxSessionValidCount;

 public SessionListener() {
  if (sessionMonitor == null) sessionMonitor = new Hashtable();
  if (loginSessionMonitor == null) loginSessionMonitor = new Hashtable();
  sessionManager = this;
  
  Properties prop = new Properties();
  try {
   InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("session.properties");
   prop.load(inputStream);
  } catch (Exception e) {
   maxSessionValidCount = 300;
   e.printStackTrace();
  }
  
  maxSessionValidCount = Integer.parseInt((String) prop.get("maxSessionValidCount"));
//  System.out.println(" ########################### maxSessionValidCount : " + maxSessionValidCount);
 }

 public static synchronized SessionListener getInstance() {
  if (sessionManager == null)
   sessionManager = new SessionListener();
  return sessionManager;
 }

 /** 현재 활성화 된 session의 수를 반환한다. */
 public int getActiveSessionCount() {
  return sessionMonitor.size();
 }

 /** 현재 등록된 session의 id목록을 반환한다. */
 public Enumeration getIds() {
  return sessionMonitor.keys();
 }
 
 /** 전체 세션갯수를 측정하여 로그인(대기)상태 메세지 창 호출 */
 public boolean isMaxLoginSessions() {
  boolean retVal = false;
  
  if(maxSessionValidCount <= getActiveLoginSessionCount()) {
   retVal = true;
  }
  
  return retVal;
 }
 
 /** 현재 활성화 된 session의 수를 반환한다. */
 public int getActiveLoginSessionCount() {
  return loginSessionMonitor.size();
 }
 
 /** 로그인한 Session Put */
 public void setLoginSession(HttpSession session) {
  synchronized (loginSessionMonitor) {
   loginSessionMonitor.put(session.getId(), session);
   
   System.out.println(" ############################################################################### ");
   System.out.println(" # 접속자 (로그인 허용인원수) : " + maxSessionValidCount + " 명#");
   System.out.println(" # 접속자 (사이트 접속자수) : " + getActiveSessionCount() + " 명#");
   System.out.println(" # 접속자 (로그인 사용자수) : " + getActiveLoginSessionCount() + " 명#");
   System.out.println(" ############################################################################### ");
  }
 }
 
 /** 로그아웃한 Session Remove */
 public void setLogoutSession(HttpSession session) {
  synchronized (loginSessionMonitor) {
   loginSessionMonitor.remove(session.getId());
  }
 }

 /**
  * 현재 등록된 session중 현재 접속된 사용자 정보와 중복 여부 확인 후 중복 접속 이면 이전의 세션을 소멸 시킨다.
  */
 /*public boolean checkDuplicationLogin(String sessionId, String userEeno) {
  boolean ret = false;
  Enumeration eNum = sessionMonitor.elements();
  System.out.println("session count : " + getActiveSessionCount());
  while (eNum.hasMoreElements()) {
   HttpSession sh_session = null;
   try {
    sh_session = (HttpSession) eNum.nextElement();
   } catch (Exception e) {
    continue;
   }
   UserModel baseModel = sh_session.getAttribute("UserInfo");
   if (baseModel != null) {
    if (userEeno.equals(baseModel.getUserId_())
      && !sessionId.equals(sh_session.getId())) {
     // 전달 받은 사번과(userEeno) 기존 세션값 중 사번이 중복 되면
     // 기존 세션을 소멸 시킨다.
     // 사용자 로그아웃 이력(중복접속)을 저장한다.
     try {
      HashMap param = new HashMap();
      param.put("usrId", baseModel.getUserId_());
      param.put("ipAddr", baseModel.getRemoteIp_());
      param.put("logKind", "LOGOUT");
      param.put("logRsn", "DUPLICATE");
      // DB 처리
      xxxxxxxx.insertLoginLog(param);

     } catch (Exception e) {
      e.printStackTrace();
     }
     // 해당 세션 무효화
     sh_session.invalidate();
     ret = true;
     break;
    }
   }
  }
  return ret;
 }*/

 /** 세션 생성시 이벤트 처리 **/
 public void sessionCreated(HttpSessionEvent event) {
  HttpSession session = event.getSession();
  synchronized (sessionMonitor) {
   sessionMonitor.put(session.getId(), session);
   
   System.out.println(" ############################################################################### ");
   System.out.println(" # 접속자 (로그인 허용인원수) : " + maxSessionValidCount + " 명#");
   System.out.println(" # 접속자 (사이트 접속자수) : " + getActiveSessionCount() + " 명#");
   System.out.println(" # 접속자 (로그인 사용자수) : " + getActiveLoginSessionCount() + " 명#");
   System.out.println(" ############################################################################### ");
  }
 }

 /** 세션 소멸(종료)시 이벤트 처리 **/
 public void sessionDestroyed(HttpSessionEvent event) {
  HttpSession session = event.getSession();
  synchronized (sessionMonitor) {
   sessionMonitor.remove(session.getId());
   loginSessionMonitor.remove(session.getId());
   
   System.out.println(" ############################################################################### ");
   System.out.println(" # 접속자 (로그인 허용인원수) : " + maxSessionValidCount + " 명#");
   System.out.println(" # 접속자 (사이트 접속자수) : " + getActiveSessionCount() + " 명#");
   System.out.println(" # 접속자 (로그인 사용자수) : " + getActiveLoginSessionCount() + " 명#");
   System.out.println(" ############################################################################### ");
  }
 }
}

[전자정부] Double Submit 방지 Token

전자정부 프레임워크를 사용하면서 새로고칭(F5)시, 이전 request가 중복 submit이 되는 현상이 발생한다. 
SessionStatus를 사용하여 처리하는 방법도 있지만, 잘 되지 않았다. (조금더 알아봐야 할듯.) 
웹 검색을 하다가 우연히 예전에 Struts 1.x 버전에서 Form에 Token값을 이용하여 중복 submit을 방지할 수 있는 방법을 찾아내서 나름대로 커스터마이징하였다.
package egovframework.com.cmm;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

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

import org.apache.log4j.Logger;

import egovframework.rte.fdl.idgnr.impl.Base64;

/**
 * Double Submit 방지 Token 생성 클래스
 * 
 * @author bcchung
 * @since 2013.04.04
 * @version 1.0
 * @see
 * 
 *      
 * << 개정이력(Modification Information) >>
 *   
 *   수정일         수정자           수정내용
 *  -------       --------    ---------------------------
 *  2013.04.04    정백철          최초 생성
 * 
 * 

 */
public class TokenMngUtil {
 
 private static final String TOKEN_KEY = "TOKEN_KEY";
 private static final Logger logger = Logger.getLogger(TokenMngUtil.class.getName());

 /**
  * 로직처리를 위해 세션과 request에 Token 생성
  * 
  * @param request
  */
 public static void saveToken(HttpServletRequest request) {
  HttpSession session = request.getSession(true);
  long systemTime = System.currentTimeMillis();
  byte[] time = new Long(systemTime).toString().getBytes();
  byte[] id = session.getId().getBytes();
  
  try {
   MessageDigest SHA = MessageDigest.getInstance("SHA-256");
   SHA.update(id);
   SHA.update(time);

   String token = Base64.encode(SHA.digest());
   request.setAttribute(TOKEN_KEY, token);
   session.setAttribute(TOKEN_KEY, token);
   
   logger.error("#########################################################################");
   logger.error("# Generate Token Key Value = " + token + " #");
   logger.error("#########################################################################");
   
  } catch (NoSuchAlgorithmException e) {
   e.printStackTrace();
  }
 }

 /**
  * 로직처리 이후 중복방지를 위해 세션의 Token 초기화
  * 
  * @param request
  */
 public static void resetToken(HttpServletRequest request) {
  HttpSession session = request.getSession(true);

  try {
   session.removeAttribute(TOKEN_KEY);
  } catch (Exception e) {
   e.printStackTrace();
  }
 }

 /**
  * 세션과 request의 Token이 동일한지 비교
  * 
  * @param request
  * @return
  */
 public static boolean isTokenValid(HttpServletRequest request) {
  HttpSession session = request.getSession(true);
  String requestToken = request.getParameter(TOKEN_KEY);
  String sessionToken = (String) session.getAttribute(TOKEN_KEY);

  if (requestToken == null || sessionToken == null) {
   return false;
  } else {
   return requestToken.equals(sessionToken);
  }
 }
}
JSP
" />
Business Logic Controller
//조회화면
@RequestMapping("/cop/bbs/addBoardArticle.do")
public String addView() {
 /* 중복방지 Token 생성 */
 TokenMngUtil.saveToken(request);
}

//등록
@RequestMapping("/cop/bbs/insertBoardArticle.do")
public String add() {
 /* 중복방지 Token 체크 */
 if(!TokenMngUtil.isTokenValid(request)) {
  model.addAttribute("message", egovMessageSource.getMessage("errors.reflesh.notPermit"));
  return "uat/uia/EgovLoginUsr";
 }

 //등록 Impl 서비스
 insertArticle(boardVO);

 /* 중복방지 Token 초기화 */
 TokenMngUtil.resetToken(request);

}

EXPDP - SQL PUMP DUMP사용법


#sqlplus / as  sysdba
sql> SELECT * FROM DBA_DIRECTORIES;

sql> CREATE OR REPLACE DIRECTORY DP_DIR AS "경로";
sql> GRANT READ, WRITE ON DIRECTORY DP_DIR TO 사용자;


--DUMP.PAR 작성
SCHEMAS=KCA_RUN
DIRECTORY=DATA_PUMP_DIR
DUMPFILE=kca_run.dmp
LOGFILE=kca_run.log
EXCLUDE=TABLE:"IN ('TZIP_CCW', 'TZIP_CTPV', 'TZIP_EMD', 'TZIP_LNDN', 'TZIP_LNDN_ENTR', 'TZIP_ROAD', 'TZIP_ROAD_ENTR')"

--실행
sql> expdp ID/PW PARFILE=DUMP.PAR

SQL*LOADER 사용법


작업파일.ctl

LOAD DATA
INFILE '/oradata/juso/00.txt'
INFILE '/oradata/juso/01.txt'
INFILE '/oradata/juso/02.txt'
INFILE '/oradata/juso/03.txt'
INFILE '/oradata/juso/04.txt'
INFILE '/oradata/juso/05.txt'
INFILE '/oradata/juso/06.txt'
INFILE '/oradata/juso/07.txt'
INFILE '/oradata/juso/08.txt'
INFILE '/oradata/juso/09.txt'
INFILE '/oradata/juso/10.txt'
INFILE '/oradata/juso/11.txt'
INFILE '/oradata/juso/12.txt'
INFILE '/oradata/juso/13.txt'
INFILE '/oradata/juso/14.txt'
INFILE '/oradata/juso/15.txt'
INFILE '/oradata/juso/16.txt'
APPEND
INTO TABLE TZIP_LNDN_ENTR
#컬럼 Mapping
FIELDS TERMINATED BY '|'
(STTT_DONG_CODE, CTPV_NM, CCW_NM, STTT_EMD_NM, STTT_RI_NM, MNT_TYPE, LNDN_MAIN_NO, LNDN_SUB_NO, ROAD_NM_CODE, ROAD_NM, UDGR_TYPE, BULD_MAIN_NO, BULD_SUB_NO, BULD_NM, DTL_BULD_NM, BULD_MNG_NO, EMD_SRL_NO, ADTV_DONG_CODE, ADTV_DONG_NM, ZPCD, ZPCD_SRL_NO, MASS_TDST_NM, MVNT_RSN_CODE, CHNG_DATE, CHNG_BF_ROAD_NM_ADDR, CCW_BULD_NM, CLBR_HOUSE_TYPE)



SQL>sqlldr ID/PW control="작업파일.ctl"

Oracle Tablespace 변경방법

테이블스페이스를 변경하는 방법을 정리한다.



/* 
 * 1. 테이블의 TABLESPACE변경 방법은 다음과 같다.
 * ALTER TABLE 테이블명 MOVE TABLESPACE 테이블스페이스명;
 *
 */

SELECT 'ALTER TABLE ' || SEGMENT_NAME || ' MOVE TABLESPACE 테이블스페이명;'
FROM USER_SEGMENTS
WHERE SEGMENT_TYPE = 'TABLE';



/* 
 * 2. 두번째 INDEX의 TABLESPACE 변경.
 * ALTER INDEX 인덱스명 REBUILD TABLESPACE 테이블스페이스명;
 *
 */
SELECT 'ALTER INDEX ' || SEGMENT_NAME || ' REBUILD TABLESPACE 테이블스페이명;'
FROM USER_SEGMENTS
WHERE SEGMENT_TYPE = 'INDEX';

/* 
 * 3. LOBINDEX, LOG SEGMENT의 TABLESPACE변경
 * ALTER INDEX 인덱스명 REBUILD TABLESPACE 테이블스페이스명;
 * 테이블의 TABLESPACE를 변경해도 해당계정의 TABLESPACE사용정보를 조회하면 몇가지가 나온다.
 * LOBINDEX, LOG SEGMENT의 테이블스페이스 정보들이다.
 *
 */
SELECT * 
FROM DBA_SEGMENTS
WHERE OWNER = '사용자계정';


ALTER TABLE 테이블명 MOVE LOB ( 컬럼1, 컬럼2 ) STORE AS ( TABLESPACE 테이블스페이스명 );
DBA_SEGMENTS에 SELECT한 결과를 보니 하나의 테이블에 여러개의 LOB을 사용하면 행으로 나온다.

SELECT 'ALTER TABLE ' || TABLE_NAME || ' MOVE LOB (' || 
               SUBSTR (XMLAGG (XMLELEMENT (A, ',' || COLUMN_NAME)).EXTRACT ('//text()'),2) || ')
               STORE AS ( TABLESPACE 테이블스페이스명 );'
FROM DBA_LOBS
WHERE OWNER = '사용자계정'
GROUP BY TABLE_NAME;

TAR 압축해제하기 (IBM AIX)

TAR로 묶고 GZIP으로 압축하기

$tar cvf filename.tar file1
$gzip filename.tar

압축해제 한방

$ tar cvf - /XXX | gzip -c > XXX.tar.gz
$ gzip -dc XXX.tar.gz | tar xvf -


TAR 특정폴더 제외(IBM AIX운영체제)

$ ls /path/to/logs/* > /path/to/excludefile
$ tar -cvf /path/to/tar/new.tar -X /path/to/excludefile /path/to/source/dir