728x90

-개발환경-

IDE : Eclipse IDE for Java Developers Version: 2020-03 (4.15.0)
language : java 8
DB GUI : SQLyog Community - MySQL GUI v12.2.1 ( 64 bit )
MySQL : MySQL Server 5.5

 

-Server-

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
package networkTest3;
 
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
 
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
 
import com.koreait.interfaceTest.interfaceTest;
 
public class Server3 extends JFrame implements ActionListener,Runnable{
    //JAVA UI
    JTextArea textArea; 
    JPanel panel; 
    JTextField textField;
    JButton button;
    //Network
    ServerSocket serverSocket;
    Socket socket;
    PrintWriter printWriter;
    Scanner scanner;
    String message="";
    
    
    public Server3() {
        setTitle("채팅창");
        setBounds(8050400500);
        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                if(printWriter!=null) {
                    printWriter.write("나갈게요\n");
                    printWriter.write("bye\n");
                    printWriter.flush();
 
                    if(serverSocket!=null)try {serverSocket.close();} catch (IOException e1) {e1.printStackTrace();}
                    if(socket!=null)try {socket.close();} catch (IOException e1) {e1.printStackTrace();}
                    if(printWriter!=null)try {printWriter.close();} catch (Exception e1) {e1.printStackTrace();}
                    if(scanner!=null)try {scanner.close();} catch (Exception e1) {e1.printStackTrace();}
 
                    System.exit(0);
                }
            }
        });
        
        //Center
        textArea=new JTextArea();
        textArea.setBackground(Color.orange);
        textArea.setEditable(false);//편집 불가능
        
        //bottom
        panel=new JPanel(new BorderLayout());
        button=new JButton("입력");
        textField=new JTextField();
        
        //actionlistener
        button.addActionListener(this);
        textField.addActionListener(this);
        
        //subRegister
        panel.add(textField,BorderLayout.CENTER);
        panel.add(button,BorderLayout.EAST);
        
        //size
        panel.setPreferredSize(new Dimension(40040));
        
        //Register
        add(textArea,BorderLayout.CENTER);
        add(panel,BorderLayout.SOUTH);
        
        setVisible(true);
    }
    
    public static void main(String[] args) {
        Server3 server = new Server3();
        try {
            server.serverSocket=new ServerSocket(10004);
            server.message= "192.168.0.12 서버의 10004 번 포트로 서버 시작\n";
            server.message+="클라이언트가 접속하기를 기다립니다.\n";
            server.textArea.setText(server.message);
            
            server.textField.setEnabled(false);
            server.button.setEnabled(false);
            
            server.socket=server.serverSocket.accept();
            server.message= server.socket+ "접속 성공\n"+ server.message;
            server.textArea.setText(server.message);
            
            server.textField.setEnabled(true);
            server.button.setEnabled(true);
            server.textField.requestFocus();
            
            server.printWriter =new PrintWriter(server.socket.getOutputStream());
            server.scanner= new Scanner(server.socket.getInputStream());
            
            new Thread(server).start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
 
    @Override
    public void actionPerformed(ActionEvent e) {
        String msg=textField.getText().trim();
        if(msg.length()>0) {
            message=  message + "server >> " + msg+ "\n";
            textArea.setText(message);
            
            if(printWriter!=null) {
                printWriter.write(msg+"\n");
                printWriter.flush();
            }
        }
        textField.setText("");
        textField.requestFocus();
    }
 
    @Override
    public void run() {
        while(socket!=null) {
            String msg="";
            try {
                msg=scanner.nextLine().trim();
            } catch (Exception e) {
                break;
            }
            if(msg.length()>0) {
                message= message+ "Client >> " +msg +"\n";
                textArea.setText(message);
                if(msg.toLowerCase().equals("bye")) 
                    break;
                try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}
            }
        }
        textField.setEnabled(false);
        button.setEnabled(false);
        if(serverSocket!=null)try {serverSocket.close();} catch (IOException e) {e.printStackTrace();}
        if(socket!=null)try {socket.close();} catch (IOException e) {e.printStackTrace();}
        if(printWriter!=null)try {printWriter.close();} catch (Exception e) {e.printStackTrace();}
        if(scanner!=null)try {scanner.close();} catch (Exception e) {e.printStackTrace();}
    
    }
}
 
cs

 

더보기

-Description-

Server3 생성자에는 UI 구성

 

72 : 채팅입력후 enter 누르면 actionlistener가 실행되도록  textField에도 actionlistener를 걸어줌

91 : 포트번호를 10004번 포트로한 ServerSocket 객체생성 (포트번호는 만번때 이후로는 자유로히 사용가능)

96~97 : 클라이언트와 연결전에 입력칸(textfield)와 버튼(button) 비활성화

99 : 클라이언트 연결 대기

