DAO (Data Access Object) :  데이터 접근 객체 

- sql문을 사용하여 DataBase와 연동 할 때 마다 갹체를 지정해줘야하는 것은 불편한 과정입니다. 이러한 불편하고 비효율적인 과정을 줄이기 위해서 고안한 방법이 DAO 입니다. DAO는 DB의 데이터를 다루기 위해 만들어진 객체입니다.

 

장점

- DataBase에서 효율적으로 쿼리를 받아드릴 수 있습니다.

- DBMS를 변동하거나 수정사항이 있을 때, 소스를 통째로 고쳐야 한다면 번거로울 수 있습니다. 따라서 유지보수를 편하게 하기 위해 사용하도록 해줍니다.

- DataSoure에 정보의 저장, 변경, 삭제, 검색 기능을 제공하기 위한 메소드가 선언이 가능합니다.

public class DAO {
	//BasicDataSource ds;
	
    private static final String DRIVER = "oracle.jdbc.driver.OracleDriver";
    private static final String URL= "jdbc:oracle:thin:@localhost:1521:xe";
    private static final String USER = "scott"; //DB ID  
    private static final String PASS = "tiger"; //DB 패스워드
    
    public  DAO() {

    	try {
			Class.forName(DRIVER);
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    }
      public void insert(DTO_Member dto) {
	
		Connection conn = null;
		PreparedStatement pstmt = null;
		
		try {
			//conn = ds.getConnection();
			conn = DriverManager.getConnection(URL,USER, PASS);
			String sql = "insert into member values(?, ?, ?, ?)";
			pstmt = conn.prepareStatement(sql);
			pstmt.setString(1, dto.getName());
			pstmt.setString(2,dto.getTel());
			pstmt.setString(3,dto.getId());
			pstmt.setString(4,dto.getPw());
			
			int result = pstmt.executeUpdate();
			
			if(result == 1) {
				System.out.println("회원가입 되었습니다.");
			}else {
				System.out.println("회원가입 실패하였습니다. \n 다시 입력해주세요.");
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}finally {
			try {
				if(pstmt != null) { pstmt.close(); }
				if(conn != null) { conn.close(); }
			} catch (SQLException e) {
				System.out.println(e.getMessage());
			}
		}
	}

1) DataBase와 연결을 해줍니다.

2) sql문을 이용하여 정의를 한 다음 값을 불러올 때 DTO의 정의 되어있는 getter, setter method를 활용하여 결과를 가져 옵니다.

 

 

DTO (Data Transfer Object) : 데치터 전송 객체 

- DAO를 통해서 DataBase에 접근할 때 데이터가 오고가고 할 때 DTO가 매개체 역할을 합니다. DTO는 getter 와 setter method를 통해서 접근할 수 있도록 합니다.

- DTO는 set method를 통해서 값을 값을 전달 받고 get method를 통해서 값을 가져오도록 합니다.

 

class DTO_Member {
	
	private String name;
	private String tel;
	private String id;
	private String pw;

	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getTel() {
		return tel;
	}
	public void setTel(String tel) {
		this.tel = tel;
	}
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getPw() {
		return pw;
	}
	public void setPw(String pw) {
		this.pw = pw;
	}
	
	//DTO 객체 확인
	@Override
	public String toString() {
		 return "InFoDTO [name=" + name + ", tel=" + tel + ", id=" + id
	                + ", pw="  + pw + "]";
	}
}

getter, setter 메소드만 가진 클래스로 되어있습니다.

 

 

 

 

 

'빅데이터 > JAVA' 카테고리의 다른 글

[JAVA] JAVA&DATABASE 연결  (0) 2020.05.27
[JAVA] 이클립스, DB 연동 환경설정  (0) 2020.05.26
[JAVA] SWING (2)  (0) 2020.05.25
[JAVA] SWING(1)  (0) 2020.05.23
[JAVA] 네트워크(NETWORK)  (0) 2020.05.23

프로젝트에서 오른쪽 버튼 클릭하여 Built Path -> Add External Archives 선택합니다.

jar파일을 선택합니다.

jar 파일을 선택하면 Referenced Libraries에 생깁니다.

JDBC 드라이버 로딩과 Connection 생성

1.JDBC 드라이버 로딩

  • MySQL의 JDBC Driver Class를 로딩합니다.
  • Class.forName(“driver”)을 이용해서 Driver Class를 로딩하면 객체가 생성되고, DriverManager에 등록됩니다.
  • ex) Class.forName(“com.mysql.jdbc.Driver”)
  • Driver 클래스를 찾지 못할 경우, ClassNotFoundException 예외가 발생 합니다.

2. Connection 생성

  • Connection - 데이터베이스와 연결하는 객체입니다.
  • DriverManager.getConnection(연결문자열, DB_ID, DB_PW) 으로 Connection 객체를 생성합니다.
  • 연결문자열(Connection String) - “jdbc:Driver 종류://IP:포트번호/DB명”
  • ex) jdbc:mysql://localhost:3306/test_db
  • DB_ID : MySQL 아이디
  • DB_PW : MySQL 비밀번호

2.1 DriverManager 클래스

  • DriverManager 클래스는 JDBC 드라이버를 통하여 Connection을 만드는 역할을 합니다.
  • DriverManager는 Class.forName( ) 메소드를 통해서 생성됩니다.
package Eclipse_Db;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class JDBC_Connect {
	public static void main(String[] args) {
		String driver = "oracle.jdbc.driver.OracleDriver";
		String url = "jdbc:oracle:thin:@localhost:1521:xe";
		Connection conn= null;
		
		try {
			Class.forName(driver); // java 7 이후 생략 가능.
			conn = DriverManager.getConnection(url, "scott", "tiger");
			
			System.out.println("데이터베이스 연결  성공~~~");
		} catch (ClassNotFoundException | SQLException e) {
			// e.printStackTrace();
			System.out.println("데이터베이스 연결  실패 ㅠㅠㅠ");
		}finally {
				try {
					if(conn != null) { conn.close(); }
				} catch (SQLException e) {
					System.out.println(e.getMessage());
				}
		}
	}
}

위의 코드를 통해서 DB와 연결이 되었다면 본격적으로 이클립스를 통해서 DB에 데이터를 출력, 저장, 수정, 저장을 해보겠습니다.

위의 데이터를 출력, 저장, 수정, 저장을 위해서는 가장 먼저 해야하는 것은 DataBase에 class만들어서 각각의 특징에 맞는 자료형을 선언해 주는 것입니다.

 

 

 

1) 저장(insert)

public class JDBC_Insert {
	public static void main(String[] args) {
		String driver = "oracle.jdbc.driver.OracleDriver";
		String url = "jdbc:oracle:thin:@localhost:1521:xe";
		Connection conn= null;
		Statement stmt = null;
		
		try {
			Class.forName(driver); // java 7 이후 생략 가능.
			conn = DriverManager.getConnection(url, "scott", "tiger");
			
			// System.out.println("데이터베이스 연결  성공~~~");
			
			Scanner input = new Scanner(System.in);
			
			System.out.println("customer 테이블에 값 입력하기...");
			System.out.print("번호 입력 : ");
			int no = input.nextInt();
			
			input.nextLine(); // dummy
			
			System.out.print("이름 입력 : ");
			String name = input.nextLine();
			
			System.out.print("이메일 입력 : ");
			String email = input.nextLine();
			
			System.out.print("전화번호 입력 : ");
			String tel = input.nextLine();
			
			stmt = conn.createStatement();
			
			// insert 쿼리문에 작성.
			String sql = "insert into customer "
					+ "values ("+no+", '"+name+"', '"+email+"', '"+tel+"')";
			
			int result = stmt.executeUpdate(sql);
			
			if(result == 1) {
				System.out.println("데이터 저장 성공");
			}else {
				System.out.println("데이터 저장 실패");
			}
			
		} catch (ClassNotFoundException | SQLException e) {
			// e.printStackTrace();
			System.out.println("데이터베이스 연결  실패 ㅠㅠㅠ");
		}finally {
				try {
					if(stmt != null) { stmt.close(); }
					if(conn != null) { conn.close(); }
				} catch (SQLException e) {
					System.out.println(e.getMessage());
				}
		}
	}
}

순서

1) database와 연결합니다.

2) scanner를 이용하여 필요한 값을 입력합니다.

3) 입력한 값을 sql문에 넣어서 명령할 것을 정의 하고 int result = stmt.executeUpdate(sql); 를 통해서 DB에 명령해줍니다

4) 저장이 되었으면 "데이터 저장 성공" 저장 되지 않으면 "데이터 저장 실패"가 출력되게 합니다. 

5) 항상 마지막은 컴퓨터의 퍼포먼스를 위해서 사용했던 것들을 finally 에 넣어서 다 꺼주도록 합니다.

 

-sacnner 에 int 값을 입력한 다음 String이 오는 경우에는 항상 더미 코드를 입력하도록 합니다!!

 

 

 

2) 출력(select)

