작업 시 MultipartHttpServletRequest.getFileMap() 을 사용하여, 파일을 받았다. 하지만 또 다시 호출 하였다.


이와 같은 상황에서 발생 한다. getFileMap() 이 아니라도, 비슷한 기능의 메소드 라고 하면, 같은 상황 일 것 이다. 파일 만이 아니라, IO 작업 시 getInputStream() 을 두번 호출해도 같은 상황이라고 볼 수 있다.


IO 관련 메소드는 항상 작업 시 이런 점은 주의 해야 한다.


Map<String, MultipartFile> fileMap = ((MultipartHttpServletRequest) request).getFileMap();

// Doing...

fileMap = ((MultipartHttpServletRequest) request).getFileMap(); // Error 


소스를 점검 하고, 같은 메소드를 두번 호출 하지는 않는 지 확인 하자.


개발을 할 때 기존 기능을 보존 하면서, 확장 해야 하는 경우가 있다. 원본을 어쩔 수 없이 수정 해야 할 때는 피할 수 없지만, 확장만 한다면, Proxy 를 사용 하는 경우 쉽게 확장이 가능 하다. 사용 방법을 알아 보자.


Proxy 는 기존 에 만들었던 Class 를 새로운 Class로 포장 했다고 생각 하면 쉽다.


public class Packing {

    private Target target;

    public Packing(Target target) {
        this.target = target;
    }

    // doing...

}


위 소스를 주목 하자. 포장지 에 기존 Class 를 담았다. 하지만 먼가가 부족 하다. 함수를 연결해줄 고리가 필요 하다. 그것이 InvocationHandler 이다. java.lang.reflect 패키지에서 제공 하고 있다.


포장지에 연결 고리를 달아보자.


public class Packing implements InvocationHandler {

    // doing...

    @Override
    public Object invoke(Object paramObject, Method paramMethod, Object[] paramArrayOfObject) throws Throwable {
        return paramMethod.invoke(paramObject, paramArrayOfObject);
    }

}


invoke 라는 함수를 볼 수 있다. 포장지와, 기존 Class 를 연결 시켜주는 역할을 한다.


paramObject: targetClass (기존 Class) 를 넣는다.
paramMethod: targetClass 에서 실행 하고 싶은 메소드를 넣는다.
paramArrayOfObject: targetClass 에서 실행하고 싶은 메소드의 파라미터 값을 넣는다.


위 3가지 설정을 끝내면 준비 작업은 끝났다. 3가지 정보에 따라 포장지에서 기존 Class 함수를 실행 하게 된다. 샘플을 만들어 보자.


Github: https://github.com/whitelife/whitelife-sample/tree/master/src/main/java/kr/co/whitelife/sample/proxy


  • Target
public class Target {

    public void doProcess() {
        System.out.println("doProcess.....");
    }

    public String doStringProcess(String string) {
        System.out.println("doStringProcess.....");
        return string;
    }

}

  • Packing
public class Packing implements InvocationHandler {

    private Target target;

    public Packing(Target target) {
        this.target = target;
    }

