문제 설명

전화번호부에 적힌 전화번호 중, 한 번호가 다른 번호의 접두어인 경우가 있는지 확인하려 합니다.
전화번호가 다음과 같을 경우, 구조대 전화번호는 영석이의 전화번호의 접두사입니다.

  • 구조대 : 119
  • 박준영 : 97 674 223
  • 지영석 : 11 9552 4421

전화번호부에 적힌 전화번호를 담은 배열 phone_book 이 solution 함수의 매개변수로 주어질 때, 어떤 번호가 다른 번호의 접두어인 경우가 있으면 false를 그렇지 않으면 true를 return 하도록 solution 함수를 작성해주세요.

제한 사항

  • phone_book의 길이는 1 이상 1,000,000 이하입니다.
    • 각 전화번호의 길이는 1 이상 20 이하입니다.
    • 같은 전화번호가 중복해서 들어있지 않습니다.

입출력 예제

phone_book return
["119", "97674223", "1195524421"] false
["123","456","789"] true
["12","123","1235","567","88"] false
입출력 예 설명

입출력 예 #1
앞에서 설명한 예와 같습니다.

입출력 예 #2
한 번호가 다른 번호의 접두사인 경우가 없으므로, 답은 true입니다.

입출력 예 #3
첫 번째 전화번호, “12”가 두 번째 전화번호 “123”의 접두사입니다. 따라서 답은 false입니다.

주어진 String 배열들 중 접두사인 경우가 존재하는지 찾는 문제이다.

 

1. 코드

풀이방법 1 :

이중 for문을 통한 완전탐색으로 코드를 작성했다.

startsWith로 접두어인지 검사한다.

(※startsWith는 타겟단어로 시작하는 말인지 검사, contain은 타겟단어를 포함하는 문자인지 검사)

class Solution {
    public boolean solution(String[] phone_book) {
        boolean answer = true;
        
        for(int i=0;i<phone_book.length;i++){
            for(int j=i+1;j<phone_book.length;j++){
                String now = phone_book[i];
                String now2 = phone_book[j];
                
                if(now.startsWith(now2)||now2.startsWith(now)){
                    return false;
                } 
            }
        }
        
        return answer;
    }
}

 

효율성 테스트 3,4를 통과하지 못했다.

 

풀이방법 2:

Arrays.Sort()로 String 배열을 정렬한다.

배열의 앞뒤 인덱스끼리 비교한다.

 

ex ) [123, 88, 888, 12, 12345]

Sort 정렬 : [12, 123, 12345, 88, 888]

import java.util.Arrays;

class Solution {
    public boolean solution(String[] phone_book) {
        boolean answer = true;
        Arrays.sort(phone_book);
        
       for(int i=0; i<phone_book.length -1 ; i++){
           if(phone_book[i+1].startsWith(phone_book[i]))
               return false;
       }
        
       return true;
    }
}

이 코드로 효율성검사까지 통과하였다.

문제 설명

 

당신은 폰켓몬을 잡기 위한 오랜 여행 끝에, 홍 박사님의 연구실에 도착했습니다. 홍 박사님은 당신에게 자신의 연구실에 있는 총 N 마리의 폰켓몬 중에서 N/2마리를 가져가도 좋다고 했습니다.
홍 박사님 연구실의 폰켓몬은 종류에 따라 번호를 붙여 구분합니다. 따라서 같은 종류의 폰켓몬은 같은 번호를 가지고 있습니다. 예를 들어 연구실에 총 4마리의 폰켓몬이 있고, 각 폰켓몬의 종류 번호가 [3번, 1번, 2번, 3번]이라면 이는 3번 폰켓몬 두 마리, 1번 폰켓몬 한 마리, 2번 폰켓몬 한 마리가 있음을 나타냅니다. 이때, 4마리의 폰켓몬 중 2마리를 고르는 방법은 다음과 같이 6가지가 있습니다.

  1. 첫 번째(3번), 두 번째(1번) 폰켓몬을 선택
  2. 첫 번째(3번), 세 번째(2번) 폰켓몬을 선택
  3. 첫 번째(3번), 네 번째(3번) 폰켓몬을 선택
  4. 두 번째(1번), 세 번째(2번) 폰켓몬을 선택
  5. 두 번째(1번), 네 번째(3번) 폰켓몬을 선택
  6. 세 번째(2번), 네 번째(3번) 폰켓몬을 선택

이때, 첫 번째(3번) 폰켓몬과 네 번째(3번) 폰켓몬을 선택하는 방법은 한 종류(3번 폰켓몬 두 마리)의 폰켓몬만 가질 수 있지만, 다른 방법들은 모두 두 종류의 폰켓몬을 가질 수 있습니다. 따라서 위 예시에서 가질 수 있는 폰켓몬 종류 수의 최댓값은 2가 됩니다.
당신은 최대한 다양한 종류의 폰켓몬을 가지길 원하기 때문에, 최대한 많은 종류의 폰켓몬을 포함해서 N/2마리를 선택하려 합니다. N마리 폰켓몬의 종류 번호가 담긴 배열 nums가 매개변수로 주어질 때, N/2마리의 폰켓몬을 선택하는 방법 중, 가장 많은 종류의 폰켓몬을 선택하는 방법을 찾아, 그때의 폰켓몬 종류 번호의 개수를 return 하도록 solution 함수를 완성해주세요.

제한사항

  • nums는 폰켓몬의 종류 번호가 담긴 1차원 배열입니다.
  • nums의 길이(N)는 1 이상 10,000 이하의 자연수이며, 항상 짝수로 주어집니다.
  • 폰켓몬의 종류 번호는 1 이상 200,000 이하의 자연수로 나타냅니다.
  • 가장 많은 종류의 폰켓몬을 선택하는 방법이 여러 가지인 경우에도, 선택할 수 있는 폰켓몬 종류 개수의 최댓값 하나만 return 하면 됩니다.

입출력 예

nums result
[3,1,2,3] 2
[3,3,3,2,2,4] 3
[3,3,3,2,2,2] 2
입출력 예 설명

입출력 예 #1
문제의 예시와 같습니다.

입출력 예 #2
6마리의 폰켓몬이 있으므로, 3마리의 폰켓몬을 골라야 합니다.
가장 많은 종류의 폰켓몬을 고르기 위해서는 3번 폰켓몬 한 마리, 2번 폰켓몬 한 마리, 4번 폰켓몬 한 마리를 고르면 되며, 따라서 3을 return 합니다.

입출력 예 #3
6마리의 폰켓몬이 있으므로, 3마리의 폰켓몬을 골라야 합니다.
가장 많은 종류의 폰켓몬을 고르기 위해서는 3번 폰켓몬 한 마리와 2번 폰켓몬 두 마리를 고르거나, 혹은 3번 폰켓몬 두 마리와 2번 폰켓몬 한 마리를 고르면 됩니다. 따라서 최대 고를 수 있는 폰켓몬 종류의 수는 2입니다.

 

주어진 int 배열(nums)의 중복을 제거하는 문제이다.

중복값을 담지 않는 HashSet이용하여 문제를 풀었다.

 