public class JDBC_Select {
	public static void main(String[] args) {
		String driver = "oracle.jdbc.driver.OracleDriver";
		String url = "jdbc:oracle:thin:@localhost:1521:xe";
		Connection conn= null;
		Statement stmt = null;
		ResultSet rs = null;
		int no = 0;
		String name = null, email = null, tel = null;
		
		try {
			Class.forName(driver); // java 7 이후 생략 가능.
			conn = DriverManager.getConnection(url, "scott", "tiger");
			
			//System.out.println("데이터베이스 연결  성공~~~");
			
			stmt = conn.createStatement();
			String sql = "select * from customer";
			
			rs = stmt.executeQuery(sql);
			
			System.out.println("번호\t이름\t\t이메일\t\t전화번호");
			System.out.println("-----------------------------------------------");
			
			while(rs.next()) {
				no = rs.getInt("no");
				name = rs.getString("name");
				email = rs.getString("email");
				tel = rs.getString("tel");
				
				System.out.printf("%d\t%s\t%s\t%s\n", 
						                                      no, name, email, tel);
			}
			
		} catch (ClassNotFoundException | SQLException e) {
			// e.printStackTrace();
			System.out.println("데이터베이스 연결  실패 ㅠㅠㅠ");
		}finally {
				try {
					if(rs != null ) { rs.close(); }
					if(stmt != null) { stmt.close(); }
					if(conn != null) { conn.close(); }
				} catch (SQLException e) {
					System.out.println(e.getMessage());
				}
		}
	}
}

순서

1) database와 연결합니다.

2) sql = "select * from customer"; 를 사용하여 만들어둔 class에 저장되어 있는 값을 가져오도록 합니다.

3) sql문을 통해서 필요한 내용을 정의하고 rs = stmt.executeQuery(sql); 를 통해서 DB에 명령해줍니다.

4) while문을 활용하여 출력되는 값을 변수를 선언하여 변수 안에 넣어줘서 그 값을 출력하게 만듭니다.

5) 저장이 되었으면 "데이터 저장 성공" 저장 되지 않으면 "데이터 저장 실패"가 출력되게 합니다.

6) 항상 마지막은 컴퓨터의 퍼포먼스를 위해서 사용했던 것들을 finally 에 넣어서 다 꺼주도록 합니다.

 

- Resultset이란?

Java에서 사용하는 것은 일단 DB 연결되는 통로를 열고, 통로로 명령을 보내고, 통로로 보낸 명령에 대해서 DB 처리해서 값을 돌려보내주는 식으로 처리 됩니다. execteQuery 명령하면 ResultSet이라는 객체를 돌려줍니다.

 

execteQuery : DB 명령 ( rs = stmt.executeQuery(sql); )

ResultSet : 명령에 대한 반환값. 반환해주는 값은 테이블을 보시면서 해야 이해하시는 것이 좋을것 같습니다.

 

execteQuery("Select * from tableName"); 이라고 보냈다면 tableName 라는 테이블에서 값을 가져올겁니다. 가져온 것이 ResultSet입니다. 간단히 DB 명령을 내리는 것입니다. 그러면 명령에 따라서 디비가 작동하고, 작동한 결과 값을 돌려준다는 말입니다.

 

 

 

3) 수정(Update)

ublic class JDBC_Update {
	public static void main(String[] args) {
		String driver = "oracle.jdbc.driver.OracleDriver";
		String url = "jdbc:oracle:thin:@localhost:1521:xe";
		Connection conn= null;
		Statement stmt = null;
		
		try {
			Class.forName(driver); // java 7 이후 생략 가능.
			conn = DriverManager.getConnection(url, "scott", "tiger");
			
			// System.out.println("데이터베이스 연결  성공~~~");
			
			Scanner input = new Scanner(System.in);
			
			System.out.println("customer 테이블에 값 수정하기...");
			System.out.print("수정할 번호 입력 : ");
			int no = input.nextInt();
			
			input.nextLine(); // dummy
			
			System.out.print("변경할 이름 입력 : ");
			String name = input.nextLine();
			
			System.out.print("변경할 이메일 입력 : ");
			String email = input.nextLine();
			
			System.out.print("변경할 전화번호 입력 : ");
			String tel = input.nextLine();
			
			stmt = conn.createStatement();
			
			// update 쿼리문에 작성.
			String sql = "update customer set name = '"+name+
					                                      "', email = '"+email+
					                                      "', tel = '"+tel+
					                                      "' where no = "+no;
			
			int result = stmt.executeUpdate(sql);
			
			if(result == 1) {
				System.out.println("데이터 수정 성공");
			}else {
				System.out.println("데이터 수정 실패");
			}
			
		} catch (ClassNotFoundException | SQLException e) {
			// e.printStackTrace();
			System.out.println("데이터베이스 연결  실패 ㅠㅠㅠ");
		}finally {
				try {
					if(stmt != null) { stmt.close(); }
					if(conn != null) { conn.close(); }
				} catch (SQLException e) {
					System.out.println(e.getMessage());
				}
		}
	}
}

순서)

1) database를 연결합니다.

2) Scanner을 통해서 변경할 값을 입력 합니다.

3) 수정을 위해서 sql문에 where을 사용해서 조건을 달아줍니다. 저는 no의 값을 입력해서 수정할것이기 때문에

where = no 라고 입력해주었습니다.

4) executeUpdate를 사용하여 DB에게 명령해줍니다.

5) 저장이 되면 "데이터 수정 성공 " 저장되지 않으면 "데이터 수정 실패" 가 입력하도록 합니다.

6) 항상 마지막은 컴퓨터의 퍼포먼스를 위햐서 finally에서 다 종료시켜줍니다.

 

 

 

4)삭제(delete)

public class JDBC_Delete {
	public static void main(String[] args) {
		String driver = "oracle.jdbc.driver.OracleDriver";
		String url = "jdbc:oracle:thin:@localhost:1521:xe";
		Connection conn= null;
		Statement stmt = null;
		
		try {
			Class.forName(driver); // java 7 이후 생략 가능.
			conn = DriverManager.getConnection(url, "scott", "tiger");
			
			//System.out.println("데이터베이스 연결  성공~~~");
			
			Scanner input = new Scanner(System.in);
			
			System.out.println("customer 테이블에서 레코드 삭제하기...");
			System.out.print("삭제할 번호 입력 : ");
			int no = input.nextInt();
			
			stmt = conn.createStatement();
			
			String sql = "delete from customer where no = "+no;
			int result = stmt.executeUpdate(sql);
			
			if(result == 1) {
				System.out.println("데이터 삭제 성공");
			}else {
				System.out.println("데이터 삭제 실패");
			}
			
		} catch (ClassNotFoundException | SQLException e) {
			// e.printStackTrace();
			System.out.println("데이터베이스 연결  실패 ㅠㅠㅠ");
		}finally {
				try {
					if(stmt != null) { stmt.close(); }
					if(conn != null) { conn.close(); }
				} catch (SQLException e) {
					System.out.println(e.getMessage());
				}
		}
	}
}

위의 수정과 같은 방식으로 sql문에서 update를 delete로 고쳐주면 작동하게 됩니다.

 

 

위의 내용들에서 sql문에서 정보드를 숨기고 싶을 떄는 preapareStatement 를 사용하여 sql 따로 입력하도록 만들어줍니다.

String sql = "insert into customer values (?, ?, ?, ?)";
			pstmt = conn.prepareStatement(sql);
			pstmt.setInt(1, no);
			pstmt.setString(2, name);
			pstmt.setString(3, email);
			pstmt.setString(4, tel);

위와 같은 형태로 사용합니다.

