- 인터셉터(Interceptor) 란 ?


컨트롤러에 들어오는 요청 HttpRequest와 컨트롤러가 응답하는 HttpResponse를 가로채는 역할을 한다. 
예를들어 관리자만 접근할 수 있는 페이지의 경우, 페이지에 접근하기 전에 관리자 인증을 유도하는 용도로 활용할 수 있다. 
주로 로그인과 같은 권한 체크에 유용하게 사용된다. 

이와 유사한 역할을 하는 것이 'Filter'인데 Filter와 Interceptor는 비슷한 역할을 하지만 호출 시점에 차이가 있다. 

1. 호출 시점. 
Filter는 DispatcherServlet 이 실행되기 전, Interceptor는 DispatcherServlet이 실행된 후에 호출된다. 

2. 설정 위치
Filter는 web.xml에서 설정하고, Interceptor는 spring-servlet.xml에서 설정한다. 

 

Interceptor 구현 방법은 2가지가 있는데, 하나는 HandlerInterceptor인터페이스를 구현하는 방법과 
다른 하나는 HandlerInterceptorAdapter 클래스를 상속 받는 방법이 있다. 

메서드는 Controller의 실행 직전, 직후에 실행되는 preHandle()과 postHandle()이 있고, 
뷰를 렌더링 한 후의 콜백 핸들러 실행 결과에 따라 호출되는 afterCompletion()이 있다. 

'Java' 카테고리의 다른 글

자바 람다(Lamda) 기초  (0) 2021.02.13
자바 스트림(Stream)  (0) 2021.02.09
자바 HashMap 탐색 entrySet(), keySet(), Iterator()  (0) 2021.02.03
자바 Primitive Type과 Reference Type  (0) 2020.02.26
자바 [getOrDefault, putIfAbsent]  (0) 2020.01.22

 - 람다(Lamdda) 란 ? 


자바 8부터 등장하는 개념으로, 
기존에 메소드 사용을 위해서는 클래스를 먼저 만들고, 클래스 안에 메소드를 정의해야만 객체화 이후 사용이 가능했다.


하지만, 람다는 별도의 정의없이 보다 선언적인 메소드 사용을 가능하게 만드는 표현식이다.

람다의 핵심은 ( 파라미터 -> {실행코드;} );

메소드와 동일한 기능을 하지만 정의하지 않고, 바로 사용 가능한 것이 핵심이다. 

대부분 스트림(Stream)이나 ForEach 등을 사용할 때 주로 사용하며 아무 곳에서나 사용은 불가능하다.

아래는 ForEach문에 사용되는 Lambda의 예제로 파라미터가 1개 일 경우와 2개일 경우다.

 

'Java' 카테고리의 다른 글

자바 인터셉터(Interceptor)  (0) 2021.02.14
자바 스트림(Stream)  (0) 2021.02.09
자바 HashMap 탐색 entrySet(), keySet(), Iterator()  (0) 2021.02.03
자바 Primitive Type과 Reference Type  (0) 2020.02.26
자바 [getOrDefault, putIfAbsent]  (0) 2020.01.22

- 스트림(Stream) 이란?

 

자바8 이전에는 배열이나 컬렉션 안의 각 요소들에 접근하기 위해 for나 Iterator 등을 사용했는데,

자바8 부터는 Stream을 이용해서 보다 간결하고 가독성 높은 코드로 각 요소들에 접근하고, 컨트롤하는 것이 가능해졌다.

또 하나의 장점은 병렬처리가 가능하다는 점으로, 쓰레드를 이용해 많은 요소들을 빠르게 처리할 수 있다.

 

스트림은 선언, 가공, 반환 세 부분으로 이뤄진다. 

// 스트림 선언 방법
Stream<타입> stream명 = Arrays.stream(배열명);
Stream<타입> stream명 = 리스트명.stream();
Stream<타입> stream명 = Stream.of('값', '값'....);

 

가공부에서는 제공하는 메소드들을 이용해 요소들을 원하는 형태로 가공하며,

반환부를 통해 원하는 타입으로 다시 반환 받을 수 있다. 

 

다음은 리스트 'langs' 를 sorted() 메소드를 이용해 정렬(가공) 후, 다시 리스트로 반환하는 코드이다.

langs.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());

 

장점으로는 사용하기 편하고, 코드가 짧아지며 그러므로 가독성이 높아진다는 것. 
단점으로는 디버깅이 어려움. 그리고 한번 사용하면 close되기 때문에 재활용이 불가능하다는 단점이 있다. 

스트림(Stream)을 이용하면 배열이나 컬렉션(List, Map, Set)등을 사용해 원하는 값을 얻고자 할 경우,
For문의 도배를 줄일 수 있고, 이미 정의되어 있는 많은 메소드들을 이용하여 원하는 값을 쉽게 가져올 수 있다. 
다만, 디버깅이 어렵다는 단점이 있다. 