103~104 : 입력칸(textfield)와 버튼(button) 활성화

105 : 초점을 textfield로 설정 

107~108 : 서버-클라이언트간 I/O를 위한 출력,입력 객체 생성

110 : 클라이언트로부터의 메세지를 주기적으로 받아들이는 Thread 실행

124 : 클라이언트로 메세지 전달  ( 메세지의 끝부분 에는 "\n"이 들어가야함 )

125 : 전달버퍼가 꽉차기 전에도 전달가능하게함 

137 : 들어온 메세지를 읽어들임

141~147 : 들어온 메세지를 가공해서 textArea에 출력 

151~154 : 통신객체들을 close() 해준다

-Client-

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
package networkTest3;
 
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
 
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
 
public class Client3 extends JFrame implements ActionListener,Runnable{
    //JAVA UI
        JTextArea textArea; 
        JPanel panel; 
        JTextField textField;
        JButton button;
        //Network
        Socket socket;
        PrintWriter printWriter;
        Scanner scanner;
        String message="";
        
        public Client3() {
            setTitle("채팅창");
            setBounds(50050400500);
            addWindowListener(new WindowAdapter() {
                @Override
                public void windowClosing(WindowEvent e) {
                    if(printWriter!=null) {
                        printWriter.write("나갈게요\n");
                        printWriter.write("bye\n");
                        printWriter.flush();
 
                        if(socket!=null)try {socket.close();} catch (IOException e1) {e1.printStackTrace();}
                        if(printWriter!=null)try {printWriter.close();} catch (Exception e1) {e1.printStackTrace();}
                        if(scanner!=null)try {scanner.close();} catch (Exception e1) {e1.printStackTrace();}
 
                        System.exit(0);
                    }
                }
            });
            
            //Center
            textArea=new JTextArea();
            textArea.setBackground(Color.orange);
            textArea.setEditable(false);//편집 불가능
            
            //bottom
            panel=new JPanel(new BorderLayout());
            button=new JButton("입력");
            textField=new JTextField();
            
            //actionlistener
            button.addActionListener(this);
            textField.addActionListener(this);
            
            //subRegister
            panel.add(textField,BorderLayout.CENTER);
            panel.add(button,BorderLayout.EAST);
            
            //size
            panel.setPreferredSize(new Dimension(40040));
            
            //Register
            add(textArea,BorderLayout.CENTER);
            add(panel,BorderLayout.SOUTH);
            
            setVisible(true);
        }
        public static void main(String[] args) {
            Client3 client = new Client3();
            try {
                client.socket=new Socket("192.168.0.12"10004);
                client.message= "192.168.0.12 서버의 10004 번 포트로 서버 접속\n";
                client.message+="서버로 접속 성공\n";
                client.textArea.setText(client.message);
                
                client.textField.setEnabled(true);
                client.button.setEnabled(true);
                client.textField.requestFocus();
                
                client.printWriter =new PrintWriter(client.socket.getOutputStream());
                client.scanner= new Scanner(client.socket.getInputStream());
                
                new Thread(client).start();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        @Override
        public void actionPerformed(ActionEvent e) {
            String msg=textField.getText().trim();
            if(msg.length()>0) {
                message=  message + "Client >> " + msg+ "\n";
                textArea.setText(message);
                
                if(printWriter!=null) {
                    printWriter.write(msg+"\n");
                    printWriter.flush();
                }
            }
            textField.setText("");
            textField.requestFocus();
        }
 
        @Override
        public void run() {
            while(socket!=null) {
                String msg="";
                try {
                    msg=scanner.nextLine().trim();
                } catch (Exception e) {
                    break;
                }
                if(msg.length()>0) {
                    message= message+ "Server >> " +msg +"\n";
                    textArea.setText(message);
                    if(msg.toLowerCase().equals("bye")) 
                        break;
                    try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}
                }
            }
            textField.setEnabled(false);
            button.setEnabled(false);
            if(socket!=null)try {socket.close();} catch (IOException e) {e.printStackTrace();}
            if(printWriter!=null)try {printWriter.close();} catch (Exception e) {e.printStackTrace();}
            if(scanner!=null)try {scanner.close();} catch (Exception e) {e.printStackTrace();}
        
        }
}
 
cs
더보기

-Description

85 : client.socket=new Socket("192.168.0.12", 10004) 인자로 IP주소, 포트번호를 전달

 

 

-요약-

네트워크 통신을 위하여

Socket ,  PrintWriter(전달하는 입장) , Scanner (받는입장) 객체변수 생성, 

함수로는 socket.getOutputStream() , socket.getInputStream() 을 사용하여

PrintWriter 객체생성, Scanner 객체 생성이 필요함을 배웠다.

네트워크 통신종료후에는 해당 객체들의 close() 명령이 필요하다.

-마침글-

네트워크 통신을 이용한 채팅프로그램을 제작해 보았다.

'21년이전 > 국비-JAVA+SQL' 카테고리의 다른 글

Memo 기능구현  (0) 2021.02.23
728x90

-개발환경-

IDE : Eclipse IDE for Java Developers Version: 2020-03 (4.15.0)
DB GUI : SQLyog Community - MySQL GUI v12.2.1 ( 64 bit )
MySQL : MySQL Server 5.5

추가 자료 : mysql-connector-java-5.1.27-bin.jar 드라이버 파일


-설정-

Eclipse -> Package Explorer -> 생성한 패키지의 오른쪽 마우스 클릭 -> Build Path

-> Configure Build Path.. ->Library 탭 click -> Add JARs.. ->  mysql-connector-java-5.1.27-bin.jar 선택

 

-구성-

Memo package composition

 

-DbUtil-

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
package DbTest;
 
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
 
public class DbUtil {
    //mysql에 연결하는 connection을 리턴하는 메소드
    public static Connection getMySQLConnection() {
        Connection conn=null;//db와 연결함
        try {
            Class.forName("com.mysql.jdbc.Driver");
//            String url= "jdbc:mysql://localhost:3306/javaam";
            //위와 같이 url을 작성하면 한글이 "?"로 입력되는 문제가 발생된다.
            //유니코드(UTF-8)를 사용할 경우 아래와 같이 url에 유니코드를 사용하도록 코딩을 추가하면 한글이 정상적으로 입력된다.
            String url= "jdbc:mysql://localhost:3306/javaam?useUnicode=true&characterEncoding=UTF-8";
            conn= DriverManager.getConnection(url,"root","0000");
        } catch (ClassNotFoundException e) {
            System.out.println("드라이버 클래스가 없거나 읽어올수 없습니다.");
        } catch (SQLException e) {
            System.out.println("데이터베이스 접속 정보가 올바르지 않습니다.");
        }
        return conn;
    }
    