ublic class JDBC_Update {
 public static void main(String[] args) {
  String driver = "oracle.jdbc.driver.OracleDriver";
  String url = "jdbc:oracle:thin:@localhost:1521:xe";
  Connection conn= null;
  Statement stmt = null;
  
  try {
   Class.forName(driver); // java 7 이후 생략 가능.
   conn = DriverManager.getConnection(url, "scott", "tiger");
   
   // System.out.println("데이터베이스 연결  성공~~~");
   
   Scanner input = new Scanner(System.in);
   
   System.out.println("customer 테이블에 값 수정하기...");
   System.out.print("수정할 번호 입력 : ");
   int no = input.nextInt();
   
   input.nextLine(); // dummy
   
   System.out.print("변경할 이름 입력 : ");
   String name = input.nextLine();
   
   System.out.print("변경할 이메일 입력 : ");
   String email = input.nextLine();
   
   System.out.print("변경할 전화번호 입력 : ");
   String tel = input.nextLine();
   
   stmt = conn.createStatement();
   
   // update 쿼리문에 작성.
   String sql = "update customer set name = '"+name+
                                           "', email = '"+email+
                                           "', tel = '"+tel+
                                           "' where no = "+no;
   
   int result = stmt.executeUpdate(sql);
   
   if(result == 1) {
    System.out.println("데이터 수정 성공");
   }else {
    System.out.println("데이터 수정 실패");
   }
   
  } catch (ClassNotFoundException | SQLException e) {
   // e.printStackTrace();
   System.out.println("데이터베이스 연결  실패 ㅠㅠㅠ");
  }finally {
    try {
     if(stmt != null) { stmt.close(); }
     if(conn != null) { conn.close(); }
    } catch (SQLException e) {
     System.out.println(e.getMessage());
    }
  }
 }

'빅데이터 > JAVA' 카테고리의 다른 글

[JAVA] JAVA&DATABASE - (DAO, DTO)  (0) 2020.06.06
[JAVA] 이클립스, DB 연동 환경설정  (0) 2020.05.26
[JAVA] SWING (2)  (0) 2020.05.25
[JAVA] SWING(1)  (0) 2020.05.23
[JAVA] 네트워크(NETWORK)  (0) 2020.05.23

DATABASE를 이클립스를 통해서 사용할 수 있도록 지원해줍니다. 환경설정을 해보도록 하겠습니다.

 

 

database connections 오른쪽 마우스를 눌러 new를 선택합니다.

 

 

여러가지 Database를 연결되어 있는데 사용하고 있는 것으로 선택하세요.  저는 오라클이 지원하는 Database 사용하기 때문에 오라클을 선택하고 Next >

Database 는 버전들도 중요합니다. 버전의 따라서 정보들이 다르기 때문에 세부적인 정보로 구체적인 세팅이 이루어져야 합니다.

 

new driver definition 을 눌러줍니다.

 

저는 oracle thin 11 버전을 사용하고 있어서 선택해줍니다.

 

jar파일을 찾아서 연결해줍니다.

내 컴퓨터를 사용할 때는 localhost로 변경해주고, 사용할 아이디, 비밀번호를 입력하신후 service name 도 확인해주세요. 그리고 매번 비밀번호를 입력하는건 번거롭기 때문에 비밀번호는 저장하도록 하면 좋습니다.

이렇게 ping succeeded! 와 함께 연결에 성공하였습니다.

 

항상 사용할 때는 위의 버전과 환경이 맞도록 선택을 하시고 connect 되도록 해야합니다.

이클립스가 꺼지면 DB와 연결이 끊어지기 때문에 이클립스를 키면 DBconnect 하는 것을 습관화하는 것이 좋습니다.

 

확인 완료!!

'빅데이터 > JAVA' 카테고리의 다른 글

[JAVA] JAVA&DATABASE - (DAO, DTO)  (0) 2020.06.06
[JAVA] JAVA&DATABASE 연결  (0) 2020.05.27
[JAVA] SWING (2)  (0) 2020.05.25
[JAVA] SWING(1)  (0) 2020.05.23
[JAVA] 네트워크(NETWORK)  (0) 2020.05.23

 

기초적인 스윙 컴포넌트와 상속 관계

 

 

스윙 컴포넌트의 공통 메소드, JComponent메소드

 

 

JLabel, 레이블 컴포넌트

: 문자열이나 이미지를 컴포넌트화 하여 출력하기 위한 목적으로 사용합니다.

 

단순 텍스트 만을 가진 레이블 컴포넌트 생성
JLabel textLabel = new JLabel("사랑합니다");

이미지를 가진 레이블 컴포넌트 생성
ImageIcon image = new ImageIcon("images/sunset.jpg");
JLabel imageLabel = new JLabel(image);

수평 정렬 값을 가진 레이블 컴포넌트 생성
ImageIcon image = new ImageIcon("images/sunset.jpg");
JLabel label = new JLabel("사랑합니다", image, SwingConstants.CENTER);

이미지 파일로부터 이미지를 읽기 위해 ImageIcon 클래스 사용합니다.

다룰 수 있는 이미지 : png, gif, jpg

sunset.jpg의 경로명이 "images/sunset.jpg" 경우

 

public class LabelEx extends JFrame {
	public LabelEx() {
		setTitle("레이블 예제");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		Container c = getContentPane();
		c.setLayout(new FlowLayout());

		JLabel textLabel = new JLabel("사랑합니다.");
		
		ImageIcon beauty = new ImageIcon("images/beauty.jpg"); 
		JLabel imageLabel = new JLabel(beauty);

		ImageIcon normalIcon = new ImageIcon("images/normalIcon.gif"); 
		JLabel label = new JLabel("보고싶으면 전화하세요",
					normalIcon, SwingConstants.CENTER);

		c.add(textLabel);
		c.add(imageLabel);
		c.add(label);

		setSize(400,600);
		setVisible(true);
	}
	public static void main(String [] args) {
		new LabelEx();
	}
}

 

 

 

JCheckBox

: 선택(selected)비선택(deselected)의 두 상태만 가지는 체크 버튼 입니다.

 

class JCheckBoxText extends JFrame {
	
	JTextField jtf ;
	
	JCheckBoxText(){ // 중복선택 가능 
		
		JCheckBox jcb1 = new JCheckBox("java");  
		JCheckBox jcb2 = new JCheckBox("r");
		JCheckBox jcb3 = new JCheckBox("python");
		JCheckBox jcb4 = new JCheckBox("db");
		
		jtf = new JTextField(10); 
		
		Container container = getContentPane();
		container.setLayout(new FlowLayout());
		
		container.add(jcb1);
		container.add(jcb2);
		container.add(jcb3);
		container.add(jcb4);
		container.add(jtf);
	-
		setTitle("JCheckjBox");
		setSize(500,100);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
	}
} 
public class JCheckBoxText_ {

	public static void main(String[] args) {
		new JCheckBoxText();
	}
}

 

출력값 :

 

 

JCheckBox에서 Item 이벤트 처리)

 

Item 이벤트

:체크 박스나 라디오버튼의 선택 상태가 바뀔 발생하는 이벤트 입니다.

- 마우스나 키보드로 체크박스를 선택 상태를 바꾸는 경우

- 프로그램에서 선택 상태를 바꾸는 경우

 

위의 코드 + ItemListener

class JCheckBoxText extends JFrame implements ItemListener{
	
	JTextField jtf ;
	
	JCheckBoxText(){
		
		JCheckBox jcb1 = new JCheckBox("java");  // 중복선택 가능 
		JCheckBox jcb2 = new JCheckBox("r");
		JCheckBox jcb3 = new JCheckBox("python");
		JCheckBox jcb4 = new JCheckBox("db");
		
		jtf = new JTextField(10); 
		
		Container container = getContentPane();
		container.setLayout(new FlowLayout());
		
		container.add(jcb1);
		container.add(jcb2);
		container.add(jcb3);
		container.add(jcb4);
		container.add(jtf);
		
		// 리스너 등록
		jcb1.addItemListener(this);
		jcb2.addItemListener(this);
		jcb3.addItemListener(this);
		jcb4.addItemListener(this);
		
		setTitle("JChecjBox 실습");
		setSize(500,100);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
	}
	@Override
	public void itemStateChanged(ItemEvent e) {
		// System.out.println("이벤트 발생");
		// 체크 박스를 선택하면 텍스트 상자에 선택한 내용이 표시된다. 
		
		JCheckBox selectCB = (JCheckBox)e.getItem();
		// 반환형이 object 이다 = 어떤 컴퍼넌트라도 처리 가능하다.
		// 반환형이 obhect 이므로  강제 형변형을 해준다.                                                                 
		
		jtf.setText(selectCB.getText());
		
		switch(selectCB.getText()){
		case "java":
			System.out.println("java해보자");
			break;
		case "r":
			System.out.println("r해보자");
			break;
		case "python":
			System.out.println("python해보자");
			break;
		case "db":
			System.out.println("db해보자");
			break;
		}
	}
} 
public class JCheckBoxText_ {
	public static void main(String[] args) {
		new JCheckBoxText();
	}
}

ActionListener 와 같은 방식으로 method를 overriding 하여 기능을 추가 합니다.

 

출력값:

 

 

● JRadioButton 

: 여러 버튼으로 그룹을 형성하고, 하나만 선택되는 버튼, 다른 버튼이 선택되면 이전에 선택된 버튼은 자동으로 해제됩니다.

 

 체크박스와의 차이점

- 체크 박스는 각 체크박스마다 선택/해제 가능 합니다.

- 라디오 버튼은 그룹에 속한 버튼 중 하나만 선택 상태가 됩나다.

- 이미지를 가진 라디오버튼의 생성 및 다루기는 체크박스와 완전히 동일합니다.

 

버튼 그룹 객체 생성
ButtonGroup group = new ButtonGroup();

라디오버튼 컴포넌트 생성
JRadioButton apple= new JRadioButton("사과");
JRadioButton pear= new JRadioButton("배");
JRadioButton cherry= new JRadioButton("체리");

라디오 버튼을 버튼 그룹에 삽입
group.add(apple);
group.add(pear);
group.add(cherry);

라디오 버튼을 컨테이너에 삽입
container.add(apple);
container.add(pear);
container.add(cherry);

 

예시)