    public void doProcess() {
        try {
            System.out.println("Packing doProcess start.....");

            this.invoke(this.target, this.target.getClass().getDeclaredMethod("doProcess", new Class[]{}), new Object[]{});

            System.out.println("Packing doProcess end.....");
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }

    public void doStringProcess(String string) {
        try {
            System.out.println("Packing doStringProcess start.....");

            String result = (String) this.invoke(this.target, this.target.getClass().getDeclaredMethod("doStringProcess", new Class[]{String.class}), new Object[]{string});
            System.out.println(result);

            System.out.println("Packing doStringProcess end.....");
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }

    @Override
    public Object invoke(Object paramObject, Method paramMethod, Object[] paramArrayOfObject) throws Throwable {
        return paramMethod.invoke(paramObject, paramArrayOfObject);
    }
}

  • ProxyTest
public class ProxyTest {

    public static void main(String[] args) {
        Packing packing = new Packing(new Target());

        packing.doProcess();
        System.out.println();

        packing.doStringProcess("doString");
    }

}


샘플 작성이 끝났다면 실행 해 보자. 아래와 같은 출력을 볼 수 있다.


Packing doProcess start.....
doProcess.....
Packing doProcess end.....

Packing doStringProcess start.....
doStringProcess.....
doString
Packing doStringProcess end.....


여기 까지 왔다면, 성공 한 것이다. 기존에 각자 사용하던 Class를 Target 으로 생각하고, 포장지를 만들어서 사용하면 된다.


만약 Spring Framework 를 사용하는 경우, 직접 구현할 필요 없이 Spring AOP Around 기능을 사용하면 쉽게 처리가 가능 할 것이다. 위 샘플 코드와 비슷 하기 때문이다.


대표 적인 로그 라이브러리라 볼 수 있다. 로그를 출력 하는 Appenders 설정을 찾을 수 없기 때문에 발생 한다.


보통의 경우 classpath, Web application 의 경우 /WEB-INF/ 하위 경로 를 사용하기도 한다.


xml, properties 두 가지 스타일로 설정을 하면 된다. xml 로 설정을 해보자.
해당 파일을 추가 하자.


  • log4j.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/doc-files/log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

    <!-- Appenders -->
    <appender name="console" class="org.apache.log4j.ConsoleAppender">
        <param name="Target" value="System.out" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d %5p %c{1} - %m%n" />
        </layout>
    </appender>

    <!-- Application Loggers -->
    <logger name="kr.co.whitelife.spring">
        <level value="debug" />
    </logger>

    <!-- Root Logger -->
    <root>
        <priority value="debug" />
        <appender-ref ref="console" />
    </root>

</log4j:configuration>


Global 로그 설정 부분은 출력 할 appender 설정, 로그 레벨 설정 부분이다. Root Logger 부분을 참고 하고, 특정 package log 만 설정을 원하는 경우, Application Loggers 부분을 참고 하자.


Logger logger = LoggerFactory.getLogger(Sample.class);
logger.debug("I am {}", "boy");


테스트 코드를 실행 해보자. log 를 확인 할 수 있다.


'Java' 카테고리의 다른 글

Java Html 태그 제거 하기  (0) 2014.10.29
Java Proxy 사용하기  (0) 2014.10.13
Java Clone 사용 하기  (0) 2014.10.10
Java String.split(String regex) 사용 시 '|' 파싱 이 안되는 경우  (1) 2014.10.08
Java HashMap Key 정렬 하기  (0) 2014.09.24

PC, 노트북을 사용하면서 보통 메인 드라이브 C: 만 사용을 했다. 파일을 따로 관리가 필요한 경우에 포맷을 하지 않아도, 파티션을 나누는 작업이 가능 하다.


예전에 파티션 관리 툴을 사용해서 Windows 를 날려먹은 적이 있지만, 기본적으로 제공 하는 기능 이기 때문에 그럴일은 없다고 생각 한다. 적용 해보도록 하자.


1. 컴퓨터 관리


내 컴퓨터 > 마우스 오른쪽 > 관리 화면 으로 이동 하자.



사용하고 있는 C: 클릭 후 > 마우스 오른쪽 > 볼륨 축소 클릭


2. 볼륨 축소


축소할 공간을 입력하면, 사용하고 있는 C: 의 공각이 줄어 든다.



완료 되면 할당되지 않은 상태로 공간이 확보 된다.


3. 볼륨 만들기


할당 되지 않은 상태 > 마우스 오른쪽 > 볼륨 만들기 클릭



단순 볼륨 만들기 마법사를 진행 한다. 가이드에 따라, 드라이브 문자 할당, 볼륨 레이블에 사용할 명칭을 정해주자. 아래와 같이 만들어진 모습을 볼 수 있다.



D: 가 새로 만들어졌다. 따로 관리할 파일들을 복사 하러 가자.


'IT' 카테고리의 다른 글

개발자에 대한 고찰  (0) 2017.05.02
Windows 7 최대 절전 모드 해제 하기  (0) 2014.10.20
IT 전문가를 공포에 떨게 하는 한마디  (0) 2013.11.08
씨게이트 통큰 이벤트~~  (0) 2013.05.27
야근은 스포츠...  (0) 2013.03.14

JSP Form 태그의 enctype="multipart/form-data" 속성을 적용 하지 않은 경우 발생 한다.


해당 속성을 추가 하도록 하자.


원본 데이터의 보존이 중요 시 되는 경우, 사용하게 된다. 복제 기능에 대해서는 Cloneable 라는 Interface 를 구현 해야 한다.


public abstract interface Cloneable {
}


Object 클래스에 정의 되어 있다. 용도에 따라 얼마든지 Override 해서 사용 하면 된다.


protected native Object clone() throws CloneNotSupportedException;


접근 제한자가 protected 로 되어 있기 때문에, 외부에서는 접근이 불가능 하므로 아래와 같이 선언 해야 외부에서 사용이 가능 하다. Cloneable Interface 를 implements 하지 않았을 경우, java.lang.CloneNotSupportedException 이 발생 하니 주의 하자.


public class Model implements Cloneable {

    // Doing...

    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}


메소드 정의가 끝났다면, clone() 을 호출 하여 사용 하도록 하자.


문자열 구분자 | 사용 하는 경우 파싱이 안될 때가 있다.


System.out.println(Arrays.toString("test|test|test|".split("|")));


각 각 하나씩 파싱이 되어 원하는 결과를 얻을 수 없다.


[, t, e, s, t, |, t, e, s, t, |, t, e, s, t]


수정 후 실행 해 보자.


System.out.println(Arrays.toString("test|test|test|".split("\\|")));


원하는 결과를 얻을 수 있다.


[test, test, test]


Tomcat의 Servlet 개발 시 HttpSession 클래스를 사용 한다. Session Timeout 설정을 위해서는, setMaxInactiveInterval(int interval) 함수를 사용해서 개별적으로 정해줄 수 있지만, 공통으로 사용할 수 있게 설정을 하는 편이 좋다. web.xml 에 아래 샘플을 추가 하자.


<session-config>
    <session-timeout>30</session-timeout>
</session-config>


session-timeout 은 분 단위로 설정 된다. 30 이라고 선언했다면 getSession() 할때 마다 Session 유효 시간은 30분 이다.

session 이 created, destoryed 되는 것을 확인 하고 싶을 때가 있을 것이다. HttpSessionListener 를 구현하면 확인이 가능하다.


  • HttpSessionCheckingListener.java
public class HttpSessionCheckingListener implements HttpSessionListener {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    public void sessionCreated(HttpSessionEvent event) {
        if (logger.isDebugEnabled()) {
            logger.debug("Session ID".concat(event.getSession().getId()).concat(" created at ").concat(new Date().toString()));
        }
    }

    public void sessionDestroyed(HttpSessionEvent event) {
        if (logger.isDebugEnabled()) {
            logger.debug("Session ID".concat(event.getSession().getId()).concat(" destroyed at ").concat(new Date().toString()));
        }
    }
}


위 파일을 web.xml 에 등록 할 차례다.


<listener>
    <listener-class>kr.co.whitelife.web.mvc.listener.HttpSessionCheckingListener</listener-class>
</listener>


Tomcat Start 한 후 로그를 살펴 보자. 생성되는 부분, 소멸되는 부분 확인이 가능하다.


created
2014-10-07 14:06:05,957  DEBUG HttpSessionCheckListener - Session IDD31C36AE223F8C14BB1087F6BFCEBD35 created at Tue Oct 07 14:06:05 KST 2014
destroyed
2014-10-07 14:08:06,068  DEBUG HttpSessionCheckListener - Session IDD31C36AE223F8C14BB1087F6BFCEBD35 destroyed at Tue Oct 07 14:08:06 KST 2014

참고 사이트


+ Recent posts