    //데이터베이스 작업에 사용한 객체를 닫는 메소드
    public static void close(Connection conn) {
        if(conn!=null) {
            try {conn.close();} catch (SQLException e) {e.printStackTrace();}
        }
    }
    public static void close(Statement conn) {
        if(conn!=null) {
            try {conn.close();} catch (SQLException e) {e.printStackTrace();}
        }
    }
    public static void close(PreparedStatement conn) {
        if(conn!=null) {
            try {conn.close();} catch (SQLException e) {e.printStackTrace();}
        }
    }
    public static void close(ResultSet conn) {
        if(conn!=null) {
            try {conn.close();} catch (SQLException e) {e.printStackTrace();}
        }
    }
}
 
cs

-java와 sql 연동하는 DbUtil class

더보기

-Desciption-

15 : Class.forName("com.mysql.jdbc.Driver");    동적로딩 수행

동적로딩 : 어떠한 클래스가 로딩 될지 모르기 때문에 Class.forName()함수를 이용해서 해당 클래스를 메모리로 로딩함

 

-MemoProject-

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
package DbTest;
 
import java.util.ArrayList;
import java.util.Scanner;
 
public class MemoProject {
 
    public static void main(String[] args) {
        int choosed=0;
        while (choosed!=5) {
            System.out.println("==================================================");
            System.out.println("1.입력 2.목록보기 3.수정 4.삭제 5.종료");
            System.out.println("==================================================");
            do {
                Scanner scanner =new Scanner(System.in);
                choosed=Integer.valueOf(scanner.nextLine());
            }while!(1<=choosed && choosed<8));
            
            switch(choosed) {
            case 1: Insert(); break;
            case 2: select();break;
            case 3: update();break;
            case 4: delete();break;
            }
            
        }
        System.out.println("프로그램을 종료합니다");
    }
 
    private static void update() {
        System.out.println("수정할 글 번호를 입력하세요 : ");
        int idx=new Scanner(System.in).nextInt();
        
        if(MemoDAO.update(idx)) {
            System.out.println(idx+"번 글 수정완료!");
        }else {
            System.out.println(idx+ "해당 글이 존재하지 않거나 비밀번호가 올바르지 않습니다.");
        } 
}
 
 
    private static void delete() {
        System.out.println("삭제할 글 번호를 입력하세요 : ");
        int idx=new Scanner(System.in).nextInt();
        
        if(MemoDAO.delete(idx)) {
            System.out.println(idx+"번 글 삭제완료!");
        }else {
            System.out.println(idx+ "해당 글이 존재하지 않거나 비밀번호가 올바르지 않습니다.");
        }
        
    }
 
 
    private static void select() {
        ArrayList<MemoVO> list=MemoDAO.select();
        
        //반드시 null을 먼저 비교해야함. 이유 : null이면 , list.size()는 에러남.
        if(list==null || list.size()==0) {
            System.out.println("빈 ArrayList입니다.");
        }else {
            for(MemoVO vo: list) {
                System.out.println(vo);
            }
        }
    }
 