class JRadioButtonTest extends JFrame implements ActionListener{
	
	
	JTextField jtf;
	JRadioButtonTest(){

		// 버튼 그룹 객체를 생성하여 그룹화할 컴포넌트 추가 (하나만 선택된다)
		ButtonGroup bg = new ButtonGroup(); // 버튼을 그룹화 
		JRadioButton jrb1 = new  JRadioButton("승마");
		JRadioButton jrb2 = new  JRadioButton("골프");
		JRadioButton jrb3 = new  JRadioButton("스쿠버");
		JRadioButton jrb4 = new  JRadioButton("글라이딩");
	    jtf = new JTextField(10);
		
		// JRadioButton은 그룹화 하여 하나만 선택되게 한다. 
		bg.add(jrb1); bg.add(jrb2); bg.add(jrb3); bg.add(jrb4);

		Container container = getContentPane();
		container.setLayout(new FlowLayout());
		
		container.add(jrb1);
		container.add(jrb2);
		container.add(jrb3);
		container.add(jrb4);
		container.add(jtf);
		
		jrb1.addActionListener(this);
		jrb2.addActionListener(this);
		jrb3.addActionListener(this);
		jrb4.addActionListener(this);
	
		setTitle("JRadioButton 실습");
		setSize(350,100);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
	}
	@Override
	public void actionPerformed(ActionEvent e) {
		jtf.setText(e.getActionCommand());
	}
}
public class JRadioButton_ {
	public static void main(String[] args) {	
		new JRadioButtonTest();
	}
}

 

결과값:

 

 

JTextField

: 한 줄 짜리 텍스트(문자열) 입력 창을 구현한 컴포넌트 입니다.

- 텍스트 입력 도중 키가 입력되면 Action 이벤트 발생합니다.

- 입력 가능한 문자 개수와 입력 창의 크기는 서로 다릅니다.

 

public class TextFieldEx extends JFrame {
	public TextFieldEx() {
		setTitle("텍스트필드 만들기 예제");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		Container c = getContentPane();
		c.setLayout(new FlowLayout());
		
		c.add(new JLabel("이름 "));
		c.add(new JTextField(20));
		c.add(new JLabel("학과 "));
		c.add(new JTextField("컴퓨터공학과 ", 20));
		c.add(new JLabel("주소 "));
		c.add(new JTextField("서울시 ...", 20));

		setSize(300,150);
		setVisible(true);
	}
	public static void main(String [] args) {
		new TextFieldEx();
	}
}

출력값:

 

 

JTextField 주요 메소드

- 문자열 편집 불가능하게 하기 : JTextField.setEditable(false);

- 입력 창에 문자열 출력 : JTextField.setText("hello");

- 문자열의 폰트 지정 : JTextField.setFont(new Font("고딕체", Font.ITALIC, 20);

 

TextArea

: 여러 줄을 입력할 수 있는 텍스트 입력 창입니다.

- JScrollPane 컴포넌트에 삽입하면 스크롤바 지원됩니다.

class JTextFieldTextArea extends JFrame{
	
	JTextField jtf;
	JTextArea jta;
	
	JTextFieldTextArea(){
		jtf = new JTextField(10); 
		jta = new JTextArea(7,20); 
		
		Container container = getContentPane();
		container.setLayout(new FlowLayout());
		
		container.add(jtf);
		container.add(jta);

		setTitle("텍스트 필드 & 텍스트 Area 실습");
		setSize(500,200);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
	}
}
public class JTextFieldTextArea_ {
	public static void main(String[] args) {
		new JTextFieldTextArea();
	}
}

jtf = new JTextField(10);  크기가 10인 텍스트 필드 객체 생성(10글자가 들어갈 수 있는 크기) ,  한 라인의 입력을 받을 수 있는 컨퍼넌트입니다. 숫자가 입력되기 전에는 아주 작게 보여줍니다.


jta = new JTextArea(7,20); // (7,20) 7행 20열의 텍스트에어리어 생성 , 화면상 7줄이 보입니다.

아쉬운점 : enter를 누르지 않으면 다음 줄로 넘어가지 않습니다.

 

출력값:

 

 

● JComboBox 

: 풀다운 형태의 리스트 컴포넌트를 만들어주는 클래스 입니다.

- 항목(list)를 선택하는 이벤트 처리 ItemListener를 이용 

- 텍스트 필드와 버튼, 그리고 드롭다운 리스트로 구성

 

 

public class ComboBoxEx extends JFrame {
	private String [] fruits = {"apple", "banana", "kiwi", "mango", "pear",
								"peach", "berry", "strawberry", "blackberry"};
	private String [] names = {"kitae", "jaemoon", "hyosoo", "namyun"};
	public ComboBoxEx() {
		setTitle("콤보박스 만들기 예제");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		Container c = getContentPane();
		c.setLayout(new FlowLayout());

		JComboBox<String> strCombo = new JComboBox<String>(fruits);
		c.add(strCombo);

		JComboBox<String> nameCombo = new JComboBox<String>();
		for(int i=0; i<names.length; i++)
			nameCombo.addItem(names[i]);
			c.add(nameCombo);

		setSize(300,300);
		setVisible(true);
	}
	public static void main(String [] args) {
		new ComboBoxEx();
	}
}

출력값:

 

 

JList

: 여러 개의 아이템을 리스트 형식으로 보여주고 선택하는 컴포넌트 입니다.

- JComboBox와 기본적으로 같은 기능

- JScrollPaneJlist를 삽입하여 스크롤 가능

 

class JListTest extends JFrame{
	
	String[] sport = {"농구" , "축구" , "배구" , "야구", "테니스", "핸드볼"};
	JListTest(){
		JList<String> jl = new JList<String> (sport); // 제너릭으로 정의해서 사용.
		jl.setVisibleRowCount(3); // 화면에 보여줄 행 수 정의.
		JScrollPane jp = new JScrollPane(jl); //  스크롤바 적용
	
		Container container = getContentPane();
	    container.setLayout(new FlowLayout());
	   
	    container.add(jp); 
        // JList가 탑제된 JScrollPane을 저장시켜줘야 정상적으로 동작이 진행된다. 
	    
		setTitle("리스트 상자 실습");
		setSize(200,200);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
	}
}
public class JList_ {
	public static void main(String[] args) {
		new JListTest();
	}
}

 

JList는 하나의 배열로 저장 되는 것이기 때문에 같은 자료형으로 저장해야 합니다. 그래서 제너릭으로 선언해줍니다 .

 

결과값:

 

 

 

● JTabbedPane 

:  그룹 폴더 컴포넌트를 만들어주는 클래스입니다.

 

class JPanelTest extends JFrame{
	
	JPanelTest(){
		
		Container container = getContentPane();
		container.setLayout(new BorderLayout());
		
		// 첫번째 패널 객체 생성 및 컴포넌트 추가 
		JPanel jp1 = new JPanel();
		jp1.setLayout(new GridLayout(5,1));
		jp1.add(new JButton("JAVA"));
		jp1.add(new JButton("R"));
		jp1.add(new JButton("PYTHON"));
		jp1.add(new JButton("DB"));
		jp1.add(new JButton("WEB"));
		
		// 두번쨰 패널 객체 및 컴포넌트 추가 
		JPanel jp2 = new JPanel();
		jp2.setLayout(new GridLayout(4,1));
		jp2.add(new JRadioButton("java")); // JRadioButton 하나만 선택 가능 (ex, 성별)
		jp2.add(new JRadioButton("r"));
		jp2.add(new JRadioButton("python"));
		jp2.add(new JRadioButton("db"));
		
		// 2개의 패널을 J프레임컨테이너에 탑재
		container.add(jp1,BorderLayout.WEST);
		container.add(jp2,BorderLayout.EAST);
		
		setTitle("패널 컨테이너 실습");
		setSize(500,180);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
	}
}
public class JPanelTest_ {
	public static void main(String[] args) {
		new JPanelTest();
	}
}

 

출력값:

 

'빅데이터 > JAVA' 카테고리의 다른 글

[JAVA] JAVA&DATABASE 연결  (0) 2020.05.27
[JAVA] 이클립스, DB 연동 환경설정  (0) 2020.05.26
[JAVA] SWING(1)  (0) 2020.05.23
[JAVA] 네트워크(NETWORK)  (0) 2020.05.23
[JAVA] 스트림(Stream)  (0) 2020.05.20

SWING(UI)이란?
: java에 프로그램 안에서 화면을 구성하는 것을 의미합니다.

 

 

● 특징
- 운영체제에 영향을 받지 않습니다.
- jvm 안에 기능이 탑제 되어있습니다.

- 클래스 이름이 J자로 시작합니다.

- 화려하고 다양한 컴포넌트로 쉽게 GUI 프로그래밍을 할 수 있습니다.

 

 

●컴포넌트/ 컨테이너

 

컴포넌트 
: 버튼, 텍스트 상자, 레이블 상자, 옵션/체크박스등(윈도우 컴포넌트)

- 모든 스윙 컴포넌트는 javax.swing.JComponent를 상속

 

컴포넌트 예시)

 

 

 


컨테이너
: 컴포넌트를 담을 수 있는 클래스 - Frame, Panel(컨테이너 컴포넌트)

- java.awt.Container 상속

- 컨포넌트가 컨테이너에 탑재 되어야 UI 출력이 가능합니다.

 

