학교에서 배운 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
학교에서 배운 JSP 내용을 정리해둡니다.

본 내용은 일반 JSP 환경에서 Reflection Method를 이용해 API 서블릿을 만드는 방법을 남겨둔 것입니다. 
파라미터와 반환값은 JSONObject를 사용하므로, 가벼운 JSON 관련 클래스를 사용했습니다.



본 기능의 목적은 아래와 같다 .


1. 특정 서블릿의 주소로 비동기 통신 요청 

2. 요청은 서블릿으로 받는다. ex) /api/user

3. 실행할 함수는 JSON 객체로 받는다 ex) { 'fn_nm' : 'get' , 'params' : {  ... } }


위 단계를 구현하기 위해서 먼저 스트링으로 받은 함수명을 reflection method로 실행하는 부분이 필요한데, 그부분은 아래와같이 클래스로 분리하였다.


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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
package util;
import java.lang.reflect.*;
import org.json.simple.*;
/*
 * API 서블릿에서 리플렉션을 사용하기 위한 클래스 
 * 
 * @author          KYEONGSOO YOO
 * @Date            2018-06-01
 * */
public class ReflectionMethod {
    // ================================================================================
    // Properties
    // ================================================================================
    private static Class<>; _parentClass;
    private static Method[] _parentMethods;
    private static Object _parentClassInstance;
    // ================================================================================
    // Constructor
    // ================================================================================
    /*
     * ReflectionMEthod 클래스의 생성자 함수이다. 인스턴스가 존재해야한다. 보통 실행할 함수가 속한 클래스의 this를 넘겨주면
     * 된다.
     * 
     * 수정 2018-06-19 KYEONGSOO YOO
     * 초기화 부분을 함수 실행시로 옮김 
     * 
     * @author                  KYEONGSOO YOO
     * 
     */
    public ReflectionMethod() {
        super();
    }
    
    // ================================================================================
    // private methods
    // ================================================================================
    /*
     * 내부 함수이다. 생성자가 제대로 동작했는지 체크한다.
     * 
     * @author                  KYEONGSOO YOO
     * @return                  생성자가 제대로 생성되었는지 여부 (Boolean)
     */
    private boolean chkState() {
        return !(_parentMethods == null || _parentMethods.length &lt; 0);
    }
    /*
     * 현재 클래스에서 String을 기준으로 함수를 가져온다. 만약 함수가 존재하지 않으면 null을 리턴한다.
     * 
     * @author                  KYEONGSOO YOO
     * @param   name            가져올 함수의 이름
     * @return                  가져온 함수 , 존재하지 않으면 null
     */
    private Method get(String name) {
        for (Method fn : _parentMethods) {
            if (fn.getName().equals(name)) {
                return fn;
            }
        }
        System.out.println("[RM] can not find method by [" + name + "]");
        return null;
    }
    
    private boolean setInstance(Object instance) {
        if(instance != null) {
            _parentClassInstance = instance;
            _parentClass = _parentClassInstance.getClass();
            _parentMethods = _parentClass.getDeclaredMethods();
            return true;
        }
        else {
            return false;
        }
        
    }
    
    /*
     * 현재 클래스에 함수가 존재하는지 여부를 확인한다.
     * 
     * @author                  KYEONGSOO YOO
     * @param   name            가져올 함수의 이름
     * @return                  함수의 존재 여부
     */
    private boolean exists(String fn_nm) {
        for (int i = 0; i &lt; _parentMethods.length; i++) {
            // System.out.println(_parentMethods[i]);
            if (_parentMethods[i].getName().equals(fn_nm)) {
                return true;
            }
        }
        return false;
    }
    /*
     * 현재 클래스에서 함수를 가져오고 실제로 실행한다. 변수들은 json으로 받고 그 결과도 json으로 넘겨준다.
     * 
     * @author              KYEONGSOO YOO
     * @param   fn_nm       가져올 함수의 이름
     * @param   params      함수에 넘겨줄 매개변수들, json
     * @return              함수 실행 결과, json
     */
    private JSONObject invoke(String fn_nm, JSONObject params) {
        JSONObject obj = new JSONObject();
        try {
            Method fn = get(fn_nm);
            Object value = fn.invoke(_parentClassInstance, params);
            obj.put("INVOKE_RESULT_CD"1);
            obj.put("INVOKE_DATA", value);
            return obj;
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            obj.put("INVOKE_RESULT_CD"-1);
            obj.put("INVOKE_ERR_MSG", e.getLocalizedMessage());
            return obj;
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            obj.put("INVOKE_RESULT_CD"-2);
            obj.put("INVOKE_ERR_MSG", e.getLocalizedMessage());
            return obj;
        } catch (InvocationTargetException e) {
            // TODO Auto-generated catch block
            obj.put("INVOKE_RESULT_CD"-3);
            obj.put("INVOKE_ERR_MSG", e.getLocalizedMessage());
            return obj;
        }
    }
    /*
     * 클래스의 함수를 실행하고 결과 json까지 만들어준다. invoke, exists, get을 합친 것이다. 본 함수를 사용할
     * 
     * @author              KYEONGSOO YOO
     * @param   fn_nm       가져올 함수의 이름
     * @param   params      함수에 넘겨줄 매개변수들, json
     * @return              함수 실행 결과, json
     */
    private JSONObject callAndGetResult(String fn_nm, JSONObject params) {
        JSONObject jsonObj = new JSONObject();
        if (chkState()) {
            if (exists(fn_nm)) {
                JSONObject ret = invoke(fn_nm, params);
                int resultCD = (int) ret.get("INVOKE_RESULT_CD");
                if (resultCD &gt; 0) {
                    jsonObj.put("RESULT""SUCCESS");
                    jsonObj.put("RESULT_CD"1);
                    jsonObj.put("RESULT_DATA", ret.get("INVOKE_DATA"));
                } else {
                    jsonObj.put("RESULT""FAIL");
                    jsonObj.put("RESULT_CD"-2);
                    jsonObj.put("ERR_MSG""[RM] 요청된 함수 [" + fn_nm + "]의 실행 중 오류가 발생했습니다.");
                    jsonObj.put("INVOKE_ERR_MSG", ret.get("INVOKE_ERR_MSG"));
                    jsonObj.put("INVOKE_ERR_CD", ret.get("INVOKE_RESULT_CD"));
                }
            } else {
                jsonObj.put("RESULT""FAIL");
                jsonObj.put("RESULT_CD"-1);
                jsonObj.put("ERR_MSG""[RM] 요청된 함수 [" + fn_nm + "]이 존재하지 않습니다.");
                System.out.println("METHOD IS NOT EXISTS - start");
                for(int i = 0 ; i &lt; _parentMethods.length ; i++) {
                    System.out.println(_parentMethods[i].getName());
                }
                System.out.println("METHOD IS NOT EXISTS - end");
            }
        } else {
            jsonObj.put("RESULT""FAIL");
            jsonObj.put("RESULT_CD"0);
            jsonObj.put("ERR_MSG""[RM] 리플렉션 클래스가 정상적으로 초기화되지 않았습니다.");
        }
        return jsonObj;
    }
    