1. 문제해설

배열의 길이의 1/2만큼 폰켓몬을 가져가기 때문에 최대 가져갈수 있는 값을 maxCnt로 선언한다.

HashSet에 배열의 종류를 담고, 담긴 Set의 길이와 maxCnt를 비교하여 리턴한다.

 

2. 코드

import java.util.*;

class Solution {
    public int solution(int[] nums) {
        int answer = 0;
        HashSet<Integer> hs =new HashSet<Integer>();
        int maxCnt = nums.length/2;
        
        //HashSet에 배열값을 담음(중복제거)
        for(int a : nums){
            hs.add(a);
        }
        
        //Set사이즈가 더 클경우 maxCnt를 리턴한다.
        if(hs.size() > maxCnt){
            answer = maxCnt;  
        }else{
            answer = hs.size();
        }
        
        
        return answer;
    }
}

정확성: 100.0&nbsp; 합계: 100.0 / 100.0

 

문제 설명

어떤 숫자에서 k개의 수를 제거했을 때 얻을 수 있는 가장 큰 숫자를 구하려 합니다.

예를 들어, 숫자 1924에서 수 두 개를 제거하면 [19, 12, 14, 92, 94, 24] 를 만들 수 있습니다. 이 중 가장 큰 숫자는 94 입니다.

문자열 형식으로 숫자 number와 제거할 수의 개수 k가 solution 함수의 매개변수로 주어집니다. number에서 k 개의 수를 제거했을 때 만들 수 있는 수 중 가장 큰 숫자를 문자열 형태로 return 하도록 solution 함수를 완성하세요.

제한 조건

  • number는 2자리 이상, 1,000,000자리 이하인 숫자입니다.
  • k는 1 이상 number의 자릿수 미만인 자연수입니다.

입출력 예

numbrt k return
"1924" 2 "94"
"1231234" 3 "3234"
"4177252841" 4 "775841"

 

임의의 수에 대해 k만큼의 갯수의 수를 제거하고 그 중에서 가장 큰 수를 찾는 문제이다.

나는 Greedy(탐욕법) 탐색을 통해 문제를 풀었다.

 

1. 문제 해설

이중 for문을 사용하여

number = "1234123"

k = 3 일때

첫번째 for문의 조건은 반환해야하는 숫자의 자릿수만큼 loop를 돌려준다.

따라서 i는 0부터 number.length()-k  전 까지 돌려준다. ( 예시로 치면 0~3까지 )

이중 for문의 안쪽 for문은 기준 인덱스부터 뒤에 붙여야하는 자릿수의 전 인덱스까지 loop를 돌려준다.

따라서 j는 index부터 i+k까지 돌려준다. (예시로 치면 0~3, 4~4...)   

또한 String을 이어붙이는 것이 아니라 Stringbuilder를 사용하면 좀 더 효율적으로 String을 이어붙여 리턴 할 수 있다.

 

2. 코드

class Solution {
    public String solution(String number, int k) {
        int index=0;
        int max=0;
        //StringBuilder를 사용하면 효율성 증가
        StringBuilder sb = new StringBuilder();
        
        for(int i=0; i<number.length()-k; i++){
            max =0;
            for(int j=index; j<=i+k; j++){
                if(max < number.charAt(j) -'0'){
                    max = number.charAt(j) - '0';
                    index = j+1; //다음 인덱스부터 검사하도록
                }
            }
            sb.append(max);
        }
        
        return sb.toString();
    }
}

정확성: 100.0 합계: 100.0 / 100.0

number.charAt(j)를 int값과 비교를 하기위해서는

number.charAt(j)값이 아스키코드값을 반환하기때문에 '0'(아스키코드값 48)을 빼줌으로 써

int값과 비교가 가능해진다.

문제 설명

피보나치 수는 F(0) = 0, F(1) = 1일 때, 1 이상의 n에 대하여 F(n) = F(n-1) + F(n-2) 가 적용되는 수 입니다.

예를들어

  • F(2) = F(0) + F(1) = 0 + 1 = 1
  • F(3) = F(1) + F(2) = 1 + 1 = 2
  • F(4) = F(2) + F(3) = 1 + 2 = 3
  • F(5) = F(3) + F(4) = 2 + 3 = 5

와 같이 이어집니다.

2 이상의 n이 입력되었을 때, n번째 피보나치 수를 1234567으로 나눈 나머지를 리턴하는 함수, solution을 완성해 주세요.

제한 사항

  • n은 2 이상 100,000 이하인 자연수입니다.

 

임의의 값이 주어지면 피보나치 수를 구해 그 값을 1234567로 나누는 문제이다.

나는 재귀적 함수 호출 방법으로 첫번째 답변을 작성했다.

 

1. 재귀적 방법

class Solution {
    public int solution(int n) {
        int answer = 0;
        int a = fibo(n);
        answer = a % 1234567;     
        return answer;
    }
    
    //재귀함수
    public int fibo(int n){
        if(n<=1){
            return n;
        }else{
            return fibo(n-1)+fibo(n-2);
        }
    }
}

 

위와 같은 방법으로 답변을 제출하니 몇가지 케이스에 대해 시간초과가 발생하였다.

 

정확성: 42.9&nbsp; 합계: 42.9 / 100.0

 

2. 반복문 사용

class Solution {
    public int solution(int n) {
        int answer = 0;
        int fn1 = 0;
        int fn2 = 1;
        
        for(int i=2;i<=n;i++){
            answer = (fn1 + fn2) % 1234567;
            fn1 = fn2;
            fn2 = answer;
        }      
        return answer;
    }
}

 

정확성: 100.0&nbsp; 합계: 100.0 / 100.0

 

위와 같이 반복문을 사용하니 효율성면에서 통과되었다.

재귀적방법이 직관적이나, 연산이 많이 필요하여 효율성이 떨어진다.

따라서 이 피보나치 수의 경우에는 반복문으로 통한 풀이가 효율성 측면에서 더 낫다.