UI 프로그램 샘플)

 

 

스윙 패키지 사용을 위한 import

- import java.awt.*;  그래픽 처리를 위한 클래스들의 경로명

- import javax.swing.*;  스윙 컴포넌트 클래스들의 경로명

- import javax.swing.event.*; 스윙 이벤트를 위한 경로명

 

 

● 스윙 프레임

 

모든 스윙 컴포넌트를 담는 최상위 GUI 컨테이너

- JFrame을 상속받아 구현

- 컴포넌트가 화면에 보이려면 스윙 프레임에 부착되어야 합니다.

- 프레임을 닫으면 프레임 내의 모든 컴포넌트가 보이지 않게 됩니다.

 

스윙 프레임(JFrame) 기본 구성

프레임 스윙 프로그램의 기본 틀

메뉴바 메뉴들이 부착되는 공간

컨텐트– GUI 컴포넌트들이 부착되는 공간

// 컨테이너의 구조 형성(프로그램 시작과 동시에 ui 구현)
class ButtonTest extends JFrame{  
	
	ButtonTest(){ 
	// 버튼, 레이블 객체 생성 (컴포넌트의 요소-> 자료형)	
		JButton male = new JButton("남자"); // 남자 버튼
		JButton female = new JButton("여자"); // 여자 버튼
		JLabel label = new JLabel("당신의 성별은?"); // 문자열을 출력
		
		
		// Frame 컨테이너 객체 생성  
		Container container = getContentPane(); 
		//  배치관리자 생성: 자동 컴포넌트 요소 배치 
		FlowLayout layout = new FlowLayout(); 
		
		container.setLayout(layout); 
        // 컨테이너는 컴포넌트를 플로우 레이아웃에 맞추어 배치해준다. 
		
		// 컨테이너에 컴포넌트 추가 (.add)
		container.add(male);
		container.add(female);
		container.add(label);
		
		// 컨테이너의 제목, 크기, 종료, 보이기(출력)
		setTitle("버튼 컴포넌트 테스트"); // 컨테이너 제목
		setSize(300,100); // 컨테이너 크기(가로, 세로)
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
        // 컨테이너 종료(안보이게만 되어 있던 기능 -> 완전 종료)
		setVisible(true); // 컨테이너 보이기(출력)
	}
}
public class Swing01 {
	public static void main(String[] args) {
		new ButtonTest();
	}
}

Frame 컨테이너 객체 생성 (getContentPane())
Container container = getContentPane();  안에서 new 해서 컨테이너를 만들어서 주소값을 return해줍니다. 최소 한개의 컨테이너가 생성이 되면 이 메서드를 통해서 new 하는 것이 아니라 하나의 컨테이너로 사용합니다.

(calender 컨셉 동일)

 

결과값

 

 

 

위의 결과에 추가적인 기능을 넣어보도록 하겠습니다. 남자, 여자의 버튼이 눌리면 단신의 성별은? 남자, 여자 로 출력되도록 하겠습니다.

 

이러한 추가적인 정보를 넣는 것을 컴포넌트에 이벤트 처리한다고 합니다.

- 이벤트란 : 특정 컴포넌트에서 발생하는 사건을 의미하며, 버튼의 클릭, 텍스트 상자에 커서가 들어오는 경우등을 예로 들 수 있습니다.

 

이벤트 처리 절차

1. 이벤트와 연관된 인터페이스를 사용하여 클래스 작성

2. 컴포넌트 객체 생성

3. 하단 객체에 리스너를 등록

4. 이벤트 처리할 처리 루틴을 작성

 

class ButtonEvent extends JFrame implements ActionListener{
	
	JLabel result; // 생성자 밖에서도 사용하기 위해서 field에 선언
	
	ButtonEvent(){  
		
		JButton male = new JButton("남자");
		JButton female = new JButton("여자");
		JLabel label = new JLabel("당신의 성별은?");
		result = new JLabel();
		
		Container container = getContentPane();
		
		FlowLayout layout = new FlowLayout();
		
		container.setLayout(layout);
		
		container.add(male);
		container.add(female);
		container.add(label);
		container.add(result);
		
		// 이벤트 처리를 위한 버튼에 리스너 등록
		male.addActionListener(this);  
		female.addActionListener(this);
		
		setTitle("버튼 컴포넌트 테스트");
		setSize(300,100);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
	}

	@Override 
	public void actionPerformed(ActionEvent e) { 
		result.setText(e.getActionCommand()); 
	}
}
public class ButtonEvent_ {
	public static void main(String[] args) {
		new ButtonEvent();
	}
}

위에 똑같은 코드에 implements ActionListener 다형성을 통한 오버라이딩으로 되어진 method를 통해서 이벤트를 구현하게 해줍니다.

 

male.addActionListener(this); 자신 객체 안에서 이벤트 처리의 동작을 처리해줍니다. 리스터 등록이 끝이 나면 actionPerformed(); method가 호출합니다.
female.addActionListener(this); 위의 코드와 동일한 처리를 해줍니다.

 

public void actionPerformed(ActionEvent e) { = (ActionEvent e) : java가 선언한 참조변수의 e 의 주소값을 불러옵니다.
버튼이 눌렸다 라는 의미로 해석하며, ActionListener 정의 되어 있는 추상메서드 : 다형성에 의한 오버라이딩 , 버튼이 눌렸을 때의 기능을 Method를 통해서 구현합니다. 메서드만 오버라이딩해서 기능만 정의가 된것이지 실질적인 이벤트 기능이 탑재 된 것이 아니므로 addActionListener(); 를 꼭 입력해야합니다.

 

결과값:

 

 

 

 

 

이미지 파일을 이용한 Swing 구현)

class JImageTest extends JFrame{
	
	JImageTest(){

		// ImageIcon ii = new ImageIcon("images/korea.gif"); ./ 뺀다고 해서 문제 되지 않는다. 
		ImageIcon ii = new ImageIcon("./images/korea.gif"); 
        // (./) default 위치에서 시작하겠다.
		
		// "버튼 이름" 과 이미지 아이콘으로 버튼 객체 생성
		// 2. 버튼에 아이콘 삽입
		
		JButton korea = new JButton("클릭", ii);
        // 이미지를 넣을 때 ("입력할 text" , 이미지file);
        
		Container container = getContentPane(); 
        // method를 통해서 container 객체를 가져온다. 
		
		container.setLayout(new FlowLayout()); 
		
		container.add(korea);
		
		setTitle("대한민국");
		setSize(500,180);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
	}
}

public class JImage_ {
	public static void main(String[] args) {
		   new JImageTest();
	}
}

 

ImageIcon 참조변수  =  new ImageIcon("./ 폴더명 / 파일이름" );

폴더의 위치 default 값:

ImageIcon ii = new ImageIcon("./images/korea.gif");

 

지금 사용하고 있는 pakage 에 넣어주면 파일을 읽어옵니다.

 

 

결과값

'빅데이터 > JAVA' 카테고리의 다른 글

[JAVA] 이클립스, DB 연동 환경설정  (0) 2020.05.26
[JAVA] SWING (2)  (0) 2020.05.25
[JAVA] 네트워크(NETWORK)  (0) 2020.05.23
[JAVA] 스트림(Stream)  (0) 2020.05.20
[JAVA] Thread  (0) 2020.05.19

TCP/IP 프로토콜

: TCPTransmission Control Protocol

- 두 시스템 간에 신뢰성 있는 데이터의 전송을 관장하는 프로토콜입니다.

- TCP에서 동작하는 응용프로그램 사례 : e-mail, FTP, (HTTP)

 

: IP는 Internet Protocol

- 패킷 교환 네트워크에서 송신 호스트와 수신 호스트가 데이터를 주고 받는 것을 관장하는 프로토콜입니다.

- TCP보다 하위 레벨 프로토콜

 

+) IP 주소 : 네트워크 상에서 유일하게 식별될 수 있는 컴퓨터 주소입니다.

- 숫자로 구성된 주소로 4개의 숫자가 ‘.’으로 연결되어있습니다. ) 192.156.11.15

- 숫자로 된 주소는 기억하기 어려우므로 www.naver.com과 같은 문자열로 구성된 도메인 이름으로 바꿔 사용합니다.

 

 

포트

- 통신하는 프로그램 간에 가상의 연결단 포트 생성합니다.

- IP 주소는 네트워크 상의 컴퓨터 또는 시스템을 식별하는 주소입니다.

- 포트 번호를 이용하여 통신할 응용프로그램 식별합니다.

- 모든 응용프로그램은 하나 이상의 포트 생성 가능합니다.

- 포트를 이용하여 상대방 응용프로그램과 데이터 교환합니다.

 

 

클라이언트/서버(client/server)
- 컴퓨터간의 관계를 역할(role)로 구분하는 개념으로 서비스를 제공하는 쪽이 서버, 제공받는 쪽이 클라이언트입니다.
- 제공하는 서비스의 종류에 따라 메일서버(email server), 파일서버(file server), 웹서버(web server) 등이 있습니다.
- 전용서버를 두는 것을 ‘서버기반 모델’, 전용서버없이 각 클라이언트가 서버역할까지 동시에 수행하는 것을

  ‘P2P 모델’이라고 합니다.

 