디버깅이 어려운 이유는 스트림은 한번에 모든 것이 수행되기 때문에, 에러나기 직전에 디버깅을 거는것이 불가능하다. 
따라서 스트림 안에서 에러 발생 시, 모두 분해 후 재 조립하는 과정을 거쳐야 한다. 

 

 

- 제공하는 함수들

filter 
sorted
allMatch : return boolean
anyMatch : return boolean
noneMatch : return boolean
max(Comparator.comparing(객체::값)) : return Optionnal<객체>
min(Comparator.comparing(객체::값)) : return Optionnal<객체>
collect(Collectors.groupingBy(객체::값)) : return Map<그룹핑 값, List<객체>>

.

.

 

예제 )

public static void main (String[] args) {
	List<String> langs = Arrays.asList("Java", "Scala", "React", "Swift", "Angular");
		
	// forEach() 순차 접근
	langs.stream().forEach(System.out::println);
		
	// sorted() 정렬
	langs = langs.stream().sorted().collect(Collectors.toList());
		
	// sorted(Comparator.reverseOrder()) 역순 정렬
	langs = langs.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
		
	// filter( input Param -> method ) 필터
	langs = langs.stream().filter( name -> name.contains("a")).collect(Collectors.toList());
		
		
	List<People> peoples = People.getPeopleList();
/* peoples
People[name:홍길동, age:17, gender:1]
People[name:홍길자, age:18, gender:2]
People[name:홍길남, age:13, gender:1]
People[name:홍길순, age:15, gender:2] */
		
		
	// 조건이 모두 match 하는지 (return : boolean으로 anyMatch, noneMatch도 있음.)
	peoples.stream().allMatch( person -> person.getName().contains("홍"));

	// 특정 속성 값에 대해 최대값을 가지는 요소 구하기.
	Optional<People> maxPeople = peoples.stream().max(Comparator.comparing(People::getAge));
	if(maxPeople.isPresent()) {
		System.out.println("나이가 많은 사람은?");
		System.out.println(maxPeople.toString()); // Optional[People[name:홍길자, age:18, gender:2]]
	}
    
    // 그룹핑
    Map<Integer, List<People>> groupByGender = People.getPeopleList().stream().collect(Collectors.groupingBy(People::getGender));
    System.out.println("남/여 목록");
    groupByGender.forEach((gender, peopleList) -> {
    System.out.println(gender);
    peopleList.forEach(System.out::println);
    });
	
/* 남/여 목록
1
People[name:홍길동, age:17, gender:1]
People[name:홍길남, age:13, gender:1]
2
People[name:홍길자, age:18, gender:2]
People[name:홍길순, age:15, gender:2] */
}

entrySet()은 key 와 value 반환하고,

keySet()은 key값을 반환.

Iterator()는 순서에 상관없이 하나씩 접근.

 

public static void main(String[] args) { 
	Map<string, string> map = new HashMap<string, string>(); 
    map.put("key1", "value1"); 
    map.put("key2", "value2"); 
    map.put("key3", "value3"); 
    map.put("key4", "value4"); 
    
    
    // entrySet 
    for( Map.Entry<string, string> elem : map.entrySet() ){
    	System.out.println( "key : " + elem.getKey() + ", value : " + elem.getValue()) ); 
    } 
    
    // keySet
    for( String key : map.keySet() ){ 
    	System.out.println( "key : " + key + ", value : " + map.get(key)) ); 
    } 
    
    // Iterator
    Iterator<string> keys = map.keySet().iterator();
    while( keys.hasNext() ){ 
    	String key = keys.next(); 
        System.out.println( "key : " + key + ", value : " + map.get(key)) );
    } 
}

'Java' 카테고리의 다른 글

자바 람다(Lamda) 기초  (0) 2021.02.13
자바 스트림(Stream)  (0) 2021.02.09
자바 Primitive Type과 Reference Type  (0) 2020.02.26
자바 [getOrDefault, putIfAbsent]  (0) 2020.01.22
자바 예외처리 [Exception]  (0) 2020.01.22

자바에서 데이터를 다룰 때 사용하는 데이터 타입은 

기초 타입(Primitive Type)레퍼런스 타입(Reference Type)으로 나뉜다. 

 

기초 타입은 언어에서 사전에 정의해 놓은 데이터 타입으로 

저장공간에 실제 리터럴 형태의 값이 저장된다.

 

반면에, 레퍼런스 타입은 실제 값이 아닌 해당 값을 참조하는 참조값(주소값)이 메모리상에 저장된다는 차이점이 있다.

 

기초타입에는 총 8개의 타입[int, char, short, long, float, double, boolean, byte]이 있고, 이 이외에는 모두 레퍼런스 타입에 해당한다.

한빛미디어 : 뇌를 자극하는 자바프로그래밍

 

- 자바 [getOrDefault, putIfAbsent]

 

1. getOrDefault

map.getOrDefault(key, defaultValue)

map에서 key 를 찾아 있으면 key의 value를 반환하고, 없으면 defaultValue 를 반환