[우선순위 큐(Priority Queue) - JAVA

 

 

1. 우선순위 큐(Queue)란? 

 

일반적인 큐는 제일 먼저 들어간 데이터가 가장 먼저 나오게 되는 자료구조이다. 이런 큐의 특성과 달리 우선순위 큐

들어간 순서에 상관없이 일정한 규칙에 따라 우선순위를 선정하고, 우선순위가 가장 높은 데이터가 가장 먼저 나오게 된다.

 

 

2. 우선순위 큐 function

 

E peek() : 큐의 처음에 있는 원소를 삭제하지 않고 가져온다. 큐가 비어있으면 null을 반환

boolean offer(E e) :원소를 추가할 때 큐의 용량을 넘어서면 false를 반환한다.

E poll() : 큐의 처음에 있는 원소를 가져온다. 큐에 원소가 없으면 null을 반환한다.

E remove() : 큐의 처음에 있는 원소를 제거한다. 큐에 원소가 없으면 예외가 발생한다.

 

 

3. 우선순위 큐를 이용한 자바 프로그램

 

[프로그래머스 - 더 맵게]

 

문제 출처 : https://programmers.co.kr/learn/courses/30/lessons/42626

 

-해답

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import java.util.PriorityQueue;
 
class Solution {
   public int solution(int[] scoville, int K) {
               PriorityQueue<Integer> que=new PriorityQueue<Integer>();
            
            //큐에 배열 넣어주기
            for(int num:scoville){
                que.add(num);
            }
       
            //섞은 횟수 저장할 변수
            int count=0;
 
            while(que.peek()<K&&!que.isEmpty()) {//peek()은 꺼내지 않고 값만 확인
                int lessSpicy=que.poll();//poll()은 우선순위가 젤 우선인 값을 꺼냄
                
                if(!que.isEmpty()){
                    int secondLessSpicy=que.poll();
                    que.add(lessSpicy+secondLessSpicy*2);
                    count++;
                }else{
                    return -1;
                }
            }
       
            return count;
   }
}
cs

 

 

'알고리즘' 카테고리의 다른 글

[알고리즘] 조합(Combination)  (0) 2022.12.02
[알고리즘] 슬라이딩 윈도우  (0) 2022.09.15
[알고리즘] 정렬1(버블,선택,삽입)  (0) 2022.07.29
[알고리즘] 힙(Heap)  (0) 2022.07.21
[알고리즘] 해시(Hash)  (0) 2022.07.15

1. Spring 3.0+JDBC(Web 환경) 


1) SpirngWeb 프로젝트 생성


Web에서 DB를 연결하는 방법은 (JDBC - Spring JDBC - Mybatis) 이렇게 3가지가 있다.


-Spring3.0을 웹으로 JDBC와 연결해보겠다.


-기본세팅파일

SpringWeb_기본세팅.zip


-폴더 구조


2) BoardController.java 작성 - created, list(글 작성, 글목록 기능)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package com.jdbc.springweb;
 
 
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.List;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
 
import com.jdbc.dao.BoardDAO;
import com.jdbc.dto.BoardDTO;
import com.jdbc.util.MyUtil;
 
@Controller
public class BoardController {
    
    @Autowired
    @Qualifier("boardDAO")
    BoardDAO dao;
    
    @Autowired
    MyUtil myUtil;
    
    @RequestMapping(value = "/created.action")
    public ModelAndView created() {
        ModelAndView mav=new ModelAndView();
        mav.setViewName("bbs/created");
        
        return mav;
    }
    
    @RequestMapping(value="/created_ok.action",method = {RequestMethod.GET,RequestMethod.POST})
    public String created_ok(BoardDTO dto, HttpServletRequest request, HttpServletResponse response) throws Exception{
        
        int maxNum=dao.getMaxNum();
        
        dto.setNum(maxNum+1);
        dto.setIpAddr(request.getRemoteAddr());
        
        dao.insertData(dto);
        
        return "redirect:/list.action";
    }
    
    @RequestMapping(value="/list.action",method = {RequestMethod.GET,RequestMethod.POST})
    public String list(HttpServletRequest request, HttpServletResponse response) throws Exception{
        
        String cp = request.getContextPath();
        
        String pageNum = request.getParameter("pageNum");
        int currentPage = 1;
        
        if(pageNum != null)
            currentPage = Integer.parseInt(pageNum);
        
        String searchKey = request.getParameter("searchKey");
        String searchValue = request.getParameter("searchValue");
        
        if(searchKey == null){
            
            searchKey = "subject";
            searchValue = "";
            
        }else{
            
            if(request.getMethod().equalsIgnoreCase("GET"))
                searchValue =
                    URLDecoder.decode(searchValue, "UTF-8");
            
        }
        
        //전체데이터갯수
        int dataCount = dao.getDataCount(searchKey, searchValue);
        
        //전체페이지수
        int numPerPage = 10;
        int totalPage = myUtil.getPageCount(numPerPage, dataCount);
        
        if(currentPage > totalPage)
            currentPage = totalPage;
        
        int start = (currentPage-1)*numPerPage+1;
        int end = currentPage*numPerPage;
        
        List<BoardDTO> lists =
            dao.getList(start, end, searchKey, searchValue);
        
        //페이징 처리
        String param = "";
        if(!searchValue.equals("")){
            param = "searchKey=" + searchKey;
            param+= "&searchValue=" 
                + URLEncoder.encode(searchValue, "UTF-8");
        }
        
        String listUrl = cp + "/list.action";
        if(!param.equals("")){
            listUrl = listUrl + "?" + param;                
        }
        
        String pageIndexList =
            myUtil.pageIndexList(currentPage, totalPage, listUrl);
        
        //글보기 주소 정리
        String articleUrl = 
            cp + "/article.action?pageNum=" + currentPage;
            
        if(!param.equals(""))
            articleUrl = articleUrl + "&" + param;
        
        //포워딩 될 페이지에 데이터를 넘긴다
        request.setAttribute("lists", lists);
        request.setAttribute("pageIndexList",pageIndexList);
        request.setAttribute("dataCount",dataCount);
        request.setAttribute("articleUrl",articleUrl);
        
        return "bbs/list";
    }
}
cs

created, list 기능만 추가한 코드이다.


-실행화면


3) article 추가(게시글 보기 기능)

컨트롤러에 article 추가한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
    @RequestMapping(value="/article.action",method = {RequestMethod.GET,RequestMethod.POST})
    public String article(HttpServletRequest request, HttpServletResponse response) throws Exception{
        
        String cp = request.getContextPath();
        
        int num = Integer.parseInt(request.getParameter("num"));
        String pageNum = request.getParameter("pageNum");
        
        String searchKey = request.getParameter("searchKey");
        String searchValue = request.getParameter("searchValue");
        
        if(searchKey != null)
            searchValue = URLDecoder.decode(searchValue, "UTF-8");
        
        //조회수 증가
        dao.updateHitCount(num);
        
        BoardDTO dto = dao.getReadData(num);
        
        if(dto==null){
            return "redirect:/list.action";
        }
        
        int lineSu = dto.getContent().split("\n").length;
        
        dto.setContent(dto.getContent().replaceAll("\n""<br/>"));
        
        String param = "pageNum=" + pageNum;
        if(searchKey!=null){
            param += "&searchKey=" + searchKey;
            param += "&searchValue=" 
                + URLEncoder.encode(searchValue, "UTF-8");
        }
        
        request.setAttribute("dto", dto);
        request.setAttribute("params",param);
        request.setAttribute("lineSu",lineSu);
        request.setAttribute("pageNum",pageNum);        
        
        return "bbs/article";    
    }
cs


