Quantcast
Channel: Uncle Bae's Story
Viewing all 50 articles
Browse latest View live

[Spring Junit] Transaction Rollback with Junit

$
0
0
JUnit 테스트시에 DB설정은 다음과 같다.


  1. DataSource 설정
  2. Transaction 설정 
  3. Junit 테스트 수행. 

이때 DB에 입력 및 삭제 테스트를 진행하면 실제로 데이터가 DB로 입력되거나, 삭제가 발생한다.
이를 선택적으로 수행할 수 있는 방법은 다음과 같다.

@Log4j
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {
DBConfiguration.class
})
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
@Transactional
Bla... Bla... TestCodes.....

상기 코드에서 @TransactionConfiguration 부분의 프로퍼티 값으로 2가지 설정을 해준다.

  • transactionManager : 어느 트랜잭션매니저를 이용할 것인지 기술한다. 
  • defaultRollback : 기본 롤백 정책을 입력한다. (true : 롤백진행, false : 롤백없이 바로 CUD진행)
그리고 중요한 것은 @Transactional을 꼭 입력해야한다는 사실..
이 어노테이션은 해당 테스트가 트랜잭션 하에서 수행하게 할 것인지 지정해주는 것이니...
당. 연. 히 넣어주는 쎈스. 



[MySQL] 유용한 커맨드 정리

$
0
0

2016.07.18

상세 칼럼 노출하기. 

show full columns from <tablename>;

날짜 변환하기

DATE_FORMAT(date, format)
FormatDescription
%a주말을 약자로 보여준다. (Sun-Sat)
%b각 월을 약어 표시로 노출한다. (Jan-Dec)
%c월을 숫자로 표현한다. (0-12)
참고, 1자리는 한자리수로만 표현됨 0이 없음 
%D영어의 서수 표현식으로 th가 붙는다.
날짜가 표시된다. (0th, 1st, 2nd, 3rd)
%d일을 표시한다. (00-31)
%e일을 표시한다. (0-31)
참고, 1자리는 한자리수로만 표현됨 0이 없음 
%f마이크로세컨드 (000000-999999)
%H시간 (00-23)
24시간제 
%h시간 (01-12)
12시간제 
%I시간 (01-12)
%i분, 숫자 (00-59)
%j년간 일자 (001-366)
%k시간 (24시간제) 1자리수 표시 (0-23)
%l시간 (12시간제) 1자리수 표시
%M월 이름 (January-December)
%m월, 숫자 (00-12)
%pAM or PM
%r시간, 12시간제 (hh:mm:ss 으로 AM, PM으로 구분가능)
%S초 (00-59)
%s초 (00-59)
%T시간 24시간제 (hh:mm:ss)
%U주 (00-53), 매 주의 첫번째는 Sunday이다. 
%u주 (00-53) 주의 첫번째는 Monday이다. 
%V주 (01-53) 주의 첫번재는 Sunday이다. 이는 %X와 함게 사용된다. 
%v주 (01-53) 주의 첫번재는 Monday이다. 이는 %x와 함께 사용된다. 
%W주의 이름을 노출한다. (Sunday-Saturday)
%w주의 날을 표시한다. (0=Sunday, 6=Saturday)
%X년간 주를 표시한다. 주의 첫번째는 Sunday이다. 4개의 숫자로 %V와 같이 사용한다. 
%x년간 주를 표시한다. 주의 첫번째는 Monday이다. 4개의 수로 %v와 함께 사용한다. 
%Y년, 숫자로 4자리 표현 
%y년, 숫자로 2자리 표현 

Sample :

SELECT DATE_FORMAT(NOW(), '%Y%m%d');
'20160718'
SELECT DATE_FORMAT(NOW(), '%Y-%m-%d');
'2016-07-18'
SELECT DATE_FORMAT(NOW(), '%Y-%c-%e');
'2016-7-18'

날짜연산 : 

한시간전
SELECT DATE_ADD(now(), interval -1 hour);
하루전
SELECT DATE_ADD(now(), interval -1 day);
한달전
SELECT DATE_ADD(now(), interval -1 month);






[독후감] 새스고딘의 시작하는 습관

$
0
0

새스고딘의 시작하는 습관


