설정 변경이 필요할 때마다 jar 를 변경하지 않도록 설정 파일등은 외부로 빼도록 해보자.

여기서는 log4j2.xml 설정을 외부로 옮기고 log도 파일로 기록되도록 설정한다.


resource 폴더의 log4j2.xml 설정파일을 수정

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
	<Appenders>
		<Console name="Console" target="SYSTEM_OUT">
			<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
		</Console>
		<File name="MyFile" filename="logs/app.log">
			<PatternLayout>
				<Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
			</PatternLayout>
		</File>
	</Appenders>
	<Loggers>
		<Root level="DEBUG">
			<!-- <appenderref ref="MyFile" /> -->
			<AppenderRef ref="Console" />
		</Root>
	</Loggers>
</Configuration>


pom.xml 의 plugin 설정 변경, jar플러그인에 열외 항목을 추가하고, resource 관리를 통해 외부 폴더로 파일을 옮겨준다.

<plugins>
	<plugin>
		<groupId>org.apache.maven.plugins</groupId>
		<artifactId>maven-jar-plugin</artifactId>
		<configuration>
			<excludes>
				<exclude>**/log4j2.xml</exclude>
			</excludes>
			<archive>
				<manifest>
					<mainClass>printTime.GetTime</mainClass>
					<addClasspath>true</addClasspath>
					<classpathPrefix>libs/</classpathPrefix>
				</manifest>
			</archive>
		</configuration>
	</plugin>
</plugins>

<resources>
	<resource>
		<directory>src/main/resources</directory>
		<targetPath>../conf</targetPath>
	</resource>
</resources>


jar를 실행해 보자. conf 파일을 외부로 뺐으므로 옵션을 선언해준다.

java -Dlog4j.configurationFile=conf\log4j2.xml -jar printTime.jar


폴더구조는 아래와 같다.


libs 폴더를 외부에 두지 않고 모든 라이브러리를 내부에 포함하고자 한다면 몇가지 플러그인을 사용하여 처리할 수 있다. shade 플러그인을 적용해 본다.

<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-shade-plugin</artifactId>
	<executions>
		<execution>
			<goals>
				<goal>shade</goal>
			</goals>
			<configuration>
				<shadedartifactAttached>true</shadedartifactAttached>
				<transformers>
					<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
						<manifestEntries>
							<Main-Class>printTime.GetTime</Main-Class>
							<Class-Path>.</Class-Path>
							<Build-Number>1</Build-Number>
						</manifestEntries>
					</transformer>
				</transformers>
			</configuration>
		</execution>
	</executions>
</plugin>

maven build > goals = "package shade:shade"


폴더구조는 아래와 같다.


libs 폴더는 jar 내부에 포함된다.



Posted by KENSIN
,

구동에 필요한 의존성 라이브러리를 모두 (외부폴더로)포함해서 jar 를 생성하도록 해본다.


pom.xml 에서 jar 플러그인을 수정하고 dependency 플러그인을 추가하고 설정한다.

<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-jar-plugin</artifactId>
	<configuration>
		<archive>
			<manifest>
				<mainClass>printTime.GetTime</mainClass>
				<addClasspath>true</addClasspath>
				<classpathPrefix>libs/</classpathPrefix>
			</manifest>
		</archive>
	</configuration>
</plugin>

<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-dependency-plugin</artifactId>
	<version>2.5.1</version>
	<executions>
		<execution>
			<id>copy-dependencies</id>
			<phase>package</phase>
			<goals>
				<goal>copy-dependencies</goal>
			</goals>
			<configuration>
				<includeScope>runtime</includeScope>
				<outputDirectory>${project.build.directory}/libs/</outputDirectory>
			</configuration>
		</execution>
	</executions>
</plugin>


libs 폴더를 추가하고 해당 폴더에 라이브러리들을 넣어 주도록 설정하였다.


jar 플러그인은 클래스패스 선언을 관리하여 MANIFEST.MF 에 넣어줄것이고, dependency 플러그인은 폴더를 생성하고 라이브러리들을 복사하여 줄것이다.


Maven build goals = package 를 진행해 보자. 


생성된 jar 의 MANIFEST.MF 를 살펴보면 아래와 같다.


Manifest-Version: 1.0

Archiver-Version: Plexus Archiver

Built-By: macdev

Class-Path: libs/log4j-api-2.11.1.jar libs/log4j-core-2.11.1.jar

Created-By: Apache Maven 3.3.9

Build-Jdk: 1.8.0_77

Main-Class: printTime.GetTime


Class-Path 가 추가된것을 확인할 수 있다.