**여기서 return값을 ModelAndView로 바꿔줄경우!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
    @RequestMapping(value="/article.action",method = {RequestMethod.GET,RequestMethod.POST})
    public ModelAndView article(HttpServletRequest request, HttpServletResponse response) throws Exception{
        
        String cp = request.getContextPath();
        
        int num = Integer.parseInt(request.getParameter("num"));
        String pageNum = request.getParameter("pageNum");
        
        String searchKey = request.getParameter("searchKey");
        String searchValue = request.getParameter("searchValue");
        
        if(searchKey != null)
            searchValue = URLDecoder.decode(searchValue, "UTF-8");
        
        //조회수 증가
        dao.updateHitCount(num);
        
        BoardDTO dto = dao.getReadData(num);
        
        if(dto==null){
            //return "redirect:/list.action";
        }
        
        int lineSu = dto.getContent().split("\n").length;
        
        dto.setContent(dto.getContent().replaceAll("\n""<br/>"));
        
        String param = "pageNum=" + pageNum;
        if(searchKey!=null){
            param += "&searchKey=" + searchKey;
            param += "&searchValue=" 
                + URLEncoder.encode(searchValue, "UTF-8");
        }
        /*
        //model
        request.setAttribute("dto", dto);
        request.setAttribute("params",param);
        request.setAttribute("lineSu",lineSu);
        request.setAttribute("pageNum",pageNum);        
        
        //view
        //return "bbs/article";    
        */
        
        ModelAndView mav=new ModelAndView();
        mav.setViewName("bbs/article");
        mav.addObject("dto",dto);
        mav.addObject("params",param);
        mav.addObject("lineSu",lineSu);
        mav.addObject("pageNum",pageNum);
        
        return mav;
    }
cs

반환값의 자료형을 ModelAndView로 바꾸고 아래쪽에 request.setAttribute~ 주석친 부분을 그  아래 코드처럼 써주면 된다.


4) update 추가(수정 기능)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
    @RequestMapping(value="/updated.action",method = {RequestMethod.GET,RequestMethod.POST})
    public String updated(HttpServletRequest request, HttpServletResponse response) throws Exception{
 
        String cp=request.getContextPath();
        
        int num = Integer.parseInt(request.getParameter("num"));
        String pageNum = request.getParameter("pageNum");
        
        BoardDTO dto = dao.getReadData(num);
        
        if(dto == null){
            return "redirect:/list.action";
        }
        
        request.setAttribute("dto", dto);
        request.setAttribute("pageNum", pageNum);
        
        return "bbs/updated";    
    }
    
    @RequestMapping(value="/updated_ok.action",method = {RequestMethod.GET,RequestMethod.POST})
    public String updated_ok(BoardDTO dto,HttpServletRequest request, HttpServletResponse response) throws Exception{
    
        String pageNum = request.getParameter("pageNum");
        
        dao.updateData(dto);
        
        return "redirect:/list.action?pageNum="+pageNum;
    }
cs


5)delete 추가


1
2
3
4
5
6
7
8
9
10
    @RequestMapping(value="/deleted.action",method = {RequestMethod.GET,RequestMethod.POST})
    public String deleted(BoardDTO dto,HttpServletRequest request, HttpServletResponse response) throws Exception{
    
        String pageNum = request.getParameter("pageNum");
        int num =Integer.parseInt(request.getParameter("num"));
        
        dao.deleteData(num);
        
        return "redirect:/list.action?pageNum="+pageNum;
    }
cs


6) 전체 실행화면




2. Spring 3.0+Spring JDBC(Web 환경) 


1) Spring JDBC lib 다운

링크 : https://mvnrepository.com/

Spring JDBC 다운받아서 pom.xml에 붙여넣는다.


-pom.xml

1
2
3
4
5
6
        <!-- spring-jdbc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>
cs


2) DAO 파일 생성 및 작성

먼저 xml파일에 객체 생성해주고 메소드를 통한 의존성 주입을 위한 세팅을 먼저 해주자.


-servlet-context.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    <beans:bean id="boardDAO2" class="com.jdbc.dao.BoardDAO2">
        <beans:property name="jdbcTemplate" ref="jdbcTemplate"/>
    </beans:bean>
    
    <beans:bean id="jdbcTemplate"
    class="org.springframework.jdbc.core.JdbcTemplate">
        <beans:constructor-arg ref="dataSource"/>
    </beans:bean>
    
    <beans:bean id="dataSource"
    class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close">
        <beans:property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
        <beans:property name="url" value="jdbc:oracle:thin:@192.168.16.12:1521:TestDB"/>
        <beans:property name="username" value="suzi"/>
        <beans:property name="password" value="a123"/>
    </beans:bean>
cs

boardDAO2를 만들고 의존성 주입을 위한 셋팅.


-BoardDAO2.java

1
2
3
4
5
6
    //DI(의존성 주입)
    private JdbcTemplate jdbcTemplate;
    
    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) throws Exception{
        this.jdbcTemplate = jdbcTemplate;
    }
cs

메소드로 의존성주입을 하였다.


-아래는 BoardDAO2의 DB를 다루는 코드 전문.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
package com.jdbc.dao;
 
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
 
import javax.sql.DataSource;
 
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
 
import com.jdbc.dto.BoardDTO;
 
public class BoardDAO2 {
    
    private JdbcTemplate jdbcTemplate;
    
    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) throws Exception{
        this.jdbcTemplate = jdbcTemplate;
    }
    
    public int getMaxNum(){
        
        int maxNum = 0;
        
        StringBuilder sql=new StringBuilder(100);//100자 저장하겠다.
        
        sql.append("select nvl(max(num),0) from board");
        maxNum=jdbcTemplate.queryForInt(sql.toString());
 
        return maxNum;
    }
    
    public void insertData(BoardDTO dto){
        
        StringBuilder sql=new StringBuilder(200);
            
        sql.append("insert into board (num,name,pwd,email,subject,content,");
        sql.append("ipAddr,hitCount,created) ") ;
        sql.append( "values(?,?,?,?,?,?,?,0,sysdate)");
        
        jdbcTemplate.update(sql.toString(),dto.getNum(),dto.getName(),dto.getPwd()
                ,dto.getEmail(),dto.getSubject(),dto.getContent(),dto.getIpAddr());
    
    }
    
    public List<BoardDTO> getList(int start, int end,
            String searchKey, String searchValue){
 
        StringBuilder sql=new StringBuilder(500);
            
        searchValue = "%" + searchValue + "%";
        
        sql.append("select * from (")
        .append("select rownum rnum,data.* from(")
        .append("select num,name,subject,hitCount,")
        .append("to_char(created,'YYYY-MM-DD') created ")
        .append("from board where " + searchKey + " like ? order by num desc) data) ")
        .append("where rnum >= ? and rnum <= ?");
        
        List<BoardDTO> lists=jdbcTemplate.query(sql.toString(), 
                new Object[] {searchValue,start,end},
                new RowMapper<BoardDTO>() {
 
                    @Override
                    public BoardDTO mapRow(ResultSet rs, int rowNum) throws SQLException {
                        
                        BoardDTO dto=new BoardDTO();
                        
                        dto.setNum(rs.getInt("num"));
                        dto.setName(rs.getString("name"));
                        dto.setSubject(rs.getString("subject"));
                        dto.setHitCount(rs.getInt("hitCount"));
                        dto.setCreated(rs.getString("created"));
                        
                        return dto;
                    }
            
        });
        
        return lists;
        
    }
    
    public int getDataCount(String searchKey,String searchValue){
        
        int result = 0;
        
        StringBuilder sql=new StringBuilder(200);
            
        searchValue = "%" + searchValue + "%";
        
        sql.append("select nvl(count(*),0) from board ")
        .append("where " + searchKey + " like ?");
            
        result=jdbcTemplate.queryForInt(sql.toString(),searchValue);
 
        return result;
    }
    
 
    public void updateHitCount(int num){
 
        StringBuilder sql=new StringBuilder(500);
        sql.append("update board set hitCount=hitCount + 1 where num=?");
            
        jdbcTemplate.update(sql.toString(),num);
    }
    
    public BoardDTO getReadData(int num){
        
        StringBuilder sql=new StringBuilder(100);
            
        sql.append("select num,name,pwd,email,subject,content,ipAddr,")
        .append("hitCount,created from board where num=?");
 
        BoardDTO dtoOne=jdbcTemplate.queryForObject(sql.toString(),
                new RowMapper<BoardDTO>(){
 
                    @Override
                    public BoardDTO mapRow(ResultSet rs, int rowNum) throws SQLException {
                        
                        BoardDTO dto = new BoardDTO();
                        
                        dto.setNum(rs.getInt("num"));
                        dto.setName(rs.getString("name"));
                        dto.setPwd(rs.getString("pwd"));
                        dto.setEmail(rs.getString("email"));
                        dto.setSubject(rs.getString("subject"));
                        dto.setContent(rs.getString("content"));
                        dto.setIpAddr(rs.getString("ipAddr"));
                        dto.setHitCount(rs.getInt("hitCount"));
                        dto.setCreated(rs.getString("created"));
                        
                        return dto;
                    }
            
            },num);
 
        return dtoOne;
    }
    
    public void deleteData(int num){
        
        StringBuilder sql=new StringBuilder(100);
        
        sql.append("delete board where num=?");
        
        jdbcTemplate.update(sql.toString(),num);
        
    }
 
    public void updateData(BoardDTO dto){
        
        StringBuilder sql=new StringBuilder(100);
        
        sql.append("update board set name=?, pwd=?, email=?, subject=?,")
        .append("content=? where num=?");
        
        jdbcTemplate.update(sql.toString(),dto.getName(),dto.getPwd(),
                dto.getEmail(),dto.getSubject(),dto.getContent(),
                dto.getNum());        
    }
}
cs