● 소켓 프로그래밍

 

소켓 (socket)

: TCP/IP 네트워크를 이용하여 쉽게 통신 프로그램을 작성하도록 지원하는 기반 기술을 말합니다.

 

특징

- 두 응용프로그램 간의 양방향 통신 링크의 한쪽 끝 단

- 소켓끼리 데이터를 주고받음

- 소켓은 특정 IP 포트 번호와 결합

- 자바로 소켓 통신할 수 있는 라이브러리 지원

- 소켓 종류 : 서버 소켓과 클라이언트 소켓

- 전화할 때 양쪽에 전화기가 필요한 것처럼, 프로세스간의 통신에서도 양쪽에 소켓이 필요

 

 

예시) Socket 클래스(서버/ 클라이언트)

 

서버)

public class SocketServer { // 서버로 구성해서 동작. 
	public static void main(String[] args) {
		
		try {
			ServerSocket serverScoket = new ServerSocket(9001); 
            // 서버로 동작되게 구성하도록 해준다.  
			// ServerSocket 인스턴스 되는 순간 서버로 구현되어지도록 한다(환경구축 완료)

			while(true) { // 클라이언트의 요청이 오면 바로 처리 할 수 있도록 무한대기 한다. 
				Socket socket =  serverScoket.accept();
				ObjectInputStream InStream = 
                new ObjectInputStream(socket.getInputStream()); 
				// 프로그램과 socket 사이의 통로로 내용을 꺼내온다. 
				
				String msg = InStream.readUTF(); 
                // 유니코드로 되어있는 문자열을 읽어오도록 한다. 
				System.out.println("클라이언트가 전송해 온 메세지 : " + msg);
				
				if(msg.equals("exit")) {break;}
				
				ObjectOutputStream outStream = 
                new ObjectOutputStream(socket.getOutputStream());
				outStream.writeUTF("홍길동이 전달한 메세지 : " + msg + "잘 받았어요.");
				// writeUTF 그냥 두면 buffer 가 찰 때까지 기다린다. 
				
				// 실시간 처리 
				outStream.flush();
              
				// 사용후 close();
				outStream.close();
				InStream.close();
				socket.close();
			}
			serverScoket.close();
		} catch (IOException e) {
			e.printStackTrace();
		}  

ServerSocket serverScoket = new ServerSocket(9001); // 서버로 동작되게 구성하도록 해줍니다. ( ) 안의 숫자는 포트번호로  9001 번으로 셋팅 , 1000~9999 부터는 임의로 번호를 부여해서 사용할 수 있으며, 안정적으로는 5000이후 번호로 셋팅 하는 것이 좋습니다. 9001 포트번호로 이 프로그램을 사용합니다. (정보 전달)
- 운영체지는 포트 번호로 프로그램들을 관리한다.

 

주의) DB 설치할 때 default 값으로 8080으로 되어있으므로 8080을 사용하지 않아야 합니다.

 

Scoket socket = serverScoket.accept();

참조변수를 선언해서 전달 받은 주소값을 저장한다. 메모리에는 클라이언트의 정보가 모두 들어있습니다. 서버는 대기하고 클라이언트가 요청할 때까지 대기하다가 요청해오면 그 정보를 메모리에 담아서(안에서 new) Scoket 단위로 저장하여 그 주소값을 return 해서 socket에 저장해줍니다.

 

outStream.writeUTF("홍길도이 전달한 메세지 : " + msg + "잘 받았어요.");
writeUTF 그냥 두면 buffer 가 찰 때까지 기다립니다 하지만 채팅 프로그램에서는 퍼포먼스보다 속도가 중요하기에

실시간으로 보내는 flush();를 사용합니다.단, flush();는 퍼포먼스가 많이 떨어지므로 상황에 맞춰서 사용하는 것이 좋습니다.   

클라이언트)

public class SocketClient {