jar가 생성된 폴더에 libs 폴더도 생성되었고 libs 폴더 내부에 로그 라이브러리들도 들어 있다.

별도의 classpath 를 불러 올 필요가 없어졌다. 실행해 보도록 하자.


java -jar printTime-1.0.0.jar

 







Posted by KENSIN
,

프로그램 실행시 작업을 수행하고 로그를 남길수 있도록 해본다.


컴파일러를 명확하게 지정하고 로그를 기록하기 위한 플러그인을 추가해 보도록 한다.


pom.xml 수정


1. 버전관리를 한곳에 모아 보기 좋도록 버전값을 속성화 한다. (root 아래)

<properties>
	<jdk.version>1.8</jdk.version>
	<log4j2.version>2.11.1</log4j2.version>
</properties>


2. logging 라이브러리 의존성 추가 (root 아래)

<dependencies>
	<dependency>
		<groupId>org.apache.logging.log4j</groupId>
		<artifactId>log4j-api</artifactId>
		<version>${log4j2.version}</version>
	</dependency>

	<dependency>
		<groupId>org.apache.logging.log4j</groupId>
		<artifactId>log4j-core</artifactId>
		<version>${log4j2.version}</version>
	</dependency>
</dependencies>


3. compile 플러그인 추가. (build > plugins 에 삽입)

<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-compiler-plugin</artifactId>
	<version>3.5.1</version>
	<configuration>
		<source>${jdk.version}
		<target>${jdk.version}</target>
	</configuration>
</plugin>


4. Maven build 실행 하면 jar 생성


jar 실행하여 확인.


java -classpath "printTime-1.0.0.jar;[경로]\log4j-api-2.11.1.jar;[경로]\log4j-core-2.11.1.jar" printTime.GetTime



현상태에서의 MANIFEST.MF 의 내용은 아래와 같다.

Manifest-Version: 1.0

Archiver-Version: Plexus Archiver

Built-By: macdev

Created-By: Apache Maven 3.3.9

Build-Jdk: 1.8.0_77

Main-Class: printTime.GetTime


폴더구조는 아래와 같다.





Posted by KENSIN
,

이클립스에서 new > maven project


create simple project 체크 하고 next


내용 입력하고 finish




프로젝트 기본 구조는 아래처럼 생성된다.



pom.xml 을 열어보면 앞서 입력한 기본정보만 등록되어 있다.



<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>org.macdev.study</groupId>
	<artifactId>printTime</artifactId>
	<version>1.0.0</version>
	<name>macdev</name>
	<description>시간출력</description>
</project>


src/main/java 에 new > class 로 자바파일을 생성한다.



package printTime;

import java.util.Calendar;

public class GetTime {
	public static void main(String[] args) {
		System.out.println(Calendar.getInstance().getTime());
	}
}

Wed Jan 09 17:20:04 KST 2019





jar 생성을 위해 pom.xml 에 maven plugin 을 추가한다. (maven-jar-plugin)


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemalocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelversion>4.0.0</modelversion>
	<groupid>org.macdev.study</groupid>
	<artifactid>printTime</artifactid>
	<version>1.0.0</version>
	<name>macdev</name>
	<description>시간출력</description>
	
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-jar-plugin</artifactId>
				<configuration>
					<archive>
						<manifest>
							<mainClass>printTime.GetTime</mainClass>
						</manifest>
					</archive>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>


메뉴에서 Run > Run As > Maven build 선택 후 대화상자의 Goals 에 "package" 라고 입력하고 Run 실행.

콘솔에 오류가 없이 정상적으로 진행이 되었다면 아래와 같이 target 에 jar 파일이 생성된다.





해당위치에서 커맨드를 입력하여 실행하여 본다.


java -jar printTime-1.0.0.jar



Posted by KENSIN
,

-- 입력받는 파라미터가 없는 메서드


import static org.junit.Assert.assertThat;
import static org.hamcrest.CoreMatchers.is;

import java.lang.reflect.Method;

import org.junit.Test;

public class ReflectTest {

    @Test
    public void testReflect() throws Exception {
        Method method = Sample.class.getMethod("getSample");
        assertThat((String) method.invoke(Sample.class.newInstance()), is("Sample"));
    }

    public static class Sample {
        public String getSample() {
            return "Sample";
        }

        public String getSample(String append) {
            return "Sample " + append;
        }
    }
}


-- 파라미터를 입력받는 메서드

import static org.junit.Assert.assertThat;
import static org.hamcrest.CoreMatchers.is;

import java.lang.reflect.Method;

import org.junit.Test;

public class ReflectTest {