-그리고 아까의 BoardController.java에서 dao 연결부분을 바꿔준다.

1
2
3
4
5
6
@Controller
public class BoardController {
    
    @Autowired
    @Qualifier("boardDAO2")
    BoardDAO2 dao;
cs

BoardDAO에서 BoardDAO2를 연결


-그리고 실행하면 게시판이 잘 작동한다.




3. Spring 3.0+Mybatis(Web 환경) 


1) 프로젝트 복사해서 생성(SpringWebMybatis)

SpringWeb을 복사해서 SpringWebMybatis로 생성


-폴더기본셋팅

SpringWebMybatis.zip


2) mvnrepository에서 mybatis,mybatis spring 다운


링크 : https://mvnrepository.com/

-pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
        <!-- mybatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.2</version>
        </dependency>
        
        <!-- mybatis-spring -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.3.1</version>
        </dependency>
cs


3) servlet-context.xml에서 mybatis설정


-servlet-context.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
 
    <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
    
    <!-- Enables the Spring MVC @Controller programming model -->
    <annotation-driven />
 
    <!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
    <resources mapping="/resources/**" location="/resources/" />
 
    <!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
    <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <beans:property name="prefix" value="/WEB-INF/views/" />
        <beans:property name="suffix" value=".jsp" />
    </beans:bean>
    
    <context:component-scan base-package="com.jdbc.springweb" />
    
    <beans:bean id="boardDAO2" class="com.jdbc.dao.BoardDAO2">
        <beans:property name="sessionTemplate" ref="sessionTemplate"/>
    </beans:bean>
    
    <beans:bean id="sessionTemplate"
    class="org.mybatis.spring.SqlSessionTemplate">
        <beans:constructor-arg ref="sessionFactory"/>    
    </beans:bean>
    
    <beans:bean id="sessionFactory" 
    class="org.mybatis.spring.SqlSessionFactoryBean">
        <beans:property name="dataSource" ref="dataSource"></beans:property>
    </beans:bean>
    
    <beans:bean id="dataSource"
    class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close">
        <beans:property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
        <beans:property name="url" value="jdbc:oracle:thin:@192.168.16.12:1521:TestDB"/>
        <beans:property name="username" value="suzi"/>
        <beans:property name="password" value="a123"/>
    </beans:bean>
    
    <beans:bean id="myUtil" class="com.jdbc.util.MyUtil"/>
    
</beans:beans>
cs


4) mybats-config.xml 파일 생성 및 작성


src/main/java에 mybatis-config.xml 파일 생성

1
2
3
4
<!-- spring하고 연결할때는 얘만 필요 -->
<mappers>
    <mapper resource="com/exe/mybatis/boardMapper.xml"/>
</mappers>
cs



그리고 servlet-context.xml에 sessionFactory 객체 생성부분에 property추가 해준다.

1
2
3
4
5
6
    <beans:bean id="sessionFactory" 
    class="org.mybatis.spring.SqlSessionFactoryBean">
        <beans:property name="dataSource" ref="dataSource"></beans:property>
        <beans:property name="configLocation"
        value="classpath:/mybatis-config.xml"/>
    </beans:bean>
cs

configLocation으로 sql문을 써놓은 xml 파일의 경로를 알려준다.


5) boardMapper.xml 생성 및 작성


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<?xml version="1.0" encoding="UTF-8"?>
 
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 
<mapper namespace="boardMapper">
 
<select id="maxNum" resultType="int">
    select nvl(max(num),0) from board
</select>
 
<insert id="insertData" parameterType="com.jdbc.dto.BoardDTO">
    insert into board(num,name,pwd,email,subject,content,ipAddr,hitCount,created) 
    values(#{num},#{name},#{pwd},#{email},#{subject},#{content},#{ipAddr},0,sysdate)
</insert>
 
<select id="getDataCount" parameterType="hashMap" resultType="int">
    select nvl(count(*),0) from board
    where ${searchKey} like '%' || #{searchValue} || '%'
</select>
 
<select id="getLists" parameterType="hashMap" resultType="com.jdbc.dto.BoardDTO">
    select * from(
    select rownum rnum, data.* from(
    select num,name,subject,hitCount,to_char(created,'YYYY-MM-DD') created
    from board where ${searchKey} like '%' || #{searchValue} || '%'
    order by num desc) data)
<![CDATA[
    where rnum>=#{start} and rnum<=#{end}
]]>
</select>
 
<select id="getReadData" parameterType="int" resultType="com.jdbc.dto.BoardDTO">
    select num,name,pwd,email,subject,content,ipAddr,hitCount,created
    from board where num=#{num}
</select>
 
<update id="updateHitCount" parameterType="int">
    update board set hitCount=hitCount+1 where num=#{num}
</update>
 
<update id="updateData" parameterType="com.jdbc.dto.BoardDTO">
    update board set name=#{name},pwd=#{pwd},email=#{email},subject=#{subject},
    content=#{content} where num=#{num}
</update>
 
<delete id="delteData" parameterType="int">
    delete board where num=#{num}
</delete>
 
</mapper>
cs


6) DAO 파일 mybatis에 맞게 바꿔준다. 