진리의 길을 걷는 사람이 저지를 수 있는
두 가지 실수가 있다.
하나는 끝까지 가지 않는 것이고,
다른 하나는 시작하지 않는 것이다.
_고타마 싯다르타 

위의 글에서 난 3가지 중요한 키워드를 발견했다.
하나는 시작하지 않는것.
하나는 끝까지 가지 않는것.
그리고 마지막으로 진리의 길을 가는것.

시작하자. 무엇이든 시작하자. 하지만 그것이 나의 진리의 길의 일부가 되어 주어야한다.
그리고 한번 시작했으면 끝을 내야 한다. 중간에 멈추는 것은 충분히 사력을 다해 노력하지 않은 것이다.
왜 시작하지 않고, 왜 시작한 일을 끝내지 않고 중간에 멈추는가? 사력을 다해 노력하지 않는가?
그것은 진리의 길에 대한 강한 믿음이 없기 때문이다.

진리의길 난 이것이 why라고 생각한다.
why 나는 왜 존재하는가? 나는 왜 이것을 하려하는가? 내가 해야만 하는 이유는 무엇인가?
그것을 아는순간 우리는 움직이지 않을수 없다. 시작하지 않을 수 없고, 그것을 끝내지 않을 수 없다.

그러한 why라는 물음에 대한 동기로 부터 시작하고 끝을 내자.
why에 부합하지 않는 것이라면 시작하지 않는것이 좋다. 설령 시작했더라도 빨리 멈추는 법도 알아야한다.

"예전 중국의 한 마을에 천리마를 가진 부자가 잇었다.
그는 그 천리마가 끄는 수레를 타고 어디론가 열심히 달리고 있었다.
지나가는 마을의 한 농부가 그 부자를 보고 물었다.
대인은 지금 어디를 그렇게 열심히 달려가시오?
그러자 부자는 나는 현명하기로 소문난 아무개를 만나러 가는 중이외다..
농부는 그사람은 당신이 가는 반대 방향에 살고 있는데 이리로 가면 어떻게 하시오?
그러자 부자는 괞찮소이다. 나에게는 하루에 천리를 가는 최고의 명마가 있으니 열심히 달려가면 될것이오 라고.."

Why를 명확히 한 사람은 자신이 갈 수 있는 최선의 길을 간다. 그리고는 끝내 도달하게 된다.
Why에 맞는 무엇이든 실행하되, 아무거나 실행하지말자.

-- 엉클배 --

Blog Scheme

GIT pull 오류

$
0
0
Git을 이용하여 pull을 수행할때 다음과 같은 오류가 날 수 있다.

오류상황 :
error: unable to resolve reference refs/remotes/origin/xxxx_file: No such file or directory
From git+ssh://remoteserver/~/test
! [new branch] xxxx_file -> origin/xxxx_file (unable to update local ref)
error: unable to resolve reference refs/remotes/origin/split-css: No such file or directory
! [new branch] xxxx_file2
-> origin/xxxx_file2 (unable to update local ref)

다음 명령어를 이용하면 불필요하게 꼬인 파일을 제거하여 정상으로 pull을 당길 수 있다.
$ git gc --prune=now
$ git remote prune origin

Java9 새로운 기능

$
0
0

from : http://www.journaldev.com/13121/java-9-features-with-examples

1. Java9 다운로드 받는곳 

https://jdk9.java.net/download/

2. JAVA9의 주요 기능 

2.1 Java 9 REPL [Read Evaluate Print Loop] : (JShell)

- Java 9 는 REPL이라는 jShell을 제공한다.
- 이를 통해 자바도 인터렉티브한 테스트와 실행을 할 수 있다.
KIDOui-iMac:~ KIDO$ jshell
|  Welcome to JShell -- Version 9-ea
|  For an introduction type: /help intro
jshell> int a = 10
a ==> 10

