학교에서 배운 JSP 관련 내용을 정리해둡니다.


본 내용은 mysql을 이용하는 db 연결부를 사용하기 편하도록 클래스로 분리하여둔 것 입니다. 사용된 외부 라이브러리들은 아래와 같습니다.


JSON-Simple-1.1.1

mysql-connector-java-5.1.24


본 내용은 이전 글( [JSP 1.x] Reflection Methods를 이용한 API구현 )과 이어집니다. 

관련된 모든 소스들은 깃허브에 업로드 되어있습니다.



목차 


1. 공용 변수 클래스 만들기

2. 공용변수 클래스를 이용해 DB Connector만들기 

3. DBConnector클래스와 API의 연동




1. 공용 변수 클래스 만들기 


API를 만들고 나서는 데이터베이스와 연결하는 부분이 필요했다. 매 API서블릿 마다 DB connector부를 만들 수는 없었기에 별도로 분리하려고 했다. 

클래스로 분리하기 먼저, JSP의 사용법을 잘 모르기... 때문에 공용 변수를 관리할 클래스를 만들어 두어야 할 필요성이 있다고 생각했다. 프로젝트를 진행하면서 connection string이외에도 다양한 값들을 공통으로 사용하게 될지 모르겠다고 생각했기 때문이다. 그 클래스는 아래와 같이 구현했다. 



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
package util;
 
/*
 * 프로젝트 공통 변수들을 Singleton으로 관리하는 클래스
 * 
 * @author      KYEONGSOO YOO
 * @Date        2018-06-04
 * */
public class CommonVariable {
    // ================================================================================
    // Properties
    // ================================================================================
    private static CommonVariable _instance = new CommonVariable();     // 실제 인스턴스
    private String jdbcDriverClassName;                                 // 디비 드라이버 명
    private String jdbcConnectionString;                                // 디비 커넥션 스트링
    private String jdbcUserAccount;                                     // 디비 사용자 명
    private String jdbcUserPassword;                                    // 디비 사용자 비밀번호
 
    // 디비 변수 관련 열거형
    public enum CV_DB_VARIABLE {
        DRIVER_NAME, CONNECTION_STRING, USER_ACCOUNT, USER_PASSWORD
    }
 
    // ================================================================================
    // Constructor
    // ================================================================================
    private CommonVariable() {
        jdbcDriverClassName = "com.mysql.jdbc.Driver";
        jdbcConnectionString = "jdbc:mysql://localhost:3306/whistle";
        jdbcUserAccount = "root";
        jdbcUserPassword = "1111";
    }
 
    // ================================================================================
    // Methods
    // ================================================================================
    /*
     * 공통 변수 클래스의 인스턴스를 가져온다. (본 클래스는 따로 Constructor를 실행하지 않음)
     * 
     * @author                  KYEONGSOO YOO
     * 
     * @return  Class           현재 클래스의 인스턴스 (singleton)
     */
    public static synchronized CommonVariable getInstance() {
        return _instance;
    }
 
    /*
     * 데이터베이스에 관련된 항목들만 가져온다
     * 
     * @param   type            가져올 항목의 열거형 코드
     * @return  String          각 코드에 맞는 private 변수들 
     */
    public String getDBInfo(CV_DB_VARIABLE type) {
        String ret;
        switch (type) {
        case DRIVER_NAME:
            ret = jdbcDriverClassName;
            break;
        case CONNECTION_STRING:
            ret = jdbcConnectionString;
            break;
        case USER_ACCOUNT:
            ret = jdbcUserAccount;
            break;
        case USER_PASSWORD:
            ret = jdbcUserPassword;
            break;
        default:
            ret = "";
            break;
        }
 
        return ret;
    }
}
cs




2. 공용변수 클래스를 이용해 DB Connector만들기 


위 클래스를 이용해 , 본격적으로 DB CONNECTOR를 만들기로 했다. 구성은 아래와 같다. 


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
package util;
 
import java.sql.*;
import org.json.simple.*;
import org.json.simple.parser.*;
 
/*
 * 데이터베이스와의 연결을 위한 클래스 
 * 
 * @author          KYEONGSOO YOO
 * @Date            2018-06-05
 * */
public class DBConnector {
    // ================================================================================
    // Properties
    // ================================================================================
    private CommonVariable _cv;
    
    // ================================================================================
    // Constructor
    // ================================================================================
    public DBConnector() {
        super();
        _cv = CommonVariable.getInstance();
    }
    
    // ================================================================================
    // private Methods
    // ================================================================================
    private Connection connect() throws ClassNotFoundException, SQLException {
        Class.forName(_cv.getDBInfo(CommonVariable.CV_DB_VARIABLE.DRIVER_NAME));
        String sConn = _cv.getDBInfo(CommonVariable.CV_DB_VARIABLE.CONNECTION_STRING);
        String sAcc = _cv.getDBInfo(CommonVariable.CV_DB_VARIABLE.USER_ACCOUNT);
        String sPw = _cv.getDBInfo(CommonVariable.CV_DB_VARIABLE.USER_PASSWORD);
        Connection conn = DriverManager.getConnection(sConn, sAcc, sPw);
        return conn;
    }
 