-BoardDAO2.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
package com.jdbc.dao;
 
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
 
import javax.sql.DataSource;
 
import org.mybatis.spring.SqlSessionTemplate;
 
import com.jdbc.dto.BoardDTO;
 
public class BoardDAO2 {
    
    private SqlSessionTemplate sessionTemplate;
    
    public void setSessionTemplate(SqlSessionTemplate sessionTemplate) throws Exception{
        this.sessionTemplate = sessionTemplate;
    }
    
    Connection conn=null;
    
    public int getMaxNum(){
        
        int maxNum = 0;
        
        maxNum=sessionTemplate.selectOne("boardMapper.maxNum");
        
        return maxNum;
    }
    
    public void insertData(BoardDTO dto){
        
        sessionTemplate.insert("boardMapper.insertData",dto);
    }
    
    public List<BoardDTO> getList(int start, int end,
            String searchKey, String searchValue){
        
        HashMap<String, Object> params=new HashMap<String, Object>();
        params.put("start", start);
        params.put("end", end);
        params.put("searchKey",searchKey);
        params.put("searchValue",searchValue);
    
        List<BoardDTO> lists=sessionTemplate.selectList("boardMapper.getLists",params);
        
        return lists;
    }
    
    public int getDataCount(String searchKey,String searchValue){
        
        int result=0;
        
        HashMap<String, Object> params=new HashMap<String, Object>();
 
        params.put("searchKey",searchKey);
        params.put("searchValue",searchValue);
 
        result=sessionTemplate.selectOne("boardMapper.getDataCount",params);
        
        return result;
    }
    
    public void updateHitCount(int num){
        
        sessionTemplate.update("boardMapper.updateHitCount",num);
    }
    
    public BoardDTO getReadData(int num){
        
        BoardDTO dto = sessionTemplate.selectOne("boardMapper.getReadData",num);
        
        return dto;
    }
    
    public void deleteData(int num){
        
        sessionTemplate.delete("boardMapper.deleteData",num);
    }
    
    public void updateData(BoardDTO dto){
 
        sessionTemplate.update("boardMapper.updateData",dto);    
    }
}
cs


- BoardController.java파일은 저번거 그대로.

그러면 Mybatis를 이용한 게시판도 잘 작동한다.


-실행화면



1. AOP(Aspect Oriented Programming : 관점지향프로그래밍) 


1) AOP 개념설명


[횡단관심사]

모든 영역에 공통적으로 적용되는 코딩

어플리케이션 여러부분에 영향을 주는 기능.


그림처럼 1XX3을 찾으라고 하면 앞이 1인 15,10의 3번을 모두 검사한다.

그림처럼 횡단으로 검사하는 모습을 볼 수 있다.


[JointPoints]

애플리케이션 실행의 특정 지점을 의미

AOP에서 Aspect(횡단 관심사)를 적용하는 위치를 표시하는데 사용


[Advice]

특정 조인포인트에 적용(실행)할 코드

실행시점에 따라 Before Advice, After Advice 등으로 구현


[Pointcut]

여러 조인포인트의 집합으로 언제 어드바이스를 실행하는 위치 표시


[Aspect]

어드바이스(동작)와 포인트컷(동작을적용하는조건)을 조합해서 

횡단 관심사에 대한 코드와 그것을 적용할 지점을 정의한 것


Aspect :무엇을(Advice) 언제(Point) 할지 정의




2) 프로젝트 생성


 SpringAOP 프로젝트 만든다.


New>Spring Legacy Project>Simple Spring Utility Project(자바 콘솔에서 실행)


② Maven Repository에서 lib 다운


링크 : https://mvnrepository.com/


1) Spring AOP 

2) AspectJ Runtime 

3) AspectJ Weaver 

4) CGLib 

위의 4가지의 코드를 가져와 pom.xml에 붙여넣자.


-pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
        <!-- spring-aop -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${spring.framework.version}</version>
        </dependency>
        
        <!-- aspectjrt -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.8.10</version>
        </dependency>
        
        <!-- aspectjweaver -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.10</version>
        </dependency>
        
        <!-- cglib -->
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>3.2.4</version>
        </dependency>
cs


③ targetA, targetB 생성 및 작성


-targetA.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.exe.aop;
 
import org.springframework.stereotype.Component;
 
@Component("targetA")
public class TargetA {
 
    public void doSomething1() {
        //advice
        System.out.println("TargetA.doSomething1");
    }
    
    public void doSomething2() {
        System.out.println("TargetA.doSomething2");
    }
    
    public void doAnother1() {
        System.out.println("TargetA.doAnother1");
    }
    
    public void doAnother2() {    
        System.out.println("TargetA.doAnother2");
    }
}
cs


-targetB.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.exe.aop;
 
import org.springframework.stereotype.Component;
 
@Component("targetB")
public class TargetB {
 
    public void doSomething1() {
        //advice
        System.out.println("TargetB.doSomething1");
    }
    
    public void doSomething2() {
        System.out.println("TargetB.doSomething2");
    }
    
    public void doAnother1() {
        System.out.println("TargetB.doAnother1");
    }
    
    public void doAnother2() {
        System.out.println("TargetB.doAnother2");
    }    
}
cs


④ MyBeforeAdvice.java 생성 및 작성


1
2
3
4
5
6
7
8
package com.exe.aop;
 
public class MyBeforeAdvice {
    
    public void beforeMethodCall() {
        System.out.println("Jointpoint 메소드가 실행되기 전에...");
    }
}
cs


app-context.xml 작성


위의 코드 추가해준다.


app-context.xml에 위의 코드 써준다.

beforeAdvice라는 객체를 생성후 aspect의 매개변수로 넘겨준다.

beforePointcut이라는 이름을 임의로 정해서 포인트컷을 생성해주고

before의 기능을하는 aop:before에 매개변수로 생성한 포인트컷을 넘겨준다.

before는 beforeAdvice라는 객체의 메소드인 beforeMethodCall()이라는 함수를 메소드로 사용한다.


-app-context.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
        https://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context 
        https://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/aop 
        https://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
 
    <description>Example configuration to get you started.</description>
 
    <context:component-scan base-package="com.exe.aop" />
    
    <!-- 여기에 객체 생성 -->
    <!-- Advice -->
    <bean id="beforeAdvice" class="com.exe.aop.MyBeforeAdvice"/>
    
    <!-- Pointcut -->
    <!-- execution(public void com..aop.*.*(..)) -->
    <!-- execution(메소드접근지정자 반환값 패키지.클래스.메소드(매개변수)) -->
    <aop:config>
        <aop:aspect ref="beforeAdvice">
            <aop:pointcut id="beforePointcut" 
            expression="execution(public void com..aop.*.*(..))"/>
            
            <aop:before method="beforeMethodCall" pointcut-ref="beforePointcut"/>
        </aop:aspect>
    </aop:config>
</beans>
cs