    private static void Insert() {
        Scanner scanner= new Scanner(System.in);
        System.out.println("이름 : ");
        String name= scanner.nextLine();
        System.out.println("비번 : ");
        String password= scanner.nextLine();
        System.out.println("메모 : ");
        String memo= scanner.nextLine();
        
        MemoVO vo=new MemoVO();
        vo.setName(name);
        vo.setPassword(password);
        vo.setMemo(memo);
        
        if(MemoDAO.insert(vo))
            System.out.println("저장완료!");
        else {
            System.out.println("저장실패!");
        }
        System.out.println("저장완료!!!");
    }
}
 
cs

-UI를 구현한 MemoProject class-

더보기

-Desciption-

30 : update() 메소드는 사용자로 부터 받은 idx에 따른 MemoDAO.update(idx)을 수행

42 : delete() 메소드는 사용자로 부터 받은 idx 에 따른 MemoDAO.delete(idx) 을 수행

56 : select() 메소드는 MemoDAO.select()를 호출하여 결과를 ArrayList<MemoVO> 객체에 저장후, 내용출력

68 : Insert() 메소드는 사용자로부터 name,password,memo 를 입력받고 , MemoVO객체로 가공후,

MemoDAO.insert(vo)를 수행.

-MemoVO-

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
package DbTest;
 
import java.util.Date;
 
//VO(Value Object): 게시글 한 건을 기억할 클래스
// 게시글 한 건을 기억할 클래스
public class MemoVO {
    private int idx;
    private String name;
    private String password;
    private String memo;
    private Date writeDate;
    
 
    public int getIdx() {
        return idx;
    }
 
    public void setIdx(int idx) {
        this.idx = idx;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public String getPassword() {
        return password;
    }
 
    public void setPassword(String password) {
        this.password = password;
    }
 
    public String getMemo() {
        return memo;
    }
 
    public void setMemo(String memo) {
        this.memo = memo;
    }
 
    public Date getWriteDate() {
        return writeDate;
    }
 
    public void setWriteDate(Date writeDate) {
        this.writeDate = writeDate;
    }
 
    @Override
    public String toString() {
        return "MemoVO [idx=" + idx + ", name=" + name + ", password=" + password + ", memo=" + memo + ", writeDate="
                + writeDate + "]";
    }
}
 
cs

-데이터만을 처리하는 MemoVO class-

더보기

-Description-

8~10 : idx, name,password,memo, writeDate  인스턴스 변수들 선언
기타 : data input out 을 위한 set,get 함수 구현

-MemoDAO-

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
package DbTest;
 
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Scanner;
 
import com.koreait.interfaceTest.interfaceTest;
 
//DAO(Data Access Object) : db에 접속해서  sql 명령을 실행하는 메소들만 모아 놓은 클래스 
public class MemoDAO {
    public static boolean insert(MemoVO vo) {
        boolean result = true;
 
        Connection conn= null;
        PreparedStatement pstmt=null;
        
        try {
            conn= DbUtil.getMySQLConnection();
            //SQL
            String sql= "insert into memo (name,password,memo) values (?,?,?)";
            pstmt = conn.prepareStatement(sql);
            pstmt.setString(1, vo.getName());
            pstmt.setString(2, vo.getPassword());
            pstmt.setString(3, vo.getMemo());
            pstmt.executeUpdate();
        } catch (SQLException e) {
            System.out.println("옳바른 sql 명령이 실행되지 않았다.");
            result=false;
        } finally {
        DbUtil.close(conn);
        DbUtil.close(pstmt);
        }
        return result;
    }
    
    public static ArrayList<MemoVO> select(){
        Connection conn=null;
        PreparedStatement pstmt=null;
        ResultSet rs = null;
        ArrayList<MemoVO> list= null;
        
        try {
            conn = DbUtil.getMySQLConnection();
            String sql="SELECT * FROM memo ORDER BY idx DESC";
            pstmt = conn.prepareStatement(sql);
            rs = pstmt.executeQuery();
            list=new ArrayList<MemoVO>();
            
            while(rs.next()) {    //ResultSet객체에 저장된 데이터가 있는 동안 반복한다.
                MemoVO vo = new MemoVO();
                vo.setIdx(rs.getInt("idx"));
                vo.setName(rs.getString("name"));
                vo.setPassword(rs.getString("password"));
                vo.setMemo(rs.getString("memo"));
                vo.setWriteDate(rs.getTimestamp("writeDate"));//getTimestamp 는 날짜,시간 다꺼내옴 , getTime은 시간만 꺼내옴, getDate는 날짜만 꺼내옴
                list.add(vo);
            }
            
        } catch (SQLException e) {
            System.out.println("옳바른 sql 명령이 실행되지 않았다.");
        } finally {
            DbUtil.close(conn);
            DbUtil.close(pstmt);
            DbUtil.close(rs);
        }
        
        return list;
    }
    