    @Test
    public void testReflect() throws Exception {
        Method method = Sample.class.getMethod("getSample");
        assertThat((String) method.invoke(new Sample()), is("Sample"));
       
        method = Sample.class.getMethod("getSample", String.class);
        assertThat((String)method.invoke(new Sample(), "Test"), is("Sample Test"));
    }

    public class Sample {
        public String getSample() {
            return "Sample";
        }

        public String getSample(String append) {
            return "Sample " + append;
        }
    }
}

-- 다수의 파라미터를 받는 메서드

import static org.junit.Assert.assertThat;
import static org.hamcrest.CoreMatchers.is;

import java.lang.reflect.Method;

import org.junit.Test;

public class ReflectTest {

    @Test
    public void testReflect() throws Exception {
        Method method = Sample.class.getMethod("getSample");
        assertThat((String) method.invoke(new Sample()), is("Sample"));
       
        method = Sample.class.getMethod("getSample", String.class);
        assertThat((String)method.invoke(new Sample(), "Test"), is("Sample Test"));
       
        method = Sample.class.getMethod("getSample", String.class, int.class);
        assertThat((String)method.invoke(new Sample(), "Cut", 7), is("Cut"));
    }

    public class Sample {
        public String getSample() {
            return "Sample";
        }

        public String getSample(String append) {
            return "Sample " + append;
        }
       
        public String getSample(String append, int beginIndex){
            return getSample(append).substring(beginIndex);
        }
    }
}
Posted by KENSIN
,


가격을 가져온다.

한국 돈으로 책은 6500원 이며,

일본 돈으로 책은 650엔 이다.

다른 물건도 단순히 '원 / 10 = 엔' 의 공식으로 값이 나오도록 적용한다.


우선 테스트를 작성한다.

import static org.junit.Assert.assertThat;
import static org.hamcrest.CoreMatchers.is;

import java.lang.reflect.Proxy;

import org.junit.Test;

public class PriceTest {
    @Test
    public void getPrice(){
        Price koreanPrice = new KoreanPrice();
        assertThat(koreanPrice.getBookPrice(), is(6500));
        assertThat(koreanPrice.getCarPrice(), is(26000000));
        assertThat(koreanPrice.getPenPrice(), is(1200));
       
        Price japanPrice = (Price)Proxy.newProxyInstance(
                getClass().getClassLoader()
                , new Class[]{Price.class}
                , new JapanPrice(new KoreanPrice()));
        assertThat(japanPrice.getBookPrice(), is(650));
        assertThat(japanPrice.getCarPrice(), is(2600000));
        assertThat(japanPrice.getPenPrice(), is(120));
    }
}

Price 인터페이스

public interface Price{
    int getBookPrice();
    int getCarPrice();
    int getPenPrice();
}

원(W)화로 계산해주는 클래스

public class KoreanPrice implements Price {

    @Override
    public int getBookPrice() {
        return 6500;
    }

    @Override
    public int getCarPrice() {
        return 26000000;
    }

    @Override
    public int getPenPrice() {
        return 1200;
    }
}

Proxy를 이용해 엔화로 계산해 주기 위한 클래스

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class JapanPrice implements InvocationHandler {
    Object price;

    public JapanPrice(Object price) {
        this.price = price;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object obj = method.invoke(price, args);
        return ((Integer) obj) / 10;//단순히 10 나누기
    }
}

책값만 엔화로 계산해 주기 테스트

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class JapanPrice implements InvocationHandler {
	Object price;

	public JapanPrice(Object price) {
		this.price = price;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		Object obj = method.invoke(price, args);
		if(obj instanceof Integer && method.getName().indexOf("Book") != -1) {
			return ((Integer)obj) / 10;
		}
		return (Integer) obj;
	}
}


import static org.junit.Assert.assertThat;
import static org.hamcrest.CoreMatchers.is;

import java.lang.reflect.Proxy;

import org.junit.Test;

public class PriceTest {
	@Test
	public void getPrice(){
		Price koreanPrice = new KoreanPrice();
		assertThat(koreanPrice.getBookPrice(), is(6500));
		assertThat(koreanPrice.getCarPrice(), is(26000000));
		assertThat(koreanPrice.getPenPrice(), is(1200));
		
		Price japanPrice = (Price)Proxy.newProxyInstance(
				getClass().getClassLoader()
				, new Class[]{Price.class}
				, new JapanPrice(new KoreanPrice()));
		assertThat(japanPrice.getBookPrice(), is(650));
		assertThat(japanPrice.getCarPrice(), is(26000000));
		assertThat(japanPrice.getPenPrice(), is(1200));
	}
}

Posted by KENSIN
,