    // ================================================================================
    // public Methods
    // ================================================================================
    /*
     * 현재 클래스에 함수가 존재하는지 여부를 확인한다.
     * 
     * @author                  KYEONGSOO YOO
     * @param   name            가져올 함수의 이름
     * @param   instance        확인할 클래스의 인스턴스 
     * @return                  함수의 존재 여부
     */
    public boolean exists(String fn_nm , Object instance) {
        if(setInstance(instance)) {
            return exists(fn_nm);
        }
        else {
            return false;
        }
    }
    /*
     * 클래스의 함수를 실행하고 결과 json까지 만들어준다. invoke, exists, get을 합친 것이다. 본 함수를 사용할
     * 
     * @author              KYEONGSOO YOO
     * @param   fn_nm       가져올 함수의 이름
     * @param   params      함수에 넘겨줄 매개변수들, json
     * @param   instance        확인할 클래스의 인스턴스 
     * @return              함수 실행 결과, json
     */
    public JSONObject callAndGetResult(String fn_nm , JSONObject params, Object instance) {
        if(setInstance(instance)) {
            return callAndGetResult(fn_nm, params);
        }else {
            JSONObject ret = new JSONObject();
            ret.put("RESULT" , "FAIL");
            ret.put("RESULT_CD"1);
            ret.put("ERR_MSG" , "클래스의 인스턴스가 주어지지 않았습니다.");
            return ret;
        }
    }
}
 
cs



아래와 같이 분리한 이후에는 특정 주소를 처리 하는 서블릿을 만들고 아래와 같이 구현한다. 


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 api;
 
import java.io.IOException;
 
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.xml.ws.http.HTTPException;
 
import java.sql.*;
import util.*;
import org.json.simple.*;
import org.json.simple.parser.*;
 
/**
 * Servlet implementation class users
 */
@WebServlet("/API/users")
public class users extends HttpServlet {
    private static final long serialVersionUID = 1L;
    private static ReflectionMethod rm;
    private CommonVariable cv;
 
    private HttpSession _session = null;
 
    /**
     * @see HttpServlet#HttpServlet()
     */
    public users() {
        super();
        // TODO Auto-generated constructor stub
        rm = new ReflectionMethod();
        cv = CommonVariable.getInstance();
    }
 
    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
     *      response)
     */
 
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // TODO Auto-generated method stub
        _session = request.getSession();
 
        JSONParser parser = new JSONParser();
        JSONObject prms = null;
        try {
            prms = (JSONObject) parser.parse(request.getParameter("params"));
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
 
        JSONObject jsonObj = rm.callAndGetResult(request.getParameter("fn"), prms ,this);
        response.setCharacterEncoding("UTF-8");
        response.getWriter().append(jsonObj.toJSONString());
 
    }
 
    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
     *      response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // TODO Auto-generated method stub
        // doGet(request, response);
        JSONParser parser = new JSONParser();
        JSONObject prms = null;
        try {
            prms = (JSONObject) parser.parse(request.getParameter("params"));
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
 
        _session = request.getSession();
 
        JSONObject jsonObj = rm.callAndGetResult(request.getParameter("fn"), prms, this);
        response.setCharacterEncoding("UTF-8");
        response.getWriter().append(jsonObj.toJSONString());
 
    }
}
 
cs


위와 같이 구현한 경우 요청 시에는 {  fn_nm : 'mockup' , params: { ... } } 형태로 값을 넘기면, fn_nm에 문자열로 넘긴 함수명을 찾아 실행하게 된다. 

아래에 만약 mockup 이라는 함수를 구현해 사용한다면,

public JSONObject mockup(JSONObject params);

라는 형태로 함수를 구현하면 된다.  


아래는 mysql과 연동 하였을 경우의 예제이다. 


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
/*
     * 예시 함수 
     * 조회를 시행해야 하는 경우.
     * 메소드 리플렉션과 데이터베이스 요청을 포함하기 때문에 예외처리 항목에 
     * 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;
    }
    
cs


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

[JSP 1.x] DB 사용부를 클래스로 분리하기  (0) 2018.06.20

+ Recent posts