    public static boolean delete(int idx) {
        boolean result= true;
        Connection conn = null;
        PreparedStatement pstmt=null;
        ResultSet rs=null;
        
        try {
            conn= DbUtil.getMySQLConnection();
            String sql="Select * From memo where idx=?";
            pstmt=conn.prepareStatement(sql);
            pstmt.setInt(1, idx);
            rs=pstmt.executeQuery();
            
            if(rs.next()) {
                MemoVO vo = new MemoVO();
                vo.setIdx(rs.getInt("idx"));
                vo.setName(rs.getString("name"));
                vo.setPassword(rs.getString("password"));
                vo.setMemo(rs.getString("memo"));
                vo.setWriteDate(rs.getTimestamp("writeDate"));
                System.out.println("삭제할 글 확인하기");
                System.out.println(vo);
                
                System.out.println("해당 게시글 비밀번호를 입력하세요.");
                String password=new Scanner(System.in).nextLine().trim();
                
                //삭제할 글의 비밀번호와 삭제하기 위해 입력한 비밀번호를 비교
                if(vo.getPassword().equals(password))  {
                    sql="delete from memo where idx=?";//delete 와 from 사이에 * 넣으면 인식못함
                    pstmt=conn.prepareStatement(sql);
                    pstmt.setInt(1, idx);
                    pstmt.executeUpdate();
                }
                else {
                    return false;
                }
            }else {
                System.out.println("삭제할 글이 테이블에 존재하지 않습니다");
                DbUtil.close(conn);
                DbUtil.close(pstmt);
                DbUtil.close(rs);
                return false;
            }
        } catch (SQLException e) {
            System.out.println("옳바른 sql 명령이 실행되지 않았다.");
        } finally {
            DbUtil.close(conn);
            DbUtil.close(pstmt);
            DbUtil.close(rs);
        }
        return true;
    }
 
    public static boolean update(int idx) {
        Connection conn = null;
        PreparedStatement pstmt=null;
        ResultSet rs=null;
        
        try {
            conn= DbUtil.getMySQLConnection();
            String sql="Select * From memo where idx=?";
            pstmt=conn.prepareStatement(sql);
            pstmt.setInt(1, idx);
            rs=pstmt.executeQuery();
            
            if(rs.next()) {
                MemoVO vo = new MemoVO();
                vo.setIdx(rs.getInt("idx"));
                vo.setName(rs.getString("name"));
                vo.setPassword(rs.getString("password"));
                vo.setMemo(rs.getString("memo"));
                vo.setWriteDate(rs.getTimestamp("writeDate"));
                System.out.println("수정할 글 확인하기");
                System.out.println(vo);
                
                System.out.println("해당 게시글 비밀번호를 입력하세요.");
                String password=new Scanner(System.in).nextLine().trim();
                
                if(vo.getPassword().equals(password))  {
                    System.out.print("수정할 메모를 입력해주세요 : ");
                    String memo=new Scanner(System.in).nextLine().trim();
                    sql="update memo set memo=? where idx=?"
                    pstmt=conn.prepareStatement(sql);
                    pstmt.setString(1, memo);
                    pstmt.setInt(2, vo.getIdx());
                    pstmt.executeUpdate();
                }
                else {
                    return false;
                }
            }else {
                System.out.println("수정할 글이 테이블에 존재하지 않습니다");
                DbUtil.close(conn);
                DbUtil.close(pstmt);
                DbUtil.close(rs);
                return false;
            }
        } catch (SQLException e) {
            System.out.println("옳바른 sql 명령이 실행되지 않았다.");
        } finally {
            DbUtil.close(conn);
            DbUtil.close(pstmt);
            DbUtil.close(rs);
        }
        return true;
    }
}
 
cs

- sql명령어를 처리하는 MemoDAO class-

-Description-

 14~37 : insert메소드
       21 : conn= DbUtil.getMySQLConnection() 을 통해 db 연결
 23~27  : sql명령어를 작성후 , setString을 이용해서 ? 채우기 

       28 : pstmt.executeUpdate() 을 통해 sql 명령 수행. 
  33~34 : Connection , PreparedStatement 등, sql 관련 객체변수를 닫아줌

  39~71 : select메소드
   42,49 : ResultSet 객체 변수를 선언 . 해당객체변수는 pstmt.executeQuery() 결과를 받음
( pstmt.executeUpdate()는 sql-table에 변동이 생길때 사용,
 pstmt.executeQuery()는 단순 table 변동없이 값을 읽어들일때 사용)