    // ================================================================================
    // public Methods
    // ================================================================================
    
    /*
     * 디비에 인서트 / 업데이트를 진행할때 사용할 함수. 
     * 쿼리 자체를 트랜잭션을 짤 수 없어서 실제 문제 없이 처리되었을때만 commit되도록 처리하였다. 
     * 
     * @author              KYEONGSOO YOO 
     * @param   query       업데이트에 사용할 쿼리 
     * @return  JSONObject  affectedRow라는 변수를 담고있다. 실제 영향을 미친 row 수 이다. 
     * */
    public JSONObject update(String query) throws ClassNotFoundException, SQLException {
        Connection conn = null;
        Statement stmt = null;
        int affectedRowCnt = 0;
        JSONObject ret = new JSONObject();
        try {
            conn = connect();
            conn.setAutoCommit(false);
            stmt = conn.createStatement();
            affectedRowCnt = stmt.executeUpdate(query);
 
            conn.commit();
        } catch (SQLException e) {
            conn.rollback();
        } finally {
            if (stmt != null)
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            if (conn != null)
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
 
            ret.put("affectedRow", affectedRowCnt);
        }
 
        return ret;
    }
 
    /*
     * 데이터베이스 조회용 함수 
     * 
     * @author              KYEONGSOO YOO
     * @param   query       조회에 사용할 함수, insert/update문을 이곳에서 사용하지 말것.
     * @return  JSONArray   조회된 내용들 
     * */
    public JSONArray excute (String query) throws ClassNotFoundException, SQLException {
        System.out.println("ex0-start");
        System.out.println(query);
        System.out.println("ex0-end");
        Connection conn = connect();
        Statement stmt = conn.createStatement();
        ResultSet rs = stmt.executeQuery(query);
        
        JSONArray result = new JSONArray();
        
        int colCnt = rs.getMetaData().getColumnCount();
        while (rs.next()) {
            JSONObject item = new JSONObject();
            for (int i = 1; i < colCnt; i++) {
                item.put(rs.getMetaData().getColumnName(i), rs.getString(i));
 
            }
            result.add(item);
        }
 
        if (stmt != null)
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        if (conn != null)
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        if (rs != null)
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
 
        return result;
    }
}
 
cs


함수는 각각 셀렉트를 위한 execute와 업데이트 , 인서트 , 딜리트의 트랜잭션 처리가 동반된 update함수가 있다. 쿼리 자체를 따로 검증하지 않으므로, 실제 사용시에 유의하여야 한다. 




3. DBConnector클래스와 API의 연동