2.putIfAbsent

 

map.putIfAbsent(key, value)

map에 key가 없으면 데이터 셋을 넣고[map.put(key, value)], map에 key가 있으면 건너띈다.

 

- 예외처리 (Exception)

완벽한 프로그래밍은 없다. 아무리 잘 짜여진 코드라도 예외상황은 있기 마련이다.

 

 

Exception처리가 없으면 프세스가 실행 시, 예외상황을 맞딱뜨릴 경우, 프로세스가 멈추게 된다.
예외상황을 맞딱드려도 정상적으로 원활한 프로세스의 진행을 위해 Exception을 사용한다.

위의 catch문 안에 있는 e.getMessage()는 예외상황에 대한 메시지를 보기위한 코드이다.


e.getMessage(); 를 많이 사용하기도 하고, 
메세지를 자세히 보고자 할때는 e.printStackTrace();를 사용한다.


- Exception의 종류

Exception의 종류는 다양하다.

가장 많이 볼 수 있는 흔한 Exception으로는

 

ArrayIndexOutOfBoundsException은 일반적으로 배열에서 존재하지 않는 index값에 접근할 경우 발생하는 Exception이며,
NumberFormatException은 주로 문자열(String)을 숫자(Number)로 바꿔주려고 할 때, 불가능한 경우에 나타나는 Exception이다.

A에서 걸리면 A만 실행, B에서 걸리면 B만 실행, A도 B도 아니면 C가 실행된다.
Exception e에서는 모든것이 실행 되는 것이다.

 


- finally

 

try~ catch 를 이용할 경우 try{}에서 문제가 발생하면 catch문이 실행 된다.
finally 문은 try와 catch문의 영향 없이 무조건 실행 된다.

 

try문에서 문제가 발생하지 않아도 finally는 무조건 실행된다.
문제가 발생해도 catch문을 거쳐 finally문이 무조건 실행 된다.




- 예외처리 문법 throws

try~catch문은 예외가 발생했을 때 자체적으로 catch문을 이용해서 해결한다.
throws의 경우에는 예외를 발생시킨 호출 쪽으로 예외를 던져버리는 방식이다.

 

 

ThrowsExClass 클래스의 객체를 생성하면  결과는 다음과 같다.


actionC
actionB
actoinA
예외는 여기서 처리할께요.^^
4        // e.getMessage();
actionBB
actionCC

 



try~catch가 좋다 throws 가 좋다 이런 문제가 아니라 상황에 맞는 처리를 해주어야 한다.

 


- 자주 발생하는 Exception

예외(Exception)의 종류는 아주 많다.
java API Doc을 보면 수십개가 있는것을 확인할 수 있다.


ArrayIndexOutOfBoundsException = 배열을 사용시 존재하지 않는 index값을 호출하면 발생
NullPointerException = 존재하지 않는 객체를 가리킬 때 발생
NumberFormatException = 문자를 숫자로 처리할 때 발생 (보통 숫자로 변경 할 수 없는 문자열을 변경하려고 할때 발생)  등 

 

- DB관련 Exception
ClassNotFoundException = 드라이브 이름을 찾지 못했을 때
SQLException: db url,id,pw가 올바르지 않을 때

 

 

- 자바 API 7 [Random과 SecureRandom의 차이]

 

java.util.Random 클래스는 난수를 생성할 때 seed값으로 '시간'을 이용한다. 
따라서, 각각 동일한 시간에 Random 클래스를 이용하여 난수를 생성하게 되면,
동일한 값이 리턴된다. [ deterministic(결정론적)]

java.security.SecureRandom클래스는 이와 다르게 non-deterministic(비결정론적) output을 생산한다.
예측할수 없는 seed를 이용하여 난수를 생성하기 때문이다.

 

참고 : API document에서 발췌

 

[Unlike the java.util.Random class, the java.security.SecureRandom class must produce non-deterministic output on each call. What that means is, in case of java.util.Random, if you were to recreate an instance with the same seed each time you needed a new random number, you would essentially get the same result every time. However, SecureRandom is guaranteed to NOT do that - so, creating a single instance or creating a new one each time does not affect the randomness of the random bytes it generates


Additionally, SecureRandom must produce non-deterministic output and therefore it is required that the seed material be unpredictable and that output of SecureRandom be cryptographically strong sequences as described in RFC 1750: Randomness Recommendations for Security.]

 

 

다음은 각각 Random과 secureRandom 을 이용하여 1부터 100이하의 난수를 생성하는 예제이다.

 

 

'Java' 카테고리의 다른 글

자바 [getOrDefault, putIfAbsent]  (0) 2020.01.22
자바 예외처리 [Exception]  (0) 2020.01.22
자바 API 6 [HashMap, HashSet, Iterator]  (0) 2020.01.21
자바 API 5 [InputStream,OutputStream]  (0) 2020.01.21
자바 API 4 [StringTokenizer]  (0) 2020.01.20

+ Recent posts