⑥ AopMain.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package com.exe.aop;
 
import org.springframework.context.support.GenericXmlApplicationContext;
 
public class AopMain {
    
    public static void main(String[] args) {
        
        GenericXmlApplicationContext context=
                new GenericXmlApplicationContext("app-context.xml");
        
        TargetA ta=(TargetA)context.getBean("targetA");
        
        ta.doAnother1();
        ta.doAnother2();
        ta.doSomething1();
        ta.doSomething2();
        
        TargetB tb=(TargetB)context.getBean("targetB");
        
        tb.doAnother1();
        tb.doAnother2();
        tb.doSomething1();
        tb.doSomething2();
    }
}
cs


-실행화면

⑦ after도 추가해보자


그 전 before는 주석처리하고 after만 실행해보자.


-MyAfterAdvice

1
2
3
4
5
6
7
8
package com.exe.aop;
 
public class MyAfterAdvice {
    
    public void afterMethodCall() {
        System.out.println("Jointpoint 메소드가 실행된 후에...");
    }
}
cs


-app-context.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    <!-- Pointcut -->
    <!-- execution(public void com..aop.*.*(..)) -->
    <!-- execution(메소드접근지정자 반환값 패키지.클래스.메소드(매개변수)) -->
    <aop:config>
        <aop:aspect ref="beforeAdvice">
            <aop:pointcut id="beforePointcut" 
            expression="execution(public void com..aop.*.*(..))"/>
            
            <aop:before method="beforeMethodCall" pointcut-ref="beforePointcut"/>
        </aop:aspect>
        
        <aop:aspect ref="afterAdvice">
            <aop:pointcut id="afterPointcut" 
            expression="execution(public void com..aop.*.*(..))"/>
            
            <aop:after method="afterMethodCall" pointcut-ref="afterPointcut"/>
        </aop:aspect>
    </aop:config>
cs

aop:after로 형식에 맞취 써준다.


그리고 메인에서 실행


-실행화면


⑧ around 추가


-MyAroundAdvice.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.exe.aop;
 
import org.aspectj.lang.ProceedingJoinPoint;
 
public class MyAroundAdvice {
 
    public Object aroundMethodCall(ProceedingJoinPoint jointPoint) {
        
        Object result=null;
        
        try {
            
            System.out.println("JointPoint 메소드 실행전..(Around)");
            
            result=jointPoint.proceed();//메소드 실행
            
            System.out.println("JointPoint 메소드 실행후..(Around)");
            
        } catch (Throwable e) {
            System.out.println(e.toString());
        }
        
        return result;
    }
}
cs


-app-context.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    <!-- Advice -->
    <bean id="aroundAdvice" class="com.exe.aop.MyAroundAdvice"/>
    
    <!-- Pointcut -->
    <!-- execution(public void com..aop.*.*(..)) -->
    <!-- execution(메소드접근지정자 반환값 패키지.클래스.메소드(매개변수)) -->
    <aop:config>
        
        <aop:aspect ref="aroundAdvice">
            <aop:pointcut id="aroundPointcut" expression="execution(public void com..aop.*.*Some*(..))"/>
            
            <aop:around method="aroundMethodCall" pointcut-ref="aroundPointcut"/>
        </aop:aspect>
        
    </aop:config>
cs

메소드의 형식을 *Some*으로 바꿔주었다.


-AopMain.java에서 똑같이 실행하면

-실행화면

*Some* 때문에 메소드의 이름에 Some이 들어가는 메소드에만 실행되는 모습을 볼 수 있다.


⑨ after-returning 추가


-MyAfterReturningAdvice.java

1
2
3
4
5
6
7
8
package com.exe.aop;
 
public class MyAfterReturningAdvice {
 
    public void afterReturningMethodCall() {
        System.out.println("JointPoint 메소드가 정상 실행한 뒤에..");
    }
}
cs


-app-context

1
2
3
4
5
6
7
8
9
    <bean id="afterReturningAdvice" class="com.exe.aop.MyAfterReturningAdvice"/>
    
    <aop:config>
        <aop:aspect ref="afterReturningAdvice">
            <aop:pointcut id="afterReturningPointcut" expression="execution(public void com..aop.*.*A*1(..))"/>
            
            <aop:after-returning method="afterReturningMethodCall" pointcut-ref="afterReturningPointcut"/>
        </aop:aspect>
    </aop:config>
cs

메소드의 형식을 *A*1으로 바꾸고


-AopMain.java에서 똑같이 실행하면

-실행화면


⑩ after-throwing 추가

: 에러가 있을 때 실행됨


-MyAfterThrowingAdvice.java

1
2
3
4
5
6
7
8
9
package com.exe.aop;
 
//에러가 났을때
public class MyAfterThrowingAdvice {
 
    public void afterThrowingMethodCall() {
        System.out.println("JointPoint 메소드가 비정상 실행한 뒤에..");
    }
}
cs


-app-context.xml

1
2
3
4
5
6
7
8
9
10
11
12
    <bean id="afterThrowingAdvice" class="com.exe.aop.MyAfterThrowingAdvice"/>
    
    <!-- Pointcut -->
    <!-- execution(public void com..aop.*.*(..)) -->
    <!-- execution(메소드접근지정자 반환값 패키지.클래스.메소드(매개변수)) -->
    <aop:config>
        <aop:aspect ref="afterThrowingAdvice">
            <aop:pointcut id="afterThrowingPointcut" expression="execution(public void com..aop.*.*(..))"/>
            
            <aop:after-throwing method="afterThrowingMethodCall" pointcut-ref="afterThrowingPointcut"/>
        </aop:aspect>
    </aop:config>
cs


-AopMain.java에서 똑같이 실행하면

-실행화면


-모두주석 풀고 패키지.클래스.메소드명 똑같이 맞춰준뒤 실행하면

아래처럼 전체메소드(Advice들)가 실행된다.




2. 전의 AOP코드를 Annotation으로 바꾸기 


app-context에 썻던코드들 다 주석처리하고 annotation으로 바꿔준다.


-MyBeforeAdvice.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.exe.aop;
 
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
 
@Aspect
@Component
public class MyBeforeAdvice {
    
    @Before("execution(* com..aop.*.*(..))")
    public void beforeMethodCall() {
        System.out.println("Jointpoint 메소드가 실행되기 전에...");
    }
}
cs


-app-context.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
        https://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context 
        https://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/aop 
        https://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
 
    <description>Example configuration to get you started.</description>
 
    <context:component-scan base-package="com.exe.aop" />
 
     <aop:aspectj-autoproxy/>
</beans>
cs

<aop:aspectj-autoproxy/>를 써주면 annotation을 쓸 수 있게 된다.


-나머지 파일도 before처럼 다 annotation써준뒤 메인에서 실행하면

아까 마지막처럼 전체 메소드들이 실행된다.

-실행화면




이전 글의 프로젝트의 DB연결을 Mybatis로 바꿔주자.

전의 프로젝트의 일부를 가져와서 아래처럼 폴더 셋팅을 해주자.


이전 글 링크 : https://welcomto-dd.tistory.com/45