jshell> System.out.print  <-- tab click..
print(     printf(    println(

jshell> System.out.println(a)
10


2.2 Immutable List, Set, Map, Map.Entity를 위한 Factory 메소드 제공

- Immutable 자료구조를 생성하기 위한 편의 Factory메소드를 제공하고 있다.
- java8 이전 버젼에서는 Collections.unmodifiableXXX라는 기능을 이용하여 이러한 불변 자료구조를 만들었다.
Collections.unmodificableList
- 이제는 Collections객체의 of메소드를 이용하여 이러한 자료구조를 편하게 생성할 수 있다.
jshell> List testImmutableList = List.of()
testImmutableList ==> []

jshell> testImmutableList.add <-- tab click..
add(      addAll(

jshell> testImmutableList.add(10)
|  Warning:
|  unchecked call to add(E) as a member of the raw type java.util.List
|  testImmutableList.add(10)
|  ^-----------------------^
|  java.lang.UnsupportedOperationException thrown:
|        at ImmutableCollections.uoe (ImmutableCollections.java:70)
|        at ImmutableCollections$AbstractImmutableList.add (ImmutableCollections.java:76)
|        at (#4:1)
jshell> List<Long> testLongImmutableList = List.of()
testLongImmutableList ==> []
jshell> testLongImmutableList.add(10L)
|  java.lang.UnsupportedOperationException thrown:
|        at ImmutableCollections.uoe (ImmutableCollections.java:70)
|        at ImmutableCollections$AbstractImmutableList.add (ImmutableCollections.java:76)
|        at (#6:1)

- 위 에제를 보면 불변의 자료구조라 값을 넣을 수 없다는 것을 알 수 있다.
jshell> List testDefaultStringImmutableList = List.of("Kido", "Kirog", "Uncle", "Bob")
testDefaultStringImmutableList ==> [Kido, Kirog, Uncle, Bob]
- Map은 다음과 같이 지정하면된다.
jshell> Map testMap = Map.of()
testMap ==> {}


jshell> testMap.put("1", "test")
|  Warning:
|  unchecked call to put(K,V) as a member of the raw type java.util.Map
|  testMap.put("1", "test")
|  ^----------------------^
|  java.lang.UnsupportedOperationException thrown:
|        at ImmutableCollections.uoe (ImmutableCollections.java:70)
|        at ImmutableCollections$AbstractImmutableMap.put (ImmutableCollections.java:557)
|        at (#9:1)

jshell> Map testDefaultValueMap = Map.of("1", "Kido", "2", "Kirog", "3", "Uncle", "4", "Bae")
testDefaultValueMap ==> {4=Bae, 3=Uncle, 2=Kirog, 1=Kido}

2.3 Interface 의 method를 private로 지정 가능 

- Java8에서는  Interface에 default메소드를 제공했다. 이는 Default, Static으로 제공되었으나 public 접근 제한자를 지원했다.
- Java9에서는 private 메소드를 제공한다. private메소드, 그리고 private static메소드를 제공한다.

public interface Card {
    private Long createCard() {
        // 내용구현하기.
    }
    private static void displayCardDetails() {
        // 여기에서 내용 구현하기.
    }
}

2.4 Module System 

- Java9 기능 중에서 가장 큰 변화중의 하나는 Module System.
- Modular JDK
- Modular Java Source Code
- Modular Run-time Image
- Encapsulate Java Internal APIs
- Java Platform Module System 
Java 9 이전버젼은 획일적인 Jar을 이용하여 자바 기반 어플리케이션을 개발했었다. 이것은 제약이 많고 결점이 있다. 이를 해결하기 위한 기능으로 Module System을 채택하였다.

- 자세한것은 쩜더 공부해서 추가하기.

2.5 Process API 향상

- Java 9에서는 Process API에 대한 향상을 제공한다. 이를 위해 새로운 클래스들과 메소드 들을 제공하며, 이것은 OS Process 컨트롤과 관리를 쉽게 해준다.

- Java.lang.ProcessHandle
- Java.lang.ProcessHandle.Info
example :
jshell> ProcessHandle handle = ProcessHandle.current()
handle ==> 53386
jshell> System.out.println("PID " + handle.getPid())
PID 53386

2.6 Try-With-Resources 향상

- Java7 에서는 새로운 예외 처리를 위한 구문인 : Try-With-Resource로 리소스를 자동적으로 관리 하는 것을 소개하였다. 이를 사용하는 이유는 더 낳은 리소스 관리를 위한 것이다.

- Java9 버젼에서는 장황한 코딩을 막고 더 읽기 쉽도록 개선되었다.
void testARM_Before_Java9() throws IOException{
 BufferedReader reader1 = new BufferedReader(new FileReader("journaldev.txt"));
 try (BufferedReader reader2 = reader1) {
   System.out.println(reader2.readLine());
 }
}

void testARM_Java9() throws IOException{
 BufferedReader reader1 = new BufferedReader(new FileReader("journaldev.txt"));
 try (reader1) {
   System.out.println(reader1.readLine());
 }
}

2.7 CompletableFuture API 개선

- Java8에서 문제를 발생시키던 Java9에서는 CompletableFuture API에 대한 개선을 가져왔다.
- delays와 timeouts를 추가하였다.

Executor exe = CompletableFuture.delayExecutor(50L, TimeUnit.SECONDS);
delayExecutor메소드는 정적 유틸리티 메소드로 Executor를 반환한다. 그리고 주어진 딜레이 이후에 해당 태스크를 제출한다.

2.8 Reactive Streams

- Reactive 프로그래밍은 최근 몇가지 매우 좋은 이점들로 인해서 유명해졌다. 프레임워크들은 이미 Reactive Streams과 많은 이점들을 준다.
- Reactive Streams API는 Publish/Subscribe 프레임워크로 비동기 구현을 수행할 수 있게 해준다. 또한 확장성, 병렬 어플리케이션을 매우 쉽게 개발 할 수 있도록 한다.
- Java9는 아래 API를 제공한다.
- java.util.concurrent.Flow
- java.util.concurrent.Flow.Publisher
- java.util.concurrent.Flow.Subscriber
- java.util.concurrent.Flow.Processor

2.9 Anonymous Inner Class를 위한 <> 오퍼레이터 제공

- Java7에서 새로운 기능으로 소개된 다이아몬드 오퍼레이터는 장환한 코드를 제거해주었다. 그러나 Anonymous Inner Class 에서 다이아몬드 오퍼레이터의 사용은 한계가 있었다.

public List getEmployee(String empid) {
    // 상세 코드를 작성하면 된다.
    return new List(emp) {};
}
위 코드는 List를 이용하고 타입 파라미터를 지정하지 않고 사용하 ㄹ수 있다.

2.10 Optional Class Improvements

java.util.Optional 클래스에 새로이 유용한 메소드가 추가되어 있다.

Stream<Optional> emp = getEmployee(id)
Stream empStream = emp.flatMap(Optional::stream)

2.11 Stream API 개선 

- Java9에서는 java.util.Stream인터페이스에 유용한 메소드가 추가 되었다. Stream은 인터페이스이며, 새로운 인터페이스는 default메소드로 구현 되었다.  이들 중 2개는 dropWhile과 takeWhile메소드로 매우 중요한 메소드이다.
- 만약 Scala나 Functional 프로그래밍 언어에 익숙하다면 이러한 메소드를 알 것이다. 이들은 함수형 스타일로 개발할때 매우 유용하다.
- takeWhile은 아규먼트를 예측하고, 처음으로 Predicate가 false를 반환할때까지 주어진 스트림 값의 서브셋 스트림을 반환한 값을 채택한다. 만약 처음 값이 Predicate를 만족하지 못하다면 비어있는 스트림을 반환하게 될 것이다.

jshell> Stream.of(1,2,3,4,5,6,7,8,9,10).takeWhile(i -> i < 5 ).forEach(System.out::println)
1
2
3
4

2.12 @Deprecated annotation 개선. 

- Java8 이전에서는 @Deprecate 어노테이션은 단순히 마커 인터페이스였다. 이는 클래스, 필드, 인터페이스, 메소드, 생성자, enum등에서 사용되었다.
- Java9 에서는 더 많은 정보를 추가할 수 있고, deprecated API의 정적 사용에 대한 분석툴을 제공한다.
- forRemoval과 since 메소드를 제공하고 있으며 이는 이러한 정보들을 제공한다.

2.13 HTTP2 Client

- HTTP/2 프로토콜을 지원하기 위한 클라이언트 API를 릴리즈 하였고 WebSocket 기능도 제공한다. 이전에 있던 Legacy HTTP Client API는 HTTP/1만 지원했고 HTTP/2를 지원하지 못하거나 WebSocket을 ㄷ지원하지 않았고, Blocking모드에서만 동작하거나 성능상의 이슈가 있었다.
- Java9에서는 java.net.http 패키지 하위에 이러한 HTTP/2 Client API를 추가하였다. 이는 HTTP/1과 HTTP/2를 둘다 제공한다. 또한 Synchronous (Blocking모드)와 asynchronous (Non Blocking모드) 모두 지원한다. 또한 Asynchronous모드에서 WebSocket을 지원한다.

import java.net.http.*;
import static java.net.http.HttpRequest.*;
import static java.net.http.HttpResponse.*;
...
URI uri = new URI("http://daum.net");
HttpResponse response = HttpRequest.create(uri).body(noBody()).GET().response()
System.out.println("Response was " + response.body(asString()))

2.14. Multi-Resolution Image API

- Java9에서는 Multi-Resolution Image API를 소개했다. 이는 MultiResolutionImage 인터페이스이며 java.awk.image패키지에 포함된다.
- 이는 서로다른 높이, 넓이를 가지는 이미지에 대해서 필요한 기능들을 제공하고 있다.

2.15. 기타

- GC(Garbage Collector) 향상
- Stack-Walking API
- Filter Incoming Serialization Data
- Deprecate the Applet API
- Enhanced Method Handles
- Java Platform Logging API and Service
- Compact Strings
- Parser API for Nashorn
- Javadoc Search
- HTML5 javadoc









Eclipse MAT (Memory Analysis Tool) 사용하기

$
0
0
1. MAT 다운로드 사이트
http://www.eclipse.org/mat/downloads.php

2. 다음 코드를 작성해서 테스트 해보기

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

public class Main {

List<String> memoryLeakList = new ArrayList<>();

public static void main(String[] args) {

Main mainObj = new Main();
while(true) {
mainObj.memoryLeakList.add("Memory......");
}

}
}

3. JVM Option으로 다음과 같이 설정한다.
-XX:+HeapDumpOnOutOfMemoryError

4. MAT 메모리 설정을 매우 크게 준다. 
Eclipse/MemoryAnalyzer.ini 파일을 다음과 같이 메모리를 올려준다. 
-startup
../Eclipse/plugins/org.eclipse.equinox.launcher_1.3.100.v20150511-1540.jar
--launcher.library
../Eclipse/plugins/org.eclipse.equinox.launcher.cocoa.macosx.x86_64_1.1.300.v20150602-1417
-vmargs
-Xmx10g
-Dorg.eclipse.swt.internal.carbon.smallFonts
-XstartOnFirstThread


5. 분석화면


내용을 보면 Main.main 프로그램을 실행하다가 OutObMemoryError이 발생했다.

ForkJoinPool 예제

$
0
0

ForkJoinPool

ForkJoinPool 은 Java7부터 사용가능한 Java Concurrency 툴이며, 동일한 작업을 여러개의 Sub Task로 분리(Fork)하여 각각 처리하고, 이를 최종적으로 합쳐서(Join) 결과를 만들어내는 방식이다.

ForkJoinPool에는 2가지 인터페이스를 제공한다. 

- RecursiveAction : 

> RecursiveAction은 결과를 반환하지 않는 태스크를 말한다. 특정 작업을 분할하고, 처리를 수행하면서 해당 작업을 내부에서 처리한다. 

예제 : 
package com.company.api_simulation;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveAction;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class APICallRecursiveAction extends RecursiveAction {

    public static final int DIVIDE_COUNT = 5;

    List<RequestObject> requestObjects = null;

    public APICallRecursiveAction(List<RequestObject> requestObjects) {
        this.requestObjects = requestObjects;
    }

    @Override
    protected void compute() {
        if (requestObjects.size() > DIVIDE_COUNT) {
            ForkJoinTask.invokeAll(divideSubActions());
        }
        else {
            processAPICall(requestObjects);
        }
    }

    private void processAPICall(List<RequestObject> requestObjects) {
        requestObjects.forEach(System.out::println);
    }

    private List<APICallRecursiveAction> divideSubActions() {

        List<RequestObject> preList = requestObjects.subList(0, requestObjects.size() / 2);
        List<RequestObject> postList = requestObjects.subList(requestObjects.size() / 2, requestObjects.size());

        List<APICallRecursiveAction> list = new ArrayList<>();
        list.add(new APICallRecursiveAction(preList));
        list.add(new APICallRecursiveAction(postList));

        return list;

    }

    public static void main(String[] args) {
        List<RequestObject> lists = new ArrayList<>();
        lists.add(new RequestObject(1L, 1L, "First1"));
        lists.add(new RequestObject(2L, 1L, "First2"));
        lists.add(new RequestObject(10L, 5L, "First10"));
        lists.add(new RequestObject(6L, 3L, "First6"));
        lists.add(new RequestObject(3L, 2L, "First3"));
        lists.add(new RequestObject(4L, 2L, "First4"));
        lists.add(new RequestObject(11L, 6L, "First11"));
        lists.add(new RequestObject(8L, 4L, "First8"));
        lists.add(new RequestObject(5L, 3L, "First5"));
        lists.add(new RequestObject(7L, 4L, "First7"));
        lists.add(new RequestObject(9L, 5L, "First9"));
        lists.add(new RequestObject(12L, 6L, "First12"));

        APICallRecursiveAction action = new APICallRecursiveAction(lists);
        ForkJoinPool forkJoinPool = ForkJoinPool.commonPool();
        forkJoinPool.invoke(action);
    }
}

- RecursiveTask : 

> 기대하는 바와 같이 이 작업은 결과를 반환하는 태스크를 Fork와 Join으로 처리한다. 

예제 : 
package com.company;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;

public class CustomRecursiveTask extends RecursiveTask<Integer> {

    private int[] arr;

    private static final int THRESHOLD = 4;

    public CustomRecursiveTask(int[] arr) {
        this.arr = arr;
    }

    @Override
    protected Integer compute() {
        if (arr.length > THRESHOLD) {
            return ForkJoinTask.invokeAll(createSubtasks())
                    .stream()
                    .mapToInt(ForkJoinTask::join)
                    .sum();
        } else {
            return processing(arr);
        }
    }

    private Collection<CustomRecursiveTask> createSubtasks() {
        List<CustomRecursiveTask> dividedTasks = new ArrayList<>();
        dividedTasks.add(new CustomRecursiveTask(
                Arrays.copyOfRange(arr, 0, arr.length / 2)));
        dividedTasks.add(new CustomRecursiveTask(
                Arrays.copyOfRange(arr, arr.length / 2, arr.length)));
        return dividedTasks;
    }

    private Integer processing(int[] arr) {
        return Arrays.stream(arr)
//                .filter(a -> a > 10 && a < 27)
                .map(a -> a * 10)
                .sum();
    }

    public static void main(String[] args) {
        ForkJoinPool commonPool = ForkJoinPool.commonPool();

        int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        CustomRecursiveTask task = new CustomRecursiveTask(arr);

//        commonPool.execute(task);
//        Integer result = task.join();
//        System.out.println(result);

//        System.out.println(commonPool.invoke(task));

        System.out.println(task.compute());
    }
}

결론적으로

Fork Join Pool은 우리가 원하는 작업을 Divided and Conquer 방식으로 처리할 수 있도록 해준다. 

실제 프로그램에서 사용할때에는 외부 API 를 여러번 호출해야하는 상황에서 작업을 분리하여 호출할 수도 있을 것이다. 


Java 8 In Action - Design Pattern

$
0
0

Lambda를 이용하여 기존 디자인패턴을 변경해보기

from Java 8 In Action

1. 전략패턴 


1.1 일반적인 전략패턴 개발방식 

public interface ValidationStrategy {
boolean execute(String s);
}

public class IsAllowerCase implements ValidationStrategy {
public boolean execute(String s) {
return s.match("[a-z]+");
}
}

public class IsNumeric implements ValidationStrategy {
public boolean execute(String s) {
return s.matches("\\d+");
}
}

public class Validator {
private final ValidationStrategy strategy;

public Validator(ValidationStrategy v) {
this.strategy = v;
}

public boolean validate(String s) {
return strategy.execute(s);
}
}

Validator numericValidator = new Validator(new IsNumeric());
boolean b1 = numericValidator.validate("aaa");

Validator lowerCaseValidator = new Validator(new IsAllLowerCase());
boolean b2 = lowerCaseValidator.validate("bbb");


1.2 람다를 이용한 개발 방식

Validator numericValidator = new Validator((String s) -> s.matches("[a-z]+"));
boolean b1 = numericValidator.validate("aaa");

Validator lowerCaseValidator = new Validator((String a) -> s.match("\\d+"));
boolean b2 = lowerCaseValidator.validate("bbb");

2. Template Method


2.1 일반적인 템플릿 메소드 방식
abstract class OnlineBanking {
public void processCustomer(int id) {
Customer c = Database.getCustomerWithId(id);
makeCustomerHappy(c);
}

abstract void makeCustomerHappy(Customer c);
}

2.2 람다를 이용한 개발 방식

public void processCustomer(int id, Consumer<Customer> makeCustomerHappy) {
Customer c = Database.getCustomerWithId(id);
makeCustomerHappy.accept(c);
}

new OnlineBankingLambda().processCustomer(1234, (Customer c) -> System.out.println("Hello " + c.getName()));

3. Observer


3.1 일반적인 옵저버 패턴

interface Observer {
void notify(String tweet);
}

class NYTimes implements Observer {
public void notify(String tweet) {
if (tweet != null && tweet.contains("money")) {
System.out.println("Breaking news in NY! " + tweet);
}
}
}

class Guardian implements Observer {
public void notify(String tweet) {
if (tweet != null && tweet.contain("queen")) {
System.out.println("Yet another news in London... " + tweet);
}
}
}

class LeMonde implements Observer {
public void notify(String tweet) {
if (tweet != null && tweet.contains("wine")) {
System.out.println("Today cheese, wine and news! " + tweet);
}
}
}

interface Subject {
void registerObserver(Observer o);
void notifyObservers(String tweet);
}

class Feed implements Subject {
private final List<Observer> observers = new ArrayList<>();

public void registerObserver(Observer o) {
this.observers.add(o);
}

public void notifyObservers(String tweet) {
observers.forEach(o -> o.notify(tweet));
}
}

Feed f = new Feed();
f.registerObserver(new NYTimes());
f.registerObserver(new Guardian());
f.registerObserver(new LeMonde());
f.notifyObservers("The queen said her favorite book is Java 8 in Action");


3.2 람다 방식의 개발

f.registerObserver((String tweet) -> {
if (tweet != null && tweet.contains("money")) {
System.out.println("Breaking news in NY! " + tweet);
}
});

f.registerObserver((String tweet) -> {
if (tweet != null && tweet.contains("queen")) {
System.out.println("Yet another news in London... " + tweet);
}
});


4. Chain of Responsibility


4.1 일반적인 방식의 COR방식

public abstract class ProcessingObject<T> {

protected ProcessingObject<T> successor;

public void setSucessor(ProcessingObject<T> successor) {
this.successor = successor;
}

public T handle(T input) {
T r = handleWork(input);
if (successor != null) {
return successor.handle(r);
}
return r;
}

abstract protected T handleWork(T input);
}

public class HeaderTextProcessing extends ProcessingObject<String> {
public String handleWork(String text) {
return "From Raoul, Mario and Alan: " + text;
}
}

public class SpellCheckerProcessing extends ProcessingObject<String> {
public String handleWork(String text) {
return text.replaceAll("labda", "lambda");
}
}

ProcessingObject<String> p1 = new HeaderTextProcessing();
ProcessingObject<String> p2 = new SpellCheckerProcessing();

p1.setSuccessor(p2);

String result = p1.handle("Aren't labdas really sexy?!!");
System.out.println(result);

4.2 람다 방식

UnaryOperator<String> headerProcessing = (String text) -> "From Raoul, Mario and Alan: " + text;
UnaryOperator<String> spellCheckerProcessing = (String text) -> text.replaceAll("labda", "lambda");
Function<String, String> pipeline = handleProcessing.andThen(spellCheckerProcessing);

String result = pipeline.apply("Aren't labdas really sexy?!!");

5. Factory


5.1 일반적인 팩토리

public class ProductFactory{
public static Product createProduct(String name) {
switch(name) {
case "loan":
return new Loan();
case "stock":
return new Stock();
case "bond":
return new Bond();
default:
throws new RuntimeException("No such product " + name);
}
}
}

Product p = ProductFactory.createProduct("loan");

5.2 람다 방식

Supplier<Product> loanSupplier = Lona::new;
Loan loan = loanSupplier.get();

final static Map<String, Supplier<Product>> map = new HashMap<>();
static {
map.put("loan", Loan::new);
map.put("stock", Stock::new);
map.put("bond", Bond::new);
}

public static Product createProduct(String name) {
Suppler<Product> p = map.get(name);
if (p != null) return p.get();
throw new IllegalArgumentException("No Such product " + name);
}

curl 유용한 사용법 몇가지

$
0
0
curl은 REST API 방식으로 개발하는 경우 필수적인 요소인듯 싶다.
몇가지 간단한 사용법만 알아보자.

1. GET 방식으로 보내기
curl http://host_address:port

2. 헤더정보 받기.
curl -i http://host_address:port

3. 오직 헤더만 받기.
curl -s    -o /dev/null    -w "%{http_code}\n" http://host_address:port

4. Header 추가해서 요청하기.
curl -H "Content-Type: application/json" http://host_address::port

5. POST 방식으로 보내기
curl -X POST http://host_address:port -d '{"key":"value", "key2":"value2"}'

6. 서버의 파일 저장하기. (내가 원하는 이름으로)
curl -o filename.txt http://host_address:port/fileurl

7. 서버의 파일 다운로드 하기 (서버에 있는 이름 그대로)
curl -O http://host_address:port/fileurl

8. 처리 시간 알아보기.
curl http://host_address:port/url -w "%{time_connect} + %{time_starttransfer} = %{time_total}"

%{time_connect} : 서버 접속시간
%{time_starttransfer} : 파일 전송시간
%{time_total} : 총 처리되어서 전송된 시간 (여기에는 서버 내부에서 실행된 시간도 포함이 된다. )

기타 나머지 : 
> curl --manual 


Available --write-out variables

Some of these variables are not available in really old curl versions.
  • %{content_type} shows the Content-Type of the requested document, if there was any.
  • %{filename_effective} shows the ultimate filename that curl writes out to. This is only meaningful if curl is told to write to a file with the --remote-name or --output option. It's most useful in combination with the --remote-header-name option.
  • %{ftp_entry_path} shows the initial path curl ended up in when logging on to the remote FTP server.
  • %{response_code} shows the numerical response code that was found in the last transfer.
  • %{http_connect} shows the numerical code that was found in the last response (from a proxy) to a curl CONNECT request.
  • %{local_ip} shows the IP address of the local end of the most recently done connection—can be either IPv4 or IPv6
  • %{local_port} shows the local port number of the most recently made connection
  • %{num_connects} shows the number of new connects made in the recent transfer.
  • %{num_redirects} shows the number of redirects that were followed in the request.
  • %{redirect_url} shows the actual URL a redirect would take you to when an HTTP request was made without -L to follow redirects.
  • %{remote_ip} shows the remote IP address of the most recently made connection—can be either IPv4 or IPv6.
  • %{remote_port} shows the remote port number of the most recently made connection.
  • %{size_download} shows the total number of bytes that were downloaded.
  • %{size_header} shows the total number of bytes of the downloaded headers.
  • %{size_request} shows the total number of bytes that were sent in the HTTP request.
  • %{size_upload} shows the total number of bytes that were uploaded.
  • %{speed_download} shows the average download speed that curl measured for the complete download in bytes per second.
  • %{speed_upload} shows the average upload speed that curl measured for the complete upload in bytes per second.
  • %{ssl_verify_result} shows the result of the SSL peer certificate verification that was requested. 0 means the verification was successful.
  • %{time_appconnect} shows the time, in seconds, it took from the start until the SSL/SSH/etc connect/handshake to the remote host was completed.
  • %{time_connect} shows the time, in seconds, it took from the start until the TCP connect to the remote host (or proxy) was completed.
  • %{time_namelookup} shows the time, in seconds, it took from the start until the name resolving was completed.
  • %{time_pretransfer} shows the time, in seconds, it took from the start until the file transfer was just about to begin. This includes all pre-transfer commands and negotiations that are specific to the particular protocol(s) involved.
  • %{time_redirect} shows the time, in seconds, it took for all redirection steps including name lookup, connect, pre-transfer and transfer before the final transaction was started. time_redirect shows the complete execution time for multiple redirections.
  • %{time_starttransfer} shows the time, in seconds, it took from the start until the first byte was just about to be transferred. This includes time_pretransfer and also the time the server needed to calculate the result.
  • %{time_total} shows the total time, in seconds, that the full operation lasted. The time will be displayed with millisecond resolution.
  • %{url_effective} shows the URL that was fetched last. This is particularly meaningful if you have told curl to follow Location: headers (with -L).
Viewing all 50 articles
Browse latest View live