 73~124 : delete메소드

126~179 : update메소드

 

-요약-

JAVA와 SQL의 연동을 위해서,  자바 코드내 드라이버관련 코드를 작성할 필요가 있음

JAVA코드내 SQL명령어로는 PreparedStatement pstmt=conn.prepareStatement(sql)와 같은예비준비단계를 거치게됨

SQL관련 자바 객체를 생성했으면 , 닫아줘야함(의무는 아님)

 

-마침글-

Back 단에서 java를 이용해 미니게시판느낌의 메모를 구현해 보았다.

 

'21년이전 > 국비-JAVA+SQL' 카테고리의 다른 글

mini chat program  (0) 2021.02.25
728x90

-CRUD ( CREATE , READ , UPDATE , DELETE) -

 

 

-CREATE-

 

1
2
3
4
5
6
7
8
#주석입니다
#삽입
#INSERT INTO 테이블이름(필드이름,...) VALUES (데이터, ...);
#문자데이터는 작은따옴표로 묶어줌
INSERT INTO memo(NAME,PASSWORD,memo) VALUES ('홍길동','1111','1등 입니다.');
INSERT INTO memo(NAME,PASSWORD,memo) VALUES ('임꺽정','2222','2등 입니다.');
INSERT INTO memo(NAME,PASSWORD,memo) VALUES ('장길산','3333','3등 입니다.');
INSERT INTO memo(NAME,PASSWORD,memo) VALUES ('일지매','4444','4등 입니다.');
cs
 

 

-READ-

 

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
#검색
#SELECT [DISTINCT] 필드이름 또는 * FROM 테이블이름;
SELECT NAME FROM memo;
SELECT DISTINCT NAME FROM memo; #DISTINCT 는 중복되는 데이터를 한번만 출력함 
#SELECT * FROM 테이블이름 ORDER BY 필드이름 [ASC/DESC]; 
ORDER BY => 지정된 필드를 기준으로 정렬함. ASC가 디폴트
SELECT * FROM memo ORDER BY NAME ASC;
SELECT * FROM memo ORDER BY idx DESC; #최신글부터 얻어옴 
#이름으로 오름  , 이름이 동일시  IDX내림
SELECT * FROM memo ORDER BY NAME ASC, idx DESC;
#SELECT * FROM 테이블이름 WHERE 조건식;
SELECT * FROM memo WHERE idx = 20 ;
SELECT * FROM memo WHERE NAME = '홍길동' ;
SELECT * FROM memo WHERE NAME = '홍길동' || NAME = '장길산' ;
SELECT * FROM memo WHERE NAME = '임꺽정' OR NAME = '일지매' ;
SELECT * FROM memo WHERE NAME IN ('홍길동','임꺽정','일지매'); #장길산 빼고다 나옴 
SELECT * FROM memo WHERE NAME NOT IN ('홍길동','임꺽정','일지매'); #장길산만 나옴
 
SELECT * FROM memo WHERE idx>5 && idx<=10;
SELECT * FROM memo WHERE idx BETWEEN 25 AND 30;   # 25<=x<=30 
#부분일치 조건
#와일드카드(대체) 문자.   '%','_',LIKE 연산자를 사용해서 부분일치 조건을 지정할 수 있다.
#'_'는 1문자를 대체할 수 있고 '%'는 여러문자를 대체할 수 있다.
#'역삼_동' => 역삼1동,역삼2동,역삼3동,... 처럼 '_' 자리에는 어떤 문자가 나와도 상관없다는 의미.
#'홍%' =>  홍으로 시작하는 모든 문자열
#'%홍' => 홍으로 끝나는 모든 문자열
#'%홍%' => 홍을 포함하는 모든 문자열
SELECT * FROM memo WHERE NAME LIKE '홍%';#홍길동
SELECT * FROM memo WHERE NAME LIKE '%공';#손오공
SELECT * FROM memo WHERE NAME LIKE '%길%';#검색기능 구현에 많이 사용
#LIMIT를 사용해서 특정 index부터 원하는 개수를 지정해 얻어올 수 있다.
#LIMIT 시작인덱스, 개수
#MYSQL 에서 인덱스는 , SELECT 가 실행됬을때 처음부터 0으로 시작됨, 인위적인 인덱스랑 다름
SELECT * FROM memo ORDER BY idx DESC LIMIT 0,10;#0번째 인덱스부터 10개를 가져옴.
SELECT * FROM memo ORDER BY idx ASC LIMIT 0,10;
#그룹 함수 : SUM(합계) ,AVG(평균) , MAX(최댓값), MIN(최솟값), COUNT(갯수)
SELECT SUM(idx) FROM memo WHERE idx<=10;#idx 1부터 10까지 쭉더해서 55가나옴
SELECT AVG(idx) FROM memo WHERE idx<=10;
SELECT MAX(idx) FROM memo WHERE idx<=10
SELECT MIN(idx) FROM memo WHERE idx<=10
#개수는 어떤 필드의 갯수를 세더라도 같은 결과가 나오기 때문에 인수로 *를 사용한다.
SELECT COUNT(*FROM memo WHERE idx<=10; #테이블에 저장된 전체글의 갯수를 얻어올수 있다.
#SELECT 그룹함수(필드이름) FROM 테이블이름 WHERE 전체조건 GROUP BY  필드이름 HAVING 그룹조건
SELECT NAME,COUNT(*FROM memo GROUP BY NAME;#각 이름마다(중복없이) 갯수가 나옴.
SELECT NAME,COUNT(*FROM memo GROUP BY NAME HAVING NAME LIKE '%길%'
#그룹함수를 실행한 결과는 필드 이름이 없기 때문에 as로 볆명을 지정할수 있다.
SELECT NAME,COUNT(*) AS '인원수' FROM memo GROUP BY NAME HAVING NAME LIKE '%길%'
 
 
cs

-UPDATE-

 

1
2
3
4
5
6
7
#UPDATE 테이블이름 SET 수정할내용, ... WHERE 조건식;
#조건식을 생략하면 테이블 전체 데이터를 수정하기 때문에 반드시 조건을 지정해서 사용한다.
UPDATE memo SET PASSWORD ='9999';#대형사고
UPDATE memo SET PASSWORD ='1111' WHERE NAME='홍길동';
UPDATE memo SET PASSWORD ='2222' WHERE NAME='임꺽정';
UPDATE memo SET PASSWORD ='3333' WHERE NAME='장길산';
UPDATE memo SET PASSWORD ='4444' WHERE NAME='일지매';
cs

 

-DELETE-

 

1
2
3
4
5
6
7
8
9
#DELETE FROM 테이블이름 WHERE 조건식;
#조건식을 생략하면 테이블 전체 데이터를 삭제하기 때문에 반드시 조건을 지정해서 사용한다.
DELETE FROM memo;#대형사고
INSERT INTO memo(NAME,PASSWORD,memo) VALUES ('홍길동','1111','1등 입니다.');#idx가 다시 1로 시작안됨.
DELETE FROM memo WHERE NAME='홍길동';
#테이블데이터 전체제거후 ,자동증가속성이 있는 idx 를 초기화 시키는방법
DELETE FROM memo;#전체 제거후
ALTER TABLE memo AUTO_INCREMENT = 1;
INSERT INTO memo(NAME,PASSWORD,memo) VALUES ('홍길동','1111','1등 입니다.');#idx가 다시 1부터 시작됨
cs

 

-ALTER-

1
2
#bidx 컬럼에 AUTO_INCREMET 넣어주기
ALTER TABLE itboard MODIFY bidx INT NOT NULL AUTO_INCREMENT;
cs
1
2
3
4
5
6
7
# 레코드들이 이미 존재하는 상황에서 auto_increment 재정렬 시켜주기 (  인덱스를 다시 1부터 순차적으로 나오게함 )
# @이 들어가는건 변수 설정임
# := 은 대입연산자임 ( 기존의 = 는 대입인지 비교인지 애매할 수 있기 때문에 := 이라는 것을 만듬 )
# 속도효율은 확답할수 없다. 왜냐하면 기존의 모든 레코드들을 한번씩 거쳐서 update 해주는 것으로 보이기 때문이다.
ALTER TABLE testtable AUTO_INCREMENT=1;
SET @COUNT = 0;
UPDATE testtable SET idx = @COUNT:=@COUNT+1;
cs

'21년이전 > 국비-sql' 카테고리의 다른 글

프로그래머스 - JOIN 문제모음  (0) 2021.06.22
SQL - JOIN  (0) 2021.06.22
SQL - DDL  (0) 2021.05.12
DB - 개념모델링  (0) 2021.05.10
728x90
  • 1) 안드로이드스튜디오 와 php 인터페이스관리
  • 2) php와 mysql 인터페이스 관리

1) 안드로이드스튜디오와 php 인터페이스

 

그림 (1)  CheckActivity.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
public class CheckActivity extends AppCompatActivity {
    private EditText userid;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_check);
        userid=findViewById(R.id.userid);
        Intent intent = getIntent();
        final int number= intent.getIntExtra("number",1);
        final String userID = intent.getStringExtra("userid");
        final int date= intent.getIntExtra("date",1);
        Response.Listener<String> responseListener = new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
                try {
                    JSONObject jsonObject = new JSONObject(response);
                    boolean success = jsonObject.getBoolean("success");
                    if ( success) {  //성공
                        Toast.makeText(getApplicationContext(),"성공하였습니다.",Toast.LENGTH_SHORT).show();
                       
                        userid.setText(jsonObject.getString("userid"));   //서버로부터 가져오는것
                    }
                    else  // 실패
                    {
                        Toast.makeText(getApplicationContext(),"실패",Toast.LENGTH_SHORT).show();
                        return;
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        };
        //서버로 volley를 이용해서 요청 
        CheckRequest checkRequest = new CheckRequest(userID,date,number,responseListener);
        RequestQueue queue = Volley.newRequestQueue(CheckActivity.this);
        queue.add(checkRequest);
    }
}
 