	public static void main(String[] args) {
		try {
			Socket socket = new Socket("localhost", 9001);
			
			ObjectOutputStream outStream = 
					new ObjectOutputStream(socket.getOutputStream());
			
			outStream.writeUTF("홍길동");
			outStream.flush();
			
			ObjectInputStream inStream = 
					new ObjectInputStream(socket.getInputStream()); 
			
			String msg = inStream.readUTF();
			
			System.out.println("서버로부터 전송되어진 메세지 :");
			System.out.println(msg);
			
			inStream.close();
			outStream.close();
			socket.close();
			
		} catch (IOException e) {
			e.printStackTrace();
		}

위의 서버와 연동을 하기 위해서  Socket socket = new Socket("localhost", 9001); "localhost" = 내 pc

저의 pc의 서버와 연결하기 위해서 "localhost"를 사용하였고, 다른 pc와 연결해주고 싶을 때는 "localhost" 자리에 pc IP를 넣어주면 됩니다.

 

서버를 실행한 이후 클라이언트를 실행하면 결과 값으로 밑의 결과가 나타납니다.

 

서버로부터 전송되어진 메세지 :
홍길동이 전달한 메세지 : 홍길동 잘 받았어요.

 

 

 

 

'빅데이터 > JAVA' 카테고리의 다른 글

[JAVA] SWING (2)  (0) 2020.05.25
[JAVA] SWING(1)  (0) 2020.05.23
[JAVA] 스트림(Stream)  (0) 2020.05.20
[JAVA] Thread  (0) 2020.05.19
[JAVA] 컬렉션 프레임워크 ( Collection Framework )  (0) 2020.05.18

 

스트림(Stream)이란?

: 프로그램을 연결해주어 입출력을 가능하게 하는 통로라고 할 수 있습니다.

 

● 스트림 입출력

- 버퍼를 가지고 순차적으로 이루어지는 입출력을 의미합니다.

   자바의 입출력 스트림

- 입력 스트림 : 입력 장치로부터 자바 프로그램으로 데이터를 전달합니다.

- 출력 스트림 : 출력 장치로 데이터 출력합니다.

 

 

● 자바의 입출력 스트림 특징

 

- 스트림의 양끝에 입출력장치와 자바 응용프로그램 연결 합니다.

- 스트림은 단방향 : 입력과 출력을 동시에 하는 스트림은 없습니다.

- 입출력 스트림 기본 단위 : 바이트 스트림의 경우 : 바이트 , 문자 스트림의 경우 : 문자(자바에서는 문자1: 2 바이트)

- 선입선출 구조로 되어있습니다.

 

입력 스트림 : InputStream - 프로그램으로 데이터를 읽어드리는 스트림입니다.

출력 스트림 : OutputStream - 프로그램으로 데이터를 내보내는 스트림입니다.

InputStream in= new FileInputStream("Fonts.zip");

스트림의 생성은 결국 인스턴스의 생성으로 가능합니다.

 

 

 

1) FileStream

: 파일을 대상으로 프로그램과 연결해주어 입출력을 가능하게 하는 통로의 역할을 합니다.

public class ByteFileCopy {
	public static void main(String[] args) {
	
		try { 
			int copyByte = 0;
			InputStream in= new FileInputStream("Fonts.zip");// 입력용 stream 
			OutputStream out = new FileOutputStream("Copy.zip"); // 출력용 stream 
			
		    while(true) {
			    int bData = in.read(); 
			    if(bData == -1) { 
				    break; 
			    }
			    out.write(bData);  
			    copyByte++;
		    }
		    
		    in.close();
		    out.close();
		   
		    System.out.println("복사된 바이트 크기 : " + copyByte );

		} catch (IOException e) { 
			e.printStackTrace();
		} 

- InputStream, OutputStream 모든 입출력의 최상위 클래스로  FileInputStream, FileOutputStream이  상속하기 때문에 다형성에 의해서 부모class를 사용해도 문제되지 않는다. 또한 오버라이딩에 의해서 메소드를 호출 시킵니다.

 

- 입력의 대상에 적절하게 read 메소드가 정의되어 있습니다. 단 read(); byte 단위로 읽어오는데 반환형을 int를 사용합니다.  모든 내용을 읽어오면 - 1이라는 값을 return 해줍니다.

 

- out.write(bData); // 1byte 로 읽어서 처리 하기 때문에 많은 시간이 소요됩니다.

 

- close : Stream 을 통해서 할당 받았던 메모리에 저장했었던 자료들을 한번에 정리하여 재사용 할 수 있도록 해줍니다.

 모든 코드를 사용한 이후에는 close를 반드시 해줘야합니다.

 

- (IOException e)예외가 발생하는 경우 : 관리자 권한으로 연결되어지는 file 같은 경우(운영체제의 권한에 의해서)에 발생할 수 있습니다.

 

주의 )

위 예제에서는 바이트 단위 복사(1바이트씩 복사)가 진행된다. 따라서 50MB가 넘는 크기의 파일 복사에는 오랜 시간이 걸립니다.

 

위의 문제점인 시간이 오래 걸리는 것을 해결하기 위한 방법이 을 보여드리겠습니다.

public class BufferFileCopy {
	public static void main(String[] args) {
		
		try { 
			byte[] buf = new byte[1024]; // 1024 byte = 1kb (1kb씩 저장하도록 만듬)
			int copyByte = 0;
			InputStream in= new FileInputStream("Fonts.zip");
			OutputStream out = new FileOutputStream("CopyBuffer.zip");
			
		    while(true) {
			    int readLen = in.read(buf); 
			   
			    if(readLen == -1) { 
				    break; 
			    }
			    out.write(buf, 0, readLen);  
                // buf 배열(크기) - 1024개  ,  0번째부터 , readLen 의 개수까지 write
			    copyByte+=readLen;  // 전체읽어온 개수 확인 
		    }
		    in.close();
		    out.close();
		    
		    System.out.println("복사된 바이트 크기 : " + copyByte );

		} catch (IOException e) { 
          e.printStackTrace();} 

배열을 선언byte[] buf = new byte[1024]; 1024 byte = 1kb (1kb씩 저장하도록 만듬) 합니다.

선언한 배열을 read(); 에 넣어서 아무것도 넣지 않았을 때 1byte 씩 읽어오지만 buf을 넣어주면 읽어온 데이터를 1024개까지 쌓아서 buf가 꽉차면 읽어온 data의 개수 만큼 return 해줍니다. 이것을 통해 시간을 많이 단축할 수 있습니다

 

 

 

2) DataStream

: 자바의 기본 자료형 데이터를 바이트 스트림으로 입출력하는 기능을 제공합니다.

 

- DataInputStream과 DataOutputStream 은 FilterInputStream과 FilterOutputStream을 상속하고 있어, 객체 생성시에 InputStream과 OutputStream을 매개변수 인자를 가집니다.

이 클래스와 입출력 장치를 대상으로 하는 입출력 클래스를 같이 이용하면 자바의 기본 자료형 데이터를 파일 등 입출력 장치로 직접 입출력할 수 있습니다.

 

public class DataFilterStream {
	public static void main(String[] args) {
		
		 try {
			OutputStream out = new FileOutputStream("data.bin"); 
			// file 이 없으면 입력한 이름으로 file 을 만들어준다. 
            // file이 이미 존재하면 원래 있던 내용을 다 지우고 내용을 입력한다.
			       
			DataOutputStream filterOut = new DataOutputStream(out);
			// OutputStream을 연결. 
			
			// out.write(365); // 별도의 자료형 입력이 없을 때는 int로 저장된다. 
			// out.close();
			
			filterOut.writeInt(365); // : 정수값 저장
			filterOut.writeDouble(3.14); // : 실수값 저장 
			filterOut.close(); // 필터를 close 하면 연결된 Stream 도 close 된다. 
			
			InputStream in = new FileInputStream("data.bin");
			DataInputStream filterIn = new DataInputStream(in);
			// InputStream 연결. 
			
			System.out.println(filterIn.readInt());
			System.out.println(filterIn.readDouble());
			
			filterIn.close();
			
					
		} catch (IOException e) {
			e.printStackTrace();
		}

 

FileInputStream / FileOutputStream 은 byte[] 단위의 데이터만 입/출력을 할 수 있었습니다. 하지만 DataStream Filter를 적용함으로써, 자바 기본 자료형(char, int, long, ...) 으로 데이터를 입력하고 출력할 수 있게 되었습니다.

 

 

 

FileStream은 1 Byte 단위로 입/출력이 이루어지면 기계적인 동작이 많아지므로 효율이 떨어지게 됩니다. 또한, 사용자가 일일이 버퍼와 크기를 지정하여 입출력을 하게 되는 것도 정적이고 불편합니다. 이러한 문제점을 해결하기 위해서 사용하는 것이 BufferedStream 입니다.

 

3) BufferedStream

public class ByteBufferedFileCopy {
	public static void main(String[] args) {
		
		// 퍼포먼스의 문제를 최소화 하여 결과값을 가질 수 있도록 한다. 
		try { 
			int copyByte = 0;
			InputStream in= new FileInputStream("Fonts.zip");
			BufferedInputStream bufferIn =  new BufferedInputStream(in);
			
			OutputStream out = new FileOutputStream("Copy1.zip");
			BufferedOutputStream bufferOut = new BufferedOutputStream(out);
	
		    while(true) {
			    int bData = bufferIn.read(); 
	
			    if(bData == -1) { 
				    break; 
			    }
			    bufferOut.write(bData); 
			    copyByte+= bData;
		    }
		    bufferIn.close();
		    bufferOut.close();
		    
		    System.out.println("복사된 바이트 크기 : " + copyByte );

		} catch (IOException e) { 
			e.printStackTrace();
		} 

사용자가 BufferedInputStream과 BufferedOutputStream을 이용하여 프로그램을 작성하면 1 바이트씩 읽고 쓰는 모든 작업이 하드 디스크 파일이 아닌 내부적인 버퍼를 대상으로 발생하며, 필요에 따라 버퍼와 하드 디스크 파일간에 입출력이 간헐적으로 발생하므로 전체적인 입출력 성능이 동적으로 향상되도록 해줍니다.

 

 

4) FileWriter
: 운영체제의 포멧으로 데이터를 저장하도록 합니다.

public class FileWriterStream {   
	public static void main(String[] args) { 

		char ch1 = 'A';
		char ch2 = 'B';
		// 윈도우 저장할 때,  영어는 1byte 로 처리, 
        // 한국어는 2byte 다른 나라는 3byte로 처리되는 곳도 있다. 
		
		try {
			Writer out = new FileWriter("hyper.txt"); 
			out.write(ch1);                                       
			out.write(ch2);                                    
			out.close();                                        
			
		} catch (IOException e) {
			e.printStackTrace();
		} 

 

FileWriter 운영체제가 관리하는 문자열 포멧으로 운영체제가 파일에 담게 처리합니다. 운영체제가 저장하고 있기 때문에 깨지지 않고 저장됩니다. char 자료형 2개 이므로 2byte 로 저장합니다. 메모장으로 읽을 때는 깨지지 않고 잘 보이지만 java에서 그대로 읽어내면 깨져서 보입니다.

java의 형식으로 저장되는 것이 아닙니다. 만약 java의 형태였다면 4byte로 저장되고, 깨져보였을 것입니다.

 

5) FileReader

: 운영체제의 포멧에 맞춰서 저장했던 데이터를 java의 문자처리 포멧으로 변환해서 반환해줍니다. 

public class FileReaderStream { 
	public static void main(String[] args) {
	
		char[] cbuf = new char[10];
		
		try { 
			Reader in = new FileReader("hyper.txt"); 
			int readCnt = in.read(cbuf, 0, cbuf.length); // 읽어온 개수만큼만 반환을 해준다. 
			for(int i=0; i < readCnt ; i++) {
				System.out.println(cbuf[i]);
			}
			in.close();
		} catch (IOException e) {
			e.printStackTrace();
		}

 

- JDK의 바이트 스트림 클래스 계층 구조

 

 

 

- JDK의 문자 스트림 클래스 계층 구조

 

'빅데이터 > JAVA' 카테고리의 다른 글

[JAVA] SWING(1)  (0) 2020.05.23
[JAVA] 네트워크(NETWORK)  (0) 2020.05.23
[JAVA] Thread  (0) 2020.05.19
[JAVA] 컬렉션 프레임워크 ( Collection Framework )  (0) 2020.05.18
[JAVA] Generics  (0) 2020.05.17

Thread 란?

사용자가 작성한 코드로서, JVM에 의해 스케줄링되어 실행되는 단위입니다.

쉽게 설명해서 하나의 프로세스 안에서 2가지 이상의 일을 수행하는 것과 같은 것과 같은 효과를 주는 것을 의미합니다.

 

Java Thread

- 자바 가상 기계(JVM)에 의해 스케쥴되는 실행 단위의 코드 블럭입니다.

- 스레드의 생명 주기는 JVM에 의해 관리됩니다.

 

 JVM멀티스레드의 관계

- Thread 는 운영체제와 관련있는 기능으로 java 이외에 thread를 구현해주는 프로그램이 없습니다.

- 하나의 JVM은 하나의 자바 응용프로그램만 실행합니다.

- 자바 응용프로그램이 시작될 때 JVM이 함께 실행합니다.

- 자바 응용프로그램이 종료하면 JVM도 함께 종료합니다.

- 하나의 응용프로그램은 하나 이상의 스레드로 구성 가성합니다.

 

-- Thread 클래스 작성(Thread 클래스 상속. 새 클래스 작성)
class TimerThread extends Thread { 


-- Thread 코드 작성
run() 메소드 오버라이딩
	@Override
	public void run() { // run() 오버라이딩
		

-- Thread 객체 생성
TimerThread th = new TimerThread(); 

-- Thread 시작(start() 메소드 호출)
th.start();




run() 메소드 오버라이딩

- run() 메소드를 Thread 코드라고 부릅니다.

- run() 메소드에서 Thread 실행 시작합니다.

- run(); 을 통해서 main 2개인것과 같은 효과를 가지게 해주며,  main과 동시 수행합니다.

 

start() 메소드 호출

- Thread 작동 시작하고  JVM에 의해 스케줄되기 시작합니다.

- start(); 호출하러 가자마자 바로 복귀를 시켜서 다음 명령어를 수행하고, 운영체제에게 명령수행하기 전 준비하도록 요청합니다.

- Thread  수행하기 전 메모리들을 운영체제에게 요청해서 thead의 메모리를 할당받아 스레드의 run을 호출하게끔 구현이 되어져있습니다. main은 main 대로 수행하고, start로 바로 복귀 시켜 두개가 함께 수행하도록 합니다.

 

 

 

 

class SumThead extends Thread{

	String threadName; 
	int start, end;
	
	SumThead(String threadName, int start, int end){
		
		this.threadName = threadName;
		this.start = start;
		this.end = end;
	}
	
	@Override
	public void run() { 
		int sum = 0;
		
		for(int i = start ; i <= end; i++) {
			sum+=i;
			System.out.println(threadName);
		}
		System.out.printf("%s => %d ~ %d 까지의 합 : %d \n", threadName, start, end, sum);
	}
}
public class ThreadUnderstand {
	public static void main(String[] args) { 
		SumThead  thread1 = new SumThead ("쓰레드1", 1, 10); // main 안에서 new 하는 컨셉은 변함없다. 
		// 1~10까지의 합
		
		SumThead  thread2 = new SumThead ("쓰레드2", 11, 20);
		// 11~20까지의 합 
		
		int sum = 0;
		
		thread1.start(); 
		thread2.start(); 
		
		for(int i = 1 ; i <= 50 ; i++) {
			sum += i;
			System.out.println("main");
		}
		System.out.println("main() 메서드 실행 => 1~50까지의 합 : " + sum);
		System.out.println("프로그램 종료.");
	}
}

결과값 : main, thread1, thread2 함께 수행하는 효과를 주지만 출력되는 순서는 일정하게 나타나지 않습니다. 이것은 

현재 운영되는 프로그램에 따라서 다른 결과를 나타나게 됩니다. 결과의 순서는 운영체제의 알고리즘만 알 수 있습니다. 
결과값을 통해서 3개의 작업이 골고루 수행되는 효과를 보여줄 수 있습니다.

 

 

자료형을 선언했을 때, 그 자료형을 thread 로 상속받고 싶을 때 다른 class 를 상속받았을 때 사용법)

=Runnable 사용

class Sum {
	int num; 
	
	Sum(){num=0;}
	
	public void addNum(int num) {this. num += num;}
	public int getNum() {return num;}
}

class AddThread extends Sum implements Runnable{    
	
	AddThread(int start , int end){
		this.start = start;
		this.end = end;
	}

	int start, end; 
	                                                          
	@Override                                                          
	public void run() {   
		for(int i = start; i <= end ; i++){
			addNum(i);
		}System.out.printf("%d ~ %d 의 총 합은 : %d  \n", start, end, num);
	}   
}

public class RunnalbleThread {
	public static void main(String[] args) {
		
		 AddThread at1 = new  AddThread(0,50); // thread 기능이 탑재 되어 있지 않다. 
		 // runnable을 상속받는  AddThread을 사용하여 run을 사용한다. 
		 
		 AddThread at2 = new  AddThread(51,100);
		 
		Thread thread1 = new Thread(at1); // run 을 수행시킬 코드를 만들어줘야 한다. 
		Thread thread2 = new Thread(at2); 
		
		thread1.start();
		thread2.start();
		
		try {
			thread1.join();
			thread2.join();
		} catch (InterruptedException e) {  
			e.printStackTrace();
		} 
		
		// join() method는 try~each 문으로 감싸줘야하며, 
        // join() method는 run(); method가 수행될때까지 기다린다. 
		
		System.out.println("0~100까지의 합 : " +  (at1.getNum()+at2.getNum()));

 

※ thread기능을 탑재 시키기 위한 유일한 방법

- Sum 을 상속 받아서 thread를 상속하지 못할 때 implements Runnable 인터페이스 사용합니다.
- Runnable 안에 run(); 추상method 하나 들어가있습니다. 또한 thread와는 상관이 없으며 단지 run method 만

  오버라이딩 되어 있는 것입니다.

 

- join() method는 run(); method가 수행될때까지 기다렸다가 수행합니다.

 

 

여기서 위의 코드의 문제점!

(at1.getNum()+at2.getNum())의 값이 계속 다르게 나타납니다.


그 이유는 thread1, thread2 , main 함께 시작하기 때문에 컴퓨터의 상태에 따라서 언제 실행될지 알 수 없습니다.
thread1, thread2이 구동되기 전에 main은 벌써

System.out.println("0~100까지의 합 : " + (at1.getNum()+at2.getNum())); 실행할수도 때문에 결과가 항상 다르게 출력합니다.
thread1, thread2가 구동이 되고 나서 System.out.println("0~100까지의 합 : " + (at1.getNum()+at2.getNum())); 실행 되어야지 올바른 결과값이 나타납니다.  

 

위의 코드를 해결 우선순위를 넣어서 코드를 만들어보겠습니다.

 

 

우선순위)

class MessageSendingThread extends Thread{

    String message; 
    
    // 우선순위 부여(절대적인 것이 아닌 가중치정도록 생각하자.)
    MessageSendingThread(String message, int prio){
    	
    	this.message = message;
    	setPriority(prio); // 값을 다시 setting 할 수 있게 만들어준다. 
    }
	
	@Override
	public void run() {  // main 2개 효과 
		for(int i = 0; i < 1000; i++) {
			System.out.printf("%s(%d) \n" , message, getPriority()); 
		}	
	}
}

public class PriorityTest {
	public static void main(String[] args) {
		
		// 우선순위 
		MessageSendingThread tr1 = new MessageSendingThread ("First", Thread.MAX_PRIORITY); 
        // ("First", 10);
		MessageSendingThread tr2 = new MessageSendingThread ("Second", Thread.NORM_PRIORITY); 
        // ("Second", 5);
		MessageSendingThread tr3 = new MessageSendingThread ("Third", Thread.MIN_PRIORITY); 
        // ("Third", 1);
		
	    tr1.start();
	    tr2.start();
	    tr3.start();	
	}

}

- setPriority(prio) 을 생성자에 초기화 시켜줍으로 run(); method안에 숫자를 넣어 우선순위 대로 출력하도록 만들어줍니다.  

 

- 우선순위가 부여되었다고 해서 Thread의 특성상 결과에 있어서 정확하게 순서에 맞춰서 출력되지는 않습니다. 각각 1000가지 씩 수행되어야 하는데, 우선순위가 낮다고 해서 무조건 늦게 나오는 것이 아니라는 점을 염두해두면 좋겠습니다.

 

동기화)

: 하나의 thread 의 동작이 완전히 진행된 이후 순서를 넘기는 것을 의미합니다. (synchronized)

class Sum{
    int num; 
    
	Sum(){num=0;}
    
	public synchronized void addNum(int num) {this. num += num;} 
	public int getNum() {return num;}                                                                                         
}                                                                        
                                                                           
class AdderThread extends Thread{

	Sum sumInst ;
	int start, end;
	
	AdderThread(Sum sum, int s , int e){
		this.sumInst = sum;
		this.start = s;
		this.end = e; 
	}
	
	@Override
	public void run() {
		for(int i =start ; i<= end ; i++) {
			sumInst.addNum(i);
		}
	}
}

public class ThreadHeapMultiAccess {
	public static void main(String[] args) {
		Sum sum = new Sum();
		
		AdderThread at1 = new AdderThread(sum , 1 , 5000); // sum의 주소값이 저장
		AdderThread at2 = new AdderThread(sum , 5001 , 10000); // sum의 주소값이 저장
		
		at1.start();
		at2.start();
		
		try {
			at1.join();
			at2.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

 

최종적으로 업데이트가 균일하게 진행되면 문제가 없지만 그렇지 못하게 때문에 나오는 문제점입니다.

위의 코드를 보면  at1 과 at2 가 같은 data를 가지고 수행하는데 Thread의 특성으로 인해서 올바른 값이 출력되지 않습니다. 이러한 문제점을 해결하기 위해서 동기화를 하나의 값이 정확히 수행되고 나서 다음 값이 진행되록 만들수 있습니다.

 

- 위와 같이 둘 이상의 thread 가 heap 영역하나의 data 를 바라보도록 접근해서 처리하게 되면 문제가 생기므로 동시화를 고려해야 합니다. 왜냐하면 순서가 왔다갔다 하면서 수행을 하게 되면 결과 값이 날아가버리기 때문입니다.

 

- synchronized 를 활용하여 동작이 완료되서 복귀 될 때까지 순서가 넘어가지 않도록 할 수 있습니다. 단, 제어권을 넘기지 않고 다 수행한 이후 제어권을 넘기도록 하면 출력 속도가 느려지기 때문에 꼭 필요한 경우에 사용하는 것을 권장합니다.

 

+ Recent posts