저번 프로젝트(SpringjdbcTemplate)에서 

① CustomDAO.java,

② CustomDTO.java,

③ CustomMain.java,

④ app-context.xml,pom.xml 파일을 가져온다.


1. Mybatis 환경 세팅 


링크 : https://mvnrepository.com/


1) mybatis 검색 후 mybaits, mybatis Spring의 코드를 긁어오자.



-pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    <dependencies>
        <!-- mybatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.2</version>
        </dependency>
        
        <!-- mybatis-spring -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.3.2</version>
        </dependency>
    </dependencies>
cs

긁어 온 코드를 pom.xml에 붙여넣고 저장하면 pom.xml을 읽어 라이브러리를 자동으로 받는다.


2) app-context.xml 파일 작성


-app-context.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
    <!-- mybatis setting -->
 
    <!-- 사용자 -->
    <bean id="customDAO"
    class="com.exe.springmybatis.CustomDAO">
        <property name="sessionTemplate" ref="sessionTemplate"></property>
    </bean>
 
    <!-- 제품 -->
    <bean id="sessionTemplate"
    class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg ref="sessionFactory"/>
    </bean>
    
    <!-- dataSource를 연결해주는 역할을 하는애(sessionFactory) -->
    <bean id="sessionFactory"
    class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    
    <!-- DB 연결 -->
    <bean id="dataSource"
    class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close"
    p:driverClassName="oracle.jdbc.driver.OracleDriver"
    p:url="jdbc:oracle:thin:@192.168.16.12:1521:TestDB"
    p:username="suzi"
    p:password="a123"
    />
cs

여기서 sessionFactory 부분에 property를 하나 추가해준다.


1
2
3
4
5
6
7
    <!-- dataSource를 연결해주는 역할을 하는애(sessionFactory) -->
    <bean id="sessionFactory"
    class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="configLocation"
        value="classpath:/com/exe/springmybatis/mybatis-config.xml"/>
    </bean>
cs

property name="configLocation" 바로 이부분이다.

sql 경로 설정에 관한 코드이다. 그럼 이 파일을 만들어주러 가자.


3) mybatis-config 파일 생성 및 작성


-mybatis-config.xml 파일 생성


-mybatis-config.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?xml version="1.0" encoding="UTF-8"?>
 
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
 
<configuration>
 
<!-- 다른 struts와 연결할 때 사용 -->
<properties>
    <property name="driver" value="oracle.jdbc.driver.OracleDriver"/>
    <property name="url" value="jdbc:oracle:thin:@192.168.16.12:1521:TestDB"/>
    <property name="username" value="suzi"/>
    <property name="password" value="a123"/>
</properties>
 
<environments default="development">
    <environment id="development">
        <transactionManager type="JDBC"/>
        <dataSource type="POOLED">
            <property name="driver" value="${driver}"/>
            <property name="url" value="${url}"/>
            <property name="username" value="${username}"/>
            <property name="password" value="${password}"/>
        </dataSource>
    </environment>
</environments>
 
<!-- spring하고 연결할때는 얘만 필요 -->
<mappers>
    <mapper resource="com/exe/mapper/customMapper.xml"/>
</mappers>
 
</configuration>
cs

Spring 연결에서는 mappers 부분이 sql문을 담고있는 xml파일과의 연결을 담당한다.

customMapper.xml이라는 sql을 모아놓은 파일을 작성해주러 가자.


4) customMapper.xml 파일 생성 및 작성


-패키지 및 파일 생성


-customMapper.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?xml version="1.0" encoding="UTF-8"?>
 
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 
<mapper namespace="com.exe.mapper">
 
<insert id="insert" parameterType="com.exe.springmybatis.CustomDTO">
    insert into custom(id,name,age) values(#{id},#{name},#{age})
</insert>
 
<select id="list" resultType="com.exe.springmybatis.CustomDTO">
    select id,name,age from custom
</select>
 
<select id="listOne" parameterType="int" resultType="com.exe.springmybatis.CustomDTO">
    select id,name,age from custom where id=#{id}
</select>
 
<update id="update" parameterType="com.exe.springmybatis.CustomDTO">
    update custom set name=#{name}, age=#{age} where id=#{id}
</update>
 
<delete id="delete" parameterType="int">
    delete from custom where id=#{id}
</delete>
 
</mapper>
cs


5) CustomDAO.java 파일 작성


-CustomDAO.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
package com.exe.springmybatis;
 
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
 
import javax.sql.DataSource;
 
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
 
public class CustomDAO {
 
    private SqlSessionTemplate sessionTemplate;
    
    //의존성 주입
    public void setSessionTemplate(SqlSessionTemplate sessionTemplate) {
        this.sessionTemplate=sessionTemplate;
    }
    
    Connection conn=null;
    
    //insert
    public void insertData(CustomDTO dto) {
        sessionTemplate.insert("com.exe.mapper.insert",dto);
    }
    
    //select 모든 데이터
    public List<CustomDTO> getList(){
        
        List<CustomDTO> lists=sessionTemplate.selectList("com.exe.mapper.list");
        
        return lists;
    }
    
    //select 1개의 데이터
    public CustomDTO getReadData(int id){
        
        CustomDTO dto=sessionTemplate.selectOne("com.exe.mapper.listOne",id);
        
        return dto;
    }
        
    //update
    public void updateData(CustomDTO dto) {
        
        sessionTemplate.update("com.exe.mapper.update",dto);
    }
    
    //delete
    public void deleteDate(int id) {
        sessionTemplate.delete("com.exe.mapper.delete",id);
    }
}
cs


6) 마지막으로 Main에서 실행


-CustomMain.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package com.exe.springmybatis;
 
import java.util.List;
 
import org.springframework.context.support.GenericXmlApplicationContext;
 
public class CustomMain {
 
    public static void main(String[] args) {
        
        GenericXmlApplicationContext context=new GenericXmlApplicationContext("app-context.xml");
        
        CustomDAO dao=(CustomDAO)context.getBean("customDAO");
        
        CustomDTO dto;
        
        /*
        //insert
        dto=new CustomDTO();
        dto.setId(333);
        dto.setName("안녕");
        dto.setAge(25);
        
        dao.insertData(dto);
        
        System.out.println("insert 완료!");
        */
        
        /*
        //Oneselect
        dto=dao.getReadData(111);
        
        if(dto!=null) {
            System.out.printf("%d %s %d\n",dto.getId(),dto.getName(),dto.getAge());
        }
        
        System.out.println("OneSelect 완료!");
        */
 
        //update
        dto = new CustomDTO();
        
        dto.setId(555);
        dto.setName("이지은");
        dto.setAge(27);
        
        dao.updateData(dto);
 
        
        //delete
        //dao.deleteDate(333);
 
        //select
        List<CustomDTO> lists=dao.getList();
        
        for(CustomDTO dto1:lists) {
            System.out.printf("%d %s %d\n",dto1.getId(),dto1.getName(),dto1.getAge());
        }
        
        System.out.println("select 완료!");
    }
}
cs


-실행화면

하나씩 주석 풀어주면서 테스트해보면 잘 실행된다.



+ Recent posts