cs

외부에서 받아온 데이터를 안드로이드스튜디오의 어떤 지점에서 이용하고 싶을때  12~36번째 줄을 해당 지점에 추가하면 된다 

 

16번째줄에 생성된 jsonObject 객체는 17,21번째 줄과 같이 외부데이터에 접근할때 이용된다.

 

34번째줄에서 객체 checkRequest를 생성함(CheckRequest class는 따로 만들어야함)   

CheckRequest 파라미터로 들어가는 값은 외부에 전달하는 데이터(신호)임 

 

35번째,36번째줄에서 Volley는 안드로이드 앱에서 HTTP 통신을 조금 더 쉽게 구현할수 있게 하는 API임 

RequestQueue: 서버 요청자. 다른 Request 클래스들의 정보대로 서버에 요청을 보내는 역할임

즉,기본적인 구조는 CheckRequest 와 같은 Request 클래스들을 이용하여 서버 요청 정보와 결과 처리 방법을 표현하고, 이 Request 객체를 RequestQueue에 넘겨 서버 요청이 발생하는 구조입니다.
안드로이드 프로그래밍에서 Volley 및 HTTP통신에 대해 더 자세히 알고 싶으면 깡샘님의 블로그를 참조.

 

 

그림 (2) CheckRequest.java 예제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class CheckRequest extends StringRequest {
 
    // 서버 URL 설정 ( PHP 파일 연동 )
    final static private String URL = "http://fkdlxkakstp.dothome.co.kr/Select_detail.php";
    private Map<String,String> map;
 
    public CheckRequest(String userid,int date,int number, Response.Listener<String> listener){
        super(Method.POST ,  URL, listener , null);
 
        map = new HashMap<>();
        map.put( "userid",userid);
        map.put( "date",date+"");
        map.put("number",number+"");
 
    }
 
    @Override
    protected Map<StringString> getParams() throws AuthFailureError {
        return map;
    }
}
 