클래스를 만들고 난 이후에 API에 실제 사용하는 모습이다. API의 전문은 깃허브에서 확인 할 수 있다.


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
 
    // ================================================================================
    // Sample
    // ================================================================================
 
    /*
     * 예시 함수 
     * 조회를 시행해야 하는 경우.
     * 메소드 리플렉션과 데이터베이스 요청을 포함하기 때문에 예외처리 항목에 
     * ClassNotFoundException / SQLException 항목이 포함되어야 한다. 
     * NOTE : 로그인을 예제로 사용함  
     * */
    public JSONObject mockup_select (JSONObject params) throws ClassNotFoundException, SQLException{
        JSONObject ret = new JSONObject();
           
        
        /*
         * JSONObject params에 아래와 같은 변수들이 들어있는 경우 
         * */
        String mail = (String) params.get("userMail");
        String pw = (String) params.get("userPW");
        
        // 데이터 베이스 요청을 위한 문자열 
        // 잦은 String append는 성능과 가독성에 좋지 않아 String.format을 사용하도록 함 
        String query = String.format("select * from tb_user where userMail = '%s' and userPw = '%' ", mail , pw);
        
        // DB에 연결하기 위함 클래스를 초기화한다.
        // 본 클래스는 util 패키지에 들어있다.
        DBConnector dc = new DBConnector();
        
        // 셀렉트 결과를 가져온다. 
        // 셀렉트시에는 반드시 execute함수를 사용해야 한다.
        // 아래 함수는 insert , update , delete시 사용하지 않도록 조심해야한다.
        // DB 연결 함수들은 항상 try catch문으로 감싸두어야 한다. 오류 검출을 위
        JSONArray db_result = null;
        try {
            db_result = dc.excute(query); 
        }
        catch(SQLException e) {
            // 실제 에러가 발생한 부분을 서버 콘솔상에 출력한다. 
            e.printStackTrace(System.out);
            
            // 실패한 결과에는 반드시 ret JSON에 아래 키들을 포함해야한다. 
            /*
             * METHOD_RESULT_CD         integer             : 결과 코드이다. 실패한 경우 0보다 작은 값을 순서대로 넣는다. 
             * METHOD_ERR_MSG           String              : 요구 사항에 따라 직접 메시지를 삽입.
             * METHOD_ERR_LOCALE_MSG    String              : 예외처리를 통해 오류가 발생한 경우에만 삽입한다. 
             * */
            ret.put("METHOD_RESULT_CD" , -1);
            ret.put("METHOD_ERR_LOCALE_MSG", e.getLocalizedMessage());
        }
        
        // JSONArray 객체는 배열이 아니라 리스트 클래스를 상속받는다.
        // 배열처럼 사용하기 위해서는 먼저 변환해주어야 한다. 
        Object[] items = db_result.toArray();
        
        if(items.length > 0) {
            // 하나 이상 값이 조회되었을 경우 1보다 갯수가 크다. 
            // 로그인이 성공한 것으로 판단하고 데이터를 돌려보낸다.
            
            // 성공한 결과에는 반드시 ret JSON에 아래 키들을 포함해야한다. 
            /*
             * METHOD_RESULT_CD     integer                 : 결과 코드이다. 성공한 경우 1을 출력한다. 
             *                                              만약 실패 한다면 0보다 작은 값으로 코드를 변경한다. (ex : -1)
             * METHOD_RESULT_DATA   JSONObject/JSONArray    : 조회된 결과 데이터이다. JSONObject 혹은 JSONArray를 넣어주도록 한다.
             * */
            ret.put("METHOD_RESULT_CD"1);
            ret.put("METHOD_RESULT_DATA", db_result);
        }
        else {
            // 로그인이 실패한 경우이다. 
            // 이 경우에는 직접 메시지를 넣어주면된다. 서버 오류로 인한 예외가 아니라 사용자 입력에 따른 예외기 떄
            ret.put("METHOD_RESULT_CD" , -2);
            ret.put("METHOD_ERR_MSG""아이디 혹은 비밀번호를 확인해주세요");   
        }
        
        
        return ret;
    }
    
    /*
     * 예시 함수 
     * 업데이트를 시행해야 하는 경우.
     * 메소드 리플렉션과 데이터베이스 요청을 포함하기 때문에 예외처리 항목에 
     * ClassNotFoundException / SQLException 항목이 포함되어야 한다. 
     * NOTE : 사용자 이름 변경하는 예제. 아래의 내용은 insert / update / delete에 공통으로 사용 
     * */
    public JSONObject mockup_update(JSONObject params) throws ClassNotFoundException, SQLException{
        JSONObject ret = new JSONObject();
        // Db와 통신 후 확인할 객체이다. 
        JSONObject dbJSON = null;
       
        // 사용할 값을 가져온다. 
        String userName = (String) params.get("userName");
        int userSeq = (int) params.get("userSeq");
        
        // 항목이 null 혹은 공백문자가 아닌지 확인 
        // 일부러 비워두도록 업데이트하는것이 아니라면 항상 확인해야한다. 
        // insert / update / delete 항목들은 되도록 엄격하게 유효성 검사를 거쳐야 한다. 
        if(userName == null || userName.isEmpty()) {
            ret.put("METHOD_RESULT_CD"-1);
            ret.put("METHOD_ERR_MSG""이름을 입력해주세요");
        }
        else {
            // 업데이트에 필요한 쿼리문을 작성 
            String query = String.format("update TB_User set userName = '%s' where userSeq = '%s'", userName , userSeq);
            
            // 데이터 베이스 연결용 클래스를 초기화해준다. 
            DBConnector dc = new DBConnector();
            
            try {
                // 위와 동일하다 
                // insert / update / delete를 사용할때는 아래 함수를 사용하도록 한다. 
                // 아래 함수는 오류가 발생하면 다시 디비를 이전 상태로 복구한다. 
                dbJSON = dc.update(query);
            }
            catch(SQLException e) {
                e.printStackTrace(System.out);
                ret.put("METHOD_RESULT_CD"-1);
                ret.put("METHOD_ERR_MSG""통신 중 오류가 발생했습니다");
                ret.put("METHOD_ERR_LOCALE_MSG", e.getLocalizedMessage());
            }
            
            // 실제 결과를 담아둔다. 
            // 이 데이터에는 실제로 영향을 받은 데이터들의 row count가 들어간다. 
            // 한건의 업데이트만 발생하면 1만 넘어간다. 아무것도 영향받지 못하면 0이 넘어간다. 
            ret.put("METHOD_RESULT_DATA", dbJSON.get("affectedRow"));
        }
        
        return ret;
    }
 
cs


'DEV > JSP' 카테고리의 다른 글

[JSP 1.x] ReflectionMethod를 이용한 API 서블릿 구현  (0) 2018.06.20

+ Recent posts