cs

다시한번 말하지만 ,

기본적인 구조는 CheckRequest 와 같은 Request 클래스들을 이용하여 서버 요청 정보와 결과 처리 방법을 표현하고, 이 Request 객체를 RequestQueue에 넘겨 서버 요청이 발생하는 구조입니다.

 

참고로, 1번째 줄에서 StringRequest 를 상속 받는데 StringRequest는 서버로부터 문자열 데이터를 얻을 목적으로 사용하는 클래스다.

 

4번째 줄의 URL에 들어간 값은 내가 웹 호스팅업체로부터 할당받은 공간에 Select_detail.php라는 내가 미리짜논 php파일을 넣어 둔 것임

 

5번째, 10번쨰 줄은 해쉬맵을 선언 해 준것이고  < 키(key) , 값(value) > 를 <String,String> 으로 정하였다.

 

7번째 줄은 생성자이며 , 생성자의 파라미터는 그림(1)의 34번째 줄 설명에서 이미 말하였다.  외부에 보내줄 데이터이다.

 

8번째 줄은 부모클래스의 생성자를 호출한다.

StringRequest 파라미터에 대한 자세한 설명

더보기

객체를 생성하면서 생성자 매개변수로 서버 요청 정보와 결과 처리 콜백을 등록합니다.

첫 번째 매개변수는 HTTP Method로서 GET이나 POST로 지정되고, 두 번째 매개변수는 서버 URL 정보입니다. 세 번째 매개변수가 결과 콜백이며, 네 번째 매개변수가 에러 콜백입니다. 서버로부터 수신된 문자열 데이터를 전달할 목적으로 세 번째 매개변수로 지정된 콜백의

onResponse( ) 함수가 자동으로 호출되며, 이 함수의 매개변수로 서버 수신 문자열이 전달됩니다.

출처: https://kkangsnote.tistory.com/45 [깡샘의 토마토]

 

 

10~13번째 줄은 php파일에서 데이터를 인식하기 위해 만드는 설정이다.

 

18,19번째 줄에서 getParams를 재정의하고 서버에 전송할 데이터를 Map객체에 담아 반환하는 형태이다. (조금 모호하긴 함)

728x90

이 게시글들은 동영상으로 구성되어 있습니다.  동영상내용을 따라해주시면 감사하겠습니다.

 

1) 컴퓨터에 하드디스크를 추가하는 방법부터 알아보겠습니다.

 

 

GMHDDSCANv20p2.exe
다운로드

+ Recent posts