데이터를 관리할 때, 비밀번호와 같은 중요한 데이터암호화할 필요가 있다. ( 나쁜 시스템 관리자가 있을 수 있으니..)

 

중요한 데이터를 복호화할 수 없는 알고리즘을 사용하여 암호화하여 관리해야한다. 

 

암호화 시 사용할 알고리즘은 SHA-256이다. SHA-256는 해시 함수중에 하나로서, 해시의 결과가 256bit이라고 한다.

 

 

Java에서 제공하는 MessageDigest 를 사용하여 암호화할 것이다.

 

순서로서는

  1. String 형태로 들어오는 암호화될 대상을 byte[]로 쪼갠 뒤, 
  2. MessageDigest 객체를 이용하여 해쉬함수를 통해 암호화된 결과를 byte[]형태로 반환받는다.
  3. 결과를 16진수 문자열로 변환시켜 String 형태로 변환하여 완성한다.

 

4. 이때, 1자리 수로 반환되는 경우가 있기 때문에 변환된 문자의 결과 길이가 1일 때마다 아무 문자나 앞이나 뒤에 추가해준다.

 

 

 

 

 

 

 

 

 

 

 

public String getSecureData(String password) {
		StringBuffer sb = new StringBuffer();//문자열을 누적시킬 객체
	
		try {
			//분해하여 16진수로 변환
			MessageDigest digest = MessageDigest.getInstance("SHA-256");
			byte[] data = password.getBytes("UTF-8"); //String형을 byte[]로 쪼갰다.
			byte[] hash = digest.digest(data);
			
			//쪼개진 데이터를 대상으로 16진수값으로 변환!!
			for(int i=0;i<hash.length;i++) {
				String hex = Integer.toHexString(0xff&hash[i]);//16진수 문자열로 변환
				if(hex.length()==1) {
					sb.append("0");
				}
				sb.append(hex);
			}
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		
		return sb.toString();
	}

같은 문자열을 암호화할 시 같은 암호화된 문자열이 반환되므로, 비밀번호와 같은 데이터를 암호화하여 사용할 수 있다.

'프로그래밍 > Java' 카테고리의 다른 글

java - mail 보내기  (0) 2021.01.06
싱글톤 패턴 알아보기  (0) 2020.12.14
JavaFX - 개발환경 구축 및 생명주기  (0) 2020.11.23
Java - JSON & XML 파싱  (0) 2020.11.17
Java - 소켓프로그래밍 기초 Echo System  (0) 2020.11.09

회원가입과 같이 mail을 보낼 경우 사용할 수 있다.

 

구글에서 제공하는 API를 사용해보겠다.

 

 

  • java에서 제공하는 dependency를 등록한다.
<!-- https://mvnrepository.com/artifact/javax.mail/mail -->
		<dependency>
			<groupId>javax.mail</groupId>
			<artifactId>mail</artifactId>
			<version>1.5.0-b01</version>
		</dependency>
  • 우선 구글로 접속하여 로그인한 뒤 google계정 탭으로 이동한다.

  • 보안 탭을 열어 2단계 인증 및 앱 비밀번호를 설정한다.

  • 앱 비밀번호를 이용하여 아래의 코드를 따라서 작성하고, 원하는 제목, 내용을 기입하여 보낼 수 있다!
import java.util.Properties;
import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

public class MailService {
	String host = "smtp.gmail.com";
	String user = "나의계정@gmail.com";
	String password = "앱비밀번호";
	Properties props = new Properties();
	
	public void send() {
		props.put("mail.smtp.host", host);
		props.put("mail.smtp.port", 465);
		props.put("mail.smtp.auth", "true");
		props.put("mail.smtp.ssl.enable", "true");
		props.put("mail.smtp.ssl.trust", "smtp.gmail.com");

		Session session = Session.getDefaultInstance(props, new Authenticator() {
			protected PasswordAuthentication getPasswordAuthentication() {
	               return new PasswordAuthentication(user, password);
	            }	
		});
		
		try {
			
			MimeMessage message = new MimeMessage(session);
			message.setFrom(new InternetAddress(user));
			message.addRecipient(Message.RecipientType.TO, new InternetAddress("받는사람이메일"));
			message.setSubject("보낼제목");
			message.setContent("<h1>this is</h1> content", "text/html;charset=utf-8");
			
			Transport.send(message);
			System.out.println("Success Message Send");
		} catch (MessagingException e) {
			e.printStackTrace();
		}
	}
	public static void main(String[] args) {
		new MailService().send();
	}
}
[출처] Java Mail HTM형식으로 보내기|작성자 원리파고

'프로그래밍 > Java' 카테고리의 다른 글

java - 암호화  (0) 2021.01.06
싱글톤 패턴 알아보기  (0) 2020.12.14
JavaFX - 개발환경 구축 및 생명주기  (0) 2020.11.23
Java - JSON & XML 파싱  (0) 2020.11.17
Java - 소켓프로그래밍 기초 Echo System  (0) 2020.11.09

싱글톤패턴(Singleton Pattern)

 

GoF의 디자인 패턴 중 하나인 싱글톤 패턴은 인스턴스를 오직 하나만 생성해서 메모리를 절약?할 수 있다.

 

package common.db;

import java.sql.SQLException;

import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;

public class PoolManager2 {
	InitialContext context;
	DataSource ds;
	private static PoolManager2 instance;
	private PoolManager2() {
		try {
			context = new InitialContext();
			ds = (DataSource)context.lookup("java:comp/env/jdbc/myoracle");
		} catch (NamingException e) {
			e.printStackTrace();
		}
	}
	public static PoolManager2 getInstance() {
		if(instance==null) {
			return instance = new PoolManager2();
		}
		return instance;
	}
}
  • 위 코드는 커넥션풀 관리하도록 만든 객체 중 일부이다.
  • 생성자의 접근지정자를 private
  • 클래스 내에 private인 현재 클래스의 객체를 멤버변수로 둔다
  • 해당변수의 get메서드static으로 만들어서 외부에서 이 클래스에 대한 인스턴스를 만들고 싶을 때는 오직 get메서드로만 생성할 수 있고 만약 아직 생성되지 않았다면 생성, 생성되어 있으면 그냥 반환만 받는 구조
  • static의 메서드에서는 static변수만 사용할 수 있으니 변수를 static으로!

실행결과

package common.db;

public class text {
	public static void main(String[] args) {
		for(int i=1;i<=10;i++) {
			System.out.println(i+" : "+PoolManager2.getInstance());
		}
	}
}

하나의 객체만 생성하게 되는 것을 볼 수 있다!

'프로그래밍 > Java' 카테고리의 다른 글

java - 암호화  (0) 2021.01.06
java - mail 보내기  (0) 2021.01.06
JavaFX - 개발환경 구축 및 생명주기  (0) 2020.11.23
Java - JSON & XML 파싱  (0) 2020.11.17
Java - 소켓프로그래밍 기초 Echo System  (0) 2020.11.09

자바FX(JavaFX)란? 

데스크톱 애플리케이션 리치 인터넷 애플리케이션(RIA)을 개발하고 배포하는 소프트웨어 플랫폼으로, 다양한 장치에서 실행 가능하다. 자바FX는 자바 SE를 위한 표준 GUI 라이브러리로서 스윙을 대체하기 위해 고안되었다.

출처 | 자바FX - 위키백과, 우리 모두의 백과사전 (wikipedia.org)

 

자바FX - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전.

ko.wikipedia.org

 

1) JavaFX 개발환경 구축 (Java버전 11부터는 내부에 탑재되어 있다고 한다!)

1. 구글창에 javafx download 입력 후 위 페이지로 이동!
2. 밑줄 친 페이지로 이동!
3. 자신의 컴퓨터의 OS에 맞는 설치파일 다운로드!
4. Eclipse Marketplace에서 e(fx)clipse를 입력하여 해당 플러그인 Install

해당 플러그인을 설치한 후, 이클립스를 재시작하고 나면 File-New-Other에 javafx가 생겼을 것이다! 

5. JavaFX Project 생성!

2) JavaFX 생명주기

우선, 자바FX 애플리케이션을 정의하기 위해서는 반드시 Application 추상 클래스를 상속받아야 한다!!

상속받은 후, 재정의할 메서드 중 start(), init(), stop()에 대해 알아볼 것이다.

start()는 애플리케이션이 실행할 준비가 되면 호출되는 메서드이다. 이 메서드는 반드시 재정의해야 하는 추상 메서드이다!

 

 

 

 

 

 

 

 

 

 

 

start메서드의 매개변수가 바로 애플리케이션의 윈도우이다!!!

FX에서는 윈도우의 반드시 하나의 Scene이 존재해야 한다. 

 

다음으로, init() 메서드를 살펴보자. 

init() 메서드는 인스턴스가 태어나고 초기화 작업에 사용되는 메서드이다.

 

다음, stop() 메서드는 메서드명과 같이 애플리케이션이 중지(종료)되었을 때 실행되는 메서드이다.

 

다음 예제를 보고 이해해보자!

package application;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class test extends Application{

	@Override
	public void start(Stage primaryStage) throws Exception {
		System.out.println("start() 메서드 호출 by  "+ Thread.currentThread().getName());
		//매개변수로 받은 stage 변수가 어플리케이션의 윈도우이다!!!
		
		//무대를 정의한다!!(FX에서는 윈도우에 반드시 하나의 Scene이 존재해야함)
		VBox parent = new VBox();//수직으로 컴포넌트를 배치하는 레이아웃 객체
													//FlowLayout과 비슷
		
		Scene s = new Scene(parent);//Parent란? 부모클래스를 의미하는 것이 아니라, 객체간 포함관계에서 바깥쪽
											//컨테이너를 의미
											//Swing과 비유하자면, 레이아웃 객체가 Parent이다!!
		
		Button bt = new Button("버튼");
		Button bt2 = new Button("버튼2");
		bt.setPrefWidth(200);
		bt.setPrefHeight(40);
		bt2.setPrefWidth(200);
		bt2.setPrefHeight(40);
		
		//버튼을 parent에 부착하기
		parent.getChildren().add(bt);
		parent.getChildren().add(bt2);
		
		//Scene을 윈도우에 부착
		primaryStage.setScene(s);
	
		bt.setOnAction((e)->{
			System.out.println("클릭했니?");
		});
		
		primaryStage.setMaxWidth(500);
		primaryStage.setMaxHeight(500);
		primaryStage.show();//윈도우 보이게
	}
	
	/*어플리케이션 시작 전, 초기화를 담당하는 메서드이다. 따라서 초기화할 게 없다면 재정의는 필수는 아니다
	 * 생성자 : 인스턴스가 태어날 떄 호출되는 메서드(더 시점이 빠르다)
	 * 초기화 : 인스턴스가 태어나고 초기화 작업에 사용되는 메서드*/
	
	public void init() throws Exception {
		//자바의 쓰레드의 메서드 중 현재 실행중인 쓰레드 정보를 얻기 위한 메서드 
		System.out.println("init() 메서드 호출 by "+ Thread.currentThread().getName());
	}
	
	public void stop() throws Exception {
		System.out.println("stop() 메서드 호출 by " + Thread.currentThread().getName());
	}
	
	
	public static void main(String[] args) {
		System.out.println("main() 메서드 호출 by " + Thread.currentThread().getName());
		launch(args);//애플리케이션을 실행하는 메서드!!!
	}
}

실행결과 보면 애플리케이션의 main() 메서드를 실행 후 애플리케이션의 초기화 작업인 init()를 실행한 후 애플리케이션이 실행될 준비가 완료되면 start() 메서드를 실행하며, 애플리케이션을 종료 시 stop() 메서드가 실행된다.

 

(start() 메서드를 실행시키는 쓰레드가 따로 존재하는데 JavaFX Application Thread가 이 일을 담당한다.

JavaFX Application Thread는 UI, Event을 담당하는 쓰레드이다.) - 사실, 이 부분은 아직 배우질 않아서 자세히는 적지 못하였음! 다음 수업을 듣고 보충해서 적어야 한다.

'프로그래밍 > Java' 카테고리의 다른 글

java - mail 보내기  (0) 2021.01.06
싱글톤 패턴 알아보기  (0) 2020.12.14
Java - JSON & XML 파싱  (0) 2020.11.17
Java - 소켓프로그래밍 기초 Echo System  (0) 2020.11.09
Java - JDBC(Java DataBase Connectiviy) 사용법  (0) 2020.11.05

JSON이란? 속성-값 쌍 또는 키-값 쌍으로 이루어진 데이터 오브젝트를 전달하기 위해 인간이 읽을 수 있는 텍스트를 사용하는 개방형 표준 포맷이다. 비동기 브라우저/서버 통신 을 위해, 넓게는 XML을 대체하는 주요 데이터 포맷이다.

XML이란? W3C에서 개발된, 다른 특수한 목적을 갖는 마크업 언어를 만드는데 사용하도록 권장하는 다목적 마크업 언어이다. 

 

1) JSON 파싱

mvnrepository.com/artifact/org.json/json

 

Maven Repository: org.json » json

JSON is a light-weight, language independent, data interchange format. See http://www.JSON.org/ The files in this package implement JSON encoders/decoders in Java. It also includes the capability to convert between JSON and XML, HTTP headers, Cookies, and

mvnrepository.com

 

위 MavenRepository에 들어가서 JSON을 파싱하여 사용하기 위한 라이브러리를 다운받아서 프로젝트에 등록한다.

 

 

		//StringBuffer를 쓴 이유는? String은 불변의 특징이 있으므로, 너무 많은 문자열 상수를 만들어내지 않기 위해
		StringBuffer sb = new StringBuffer();
		sb.append("{");
		sb.append("\"name\":\"hyuk\"");
		sb.append("}");
        
        //sb에 담겨진 표기는, 실제 JSON 객체는 아니므로, 파싱단계를 거쳐 JSON 객체로 전환해야 한다!!
		//JSON파서는 자바 자체적으로 지원하지 않으므로 외부 라이브러리를 이용하여 파싱업무를 시도하자!!
		//주로 무료 기반(오픈소스)의 외부 라이브러는 아파치 재단에서 운영되는 maven 사이트 이용하자!
		JSONParser jsonParser = new JSONParser();//구문을 분석하는 파서객체 생성
		
		try {
			JSONObject obj = (JSONObject)jsonParser.parse(sb.toString());//파싱시작!!
			//파싱이 완료된 이후부터는 더이상 문자열이 아닌, json 객체로 사용하면 된다!!
			//JSON은 키와 밸류의 형태!!!
			System.out.println(obj.get("name"));//get(키값)
		} catch (ParseException e) {
			e.printStackTrace();
		}
	}

JSONParser를 이용하여 파싱을 하여 JSONObject 객체로 반환받아서 JSON데이터의 키값을 이용하여 값을 얻어올 수 있다!!

위 코드의 출력결과

2) XML 파싱

XML 파싱은 JSON과 다르게 좀 더 복잡하다..

- jAVA에서 제공하는 SAXParser라는 추상 클래스를 제공한다.

- SAXParser는 SAXParserFactory의 newSAXParser()메서드를 이용하여 인스턴스를 얻을 수 있다.

- SAXParserFactory는 추상클래스로 SAXParserFactory의 static메서드인 newInstance()를 이용하여 인스턴스를 얻을 수 있다.

- SAXParser는 DefaultHandler를 상속받는 핸들러클래스를 재정의하여 파싱할 수 있다...

- 말만 들어도 복잡하다..

<?xml version="1.0" encoding="UTF-8"?>
<pets>
	<pet>
		<type>dog</type>
		<name>뽀미</name>
		<age>9</age>
		<gender>여</gender>
	</pet>
	<pet>
		<type>cat</type>
		<name>나비</name>
		<age>3</age>
		<gender>여</gender>
	</pet>
</pets>

이러한 XML파일이 있다. 파싱을 하기 위해

/*
	XML의 모든 노드에서 이벤트가 발생할때마다 아래의 핸들러 객체의 메서드를 
	알맞게 오버라이드하면 됨.
*/
package day1113.xml;

import java.util.ArrayList;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class MyHandler extends DefaultHandler {
	ArrayList<Pet> petList;
	Pet pet;
	boolean isType;
	boolean isName;
	boolean isAge;
	boolean isGender;

	// 문서가 시작되면 호출됨
	@Override
	public void startDocument() throws SAXException {
		System.out.println("문서를 시작합니다");
	}

	// 여는 태그 만났을때 호출됨 <태그> (/가 없는 태그)
	@Override
	public void startElement(String uri, String localName, String tag, Attributes attributes) throws SAXException {
		// TODO Auto-generated method stub
		System.out.print("<" + tag + ">");

		// 여러 태그 중 pets를 만나면 ArrayList를 생성하자!!
		if (tag.equals("pets")) {
			petList = new ArrayList<Pet>();
		} else if (tag.equals("pet")) { // 하나의 pet 인스턴스 생성할 타임이다!!
			pet = new Pet();
		} else if (tag.equals("type")) { // ???
			// 시작 태그를 지금 지나가고 있음을 알려주자!!!
			isType = true;
		} else if (tag.equals("name")) { // ???
			isName = true;
		} else if (tag.equals("age")) { // ???
			isAge = true;
		} else if (tag.equals("gender")) { // ???
			isGender = true;
		}

	}

	// 태그와 태그사이의 데이터를 만났을 때 호출
	@Override
	public void characters(char[] ch, int start, int length) throws SAXException {
		String data = new String(ch, start, length);
		System.out.print(data);
		if(isType) {
			pet.setType(data);			
		}else if(isName) {
			pet.setName(data);
		}else if(isAge) {
			pet.setAge(Integer.parseInt(data));
		}else if(isGender) {
			pet.setGender(data);
		}
	}

	// 닫는 태그를 만났을 때
	@Override
	public void endElement(String uri, String localName, String tag) throws SAXException {
		System.out.print("</" + tag + ">");
		
		if (tag.equals("pet")) { // 이 시점에 하나의 Pet이 완성된 시점이므로, 리스트에 담아두자!!
			petList.add(pet);
		} else if (tag.equals("type")) { // ???
			// 실행부가 지나가고 있는 위치를 알려주는 모든 논리값들을 다시 초기화!!
			isType = false;
		} else if (tag.equals("name")) { // ???
			// 실행부가 지나가고 있는 위치를 알려주는 모든 논리값들을 다시 초기화
			isName = false;
		} else if (tag.equals("age")) { // ???
			// 실행부가 지나가고 있는 위치를 알려주는 모든 논리값들을 다시 초기화
			isAge = false;
		} else if (tag.equals("gender")) { // ???
			// 실행부가 지나가고 있는 위치를 알려주는 모든 논리값들을 다시 초기화
			isGender = false;
		}
	}

	// 문서가 끝날 때
	@Override
	public void endDocument() throws SAXException {
		System.out.println("문서를 종료합니다");
		System.out.println("결과 보고서 : 총 " + petList.size() + "가 존재합니다.");
		for(Pet pet : petList) {
			System.out.println("type : " + pet.getType());
			System.out.println("name : " + pet.getName());
			System.out.println("age : " + pet.getAge());
			System.out.println("gender : " + pet.getGender());
			System.out.println("-------------------------------------------");
		}
	}
}

startDocument 메서드는 문서시작 시 호출되는 메서드
startElement 메서드는 열린태그를 만났을 시 호출되는 메서드
characters 메서드는 태그안의 데이터를 만났을 시 호출되는 메서드
endElement 메서드는 닫는태그를 만났을 시 호출되는 메서드 
endDocument 메서드는 문서 종료 시 호출되는 메서드

위 코드를 보면 어떤 형식으로 진행되는지 이해할 수 있을 것이다..

 

아래는 재정의한 핸들러를 사용하여 xml을 파싱하는 코드)

/*
 * java로 xml를 파싱하는 방법은 크게 2가지 있다.
 * 1)DOM 방식 - html과 같은 원리...
 * 						즉, 모든 태그마다 1:1대응하는 DOM객체를 메모리에 생성해놓고 프로그래밍언어에서 필요한 객체를 접근하는 방식
 * 						예) javascript - DOM
 * 						무거운 DOM객체가 메모리에 부하를 일으킬 수 있다.. 특히 메모리크기가 pc에 비해 상대적으로 작은 디바이스의 경우 DOM방식은 적절치못하다!!
 * 2)SAX 방식 - xml문서를 이루는 엘리먼트, 텍스트 등의 모든 노드에 대한 이벤트를 발생시켜주는 방식
 * 					따라서 개발자는 적절한 자바의 객체를 메모리에 올려, xml을 대신하여 데이터를 사용하면 된다!!
 * 
*/
package day1113.xml;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.SAXException;

public class XMLParseApp {
	// 실행중인 자바프로세스가 파일에 접근하기 위해서는 파일입력스트림 계열이 필요하다!
	FileInputStream fis;
	InputStreamReader reader;
	BufferedReader buffr;
	File file;
	URL url;
	URI uri;
	
	public XMLParseApp() {
		url = this.getClass().getClassLoader().getResource("res/pets.xml");
		try {
			uri = url.toURI(); // File 클래스의 생성자에서는 URL이 아닌 URI를 원하므로, 변환하자!
			fis = new FileInputStream(file = new File(uri)); //스트림얻기!! 현재 1byte씩얻는상태
			parseData(); //파싱시작!!
			
		} catch (URISyntaxException e) {
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} finally {
			if(fis!=null) {
				try {
					fis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	//xml파싱해보자!!
	public void parseData() {
		//SAX방식의 파서는 SAXParserFactory 객체로부터 얻는다.
		SAXParserFactory factory; 
		factory = SAXParserFactory.newInstance(); //static메서드를 이용하여 인스턴스얻음
		try {
			SAXParser saxParser=factory.newSAXParser();//Factory로부터 파서의 인스턴스를 얻을 수 있다..
			saxParser.parse(fis, new MyHandler());
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public void readTest() {
		try {
			
			//육안으로 확인할 때 한글이 깨질 수 있으므로, Reader로 업그레이드하자
			reader = new InputStreamReader(fis); //문자로 얻는 걸로 업그레이드
			buffr = new BufferedReader(reader);// 한 줄씩 얻는 걸로 업그레이드
			//한문자씩 읽어들이면 너무 시간이 오래걸리므로, 한줄씩 읽어 들이기
			
			//파싱은 나중에하고, 먼저 xml을 제대로 스트림으로 읽어들일 수 있는 지 체크
			String data = null;
			while(true) {
				data = buffr.readLine();
				if(data==null) break;
				System.out.println(data);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}

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

 

Pet클래스(VO)

/*
	한마리의 반려동물을 담게 될 VO 클래스
	VO란? Value Object의 약자로서, [로직 작성이 목적이 아닌 단지 데이터만을 보관할 용도로 사용되는 객체]를 가리키는 애플리케이션 설계 용어 중 하나!
*/
package day1113.xml;

public class Pet {
	private String type;
	private String name;
	private int age;
	private String gender;

	public String getType() {
		return type;
	}
	public void setType(String type) {
		this.type = type;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getGender() {
		return gender;
	}
	public void setGender(String gender) {
		this.gender = gender;
	}
}

위 코드의 출력결과

지금봐도 너무 어렵다... 여러번 봐야할 것 같다.. ㅠ

Echo System?

  • 자바의 소켓을 이용하여 채팅(멀티캐스팅)을 구현하기 위한 기초적인 학습!
  • 단순히, 내가 보낸 메시지를 내가 받아서 콘솔에 메아리치는(Echo) 프로그램 
  • 클라이언트는 Telnet을 사용

1) Telnet 기능 켜기

- 윈도우사용자의 경우, 제어판으로 들어가 Windows 기능 켜기/끄기를 눌러 Telnet 클라이언트를 체크한다음 확인을 눌러준다.

 

2) 서버 구현

  

  • 자신이 원하는 클래스명으로 클래스 생성
  • 하나의 클래스에서 실행을 하기 위해 main메서드 생성
  • ServerSocket 인스턴스를 사용하기 위해 멤버변수 생성
  • 포트번호는 1~1024번까지는 이미 시스템이 점유하므로 점유불가! 

 

 

 

 

 

 

 

 

 

 

  • ServerSocket은 서버를 열어놓고 accept()메서드를 이용하여 접속자가 들어올 때까지 Block상태로 대기한다.

 

 

 

 

 

 

  • ServerSocket으로부터 accpet()된 요청의 클라이언트와 메시지를 주고받기 위해선 Socket객체를 반환받아야한다.
  • Socket객체로부터 InputStream을 반환받아 클라이언트로부터 보낸 메시지를 콘솔창에 뿌릴 수 있다.

 

 

 

 

 

 

package day1109.echo;

import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class EchoServer2 {
	ServerSocket server;
	int port = 9999;

	public EchoServer2() {
		try {
			server = new ServerSocket(port);
			System.out.println("서버 소켓 생성완료!");
			
			Socket socket = server.accept();
			System.out.println("접속자 발견!");
			
			//반환받은 소켓을 이용하면, 현재 접속자에 대한 정보를 구할 수 있다.
			InetAddress inet = server.getInetAddress();
			String ip = inet.getHostAddress();
			System.out.println(ip);
			
			//클라이언트가 보낸 메시지 받기!! 
			//(메시지를 받는 것은 실행중인 프로그램으로 데이터가 들어오는 것이므로
			//입력 스트림으로처리해야한다!!)
			//소켓으로부터 스트림을 뽑아낼 수 있다!
			InputStream is =socket.getInputStream();//바이트기반(한글깨짐, 영문만)
			
			int data=1;
			while(data!=10) {
				System.out.print((char)data);//1byte읽어들임...
			}
			socket.close();
			server.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

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

cf. ServerSocket과 Socket의 차이는? 

ServerSocket : 말그대로 서버 프로그램에서만 사용하는 소켓이다. 서버소켓은 클라이언트로부터 연결 요청이 오기를 기다렸다가 연결 요청이 들어오면 클라이언트와 연결을 맺고 다른 소켓을 만드는 일을 한다.

Socket : 서버에 접속하기 위한 클라이언트를 구현는 사용하는 클래스

 

'프로그래밍 > Java' 카테고리의 다른 글

java - mail 보내기  (0) 2021.01.06
싱글톤 패턴 알아보기  (0) 2020.12.14
JavaFX - 개발환경 구축 및 생명주기  (0) 2020.11.23
Java - JSON & XML 파싱  (0) 2020.11.17
Java - JDBC(Java DataBase Connectiviy) 사용법  (0) 2020.11.05

JDBC란?

자바에서는 데이터베이스 연동하는 기술을 가리켜 JDBC(Java DataBase Connectiviy)라고 하며,

Java.sql 패키지에서 API가 지원된다!

연동 절차

1) DB기종에 알맞는 드라이버를 로드 (oracle용, mysql용, mssql용.. 각각 jar가 필요)
2) 접속
3) 원하는 쿼리 수행
4) 접속해제 (특히, 스트림 및 DB는 사용 후 반드시 해제하자!!!)

1) DB기종에 알맞는 드라이버를 로드 (oracle용, mysql용, mssql용.. 각각 jar가 필요)

- 오라클일 경우

오라클을 설치한 폴더로 찾아가 .jar파일을 가져온다

ex) oracle\product\11.2.0\server\jdbc\lib

 

자신의 java 버전에 따라 가져와서 사용한다! (나는 6을 사용했다)

jar파일을 사용하고 있는 프로젝트의 추가를 해준다!

 

- MySQL(MariaDB)일 경우

MavenRepository에 들어가서 jdbc를 검색하여 .jar파일로 다운받는다!

그 다음은 , 오라클과 다를게 없다~

 

이제 코드로 가서, Class.forName() 메소드를 이용하여 드라이버를 로드한다!

Class.forName("oracle.jdbc.driver.OracleDriver");//오라클의 경우
Class.forName("com.mysql.cj.jdbc.Driver");//MySQL의 경우

2) 접속

DriverManger(DBMS에 접속하여 Connection 인스턴스받아주는 클래스)를 이용하여 Conncection(접속된 데이터베이스의 정보를 가지고 있는 인터페이스) 인터페이스의 인스턴스를 반환받자!

Connection con=null;	
 			//jdbc:DBMS기종:방식:ip주소:포트번호:기기의 DBMS설치명
String url="jdbc:oracle:thin:@localhost:1521:XE"; //Oracle 경우
			//jdbc:DBMS기종:ip주소:(포트번호):database명
String url = "jdbc:mysql://localhost:/exdatabase"; //MySQL 경우
String user="";
String password="";
con=DriverManager.getConnection(url, user, password); //접속시도!!

3) 원하는 쿼리 실행

- SELECT의 경우

PreparedStatement pstmt; // 쿼리문 수행 객체, 인터페이스이므로 new로 생성하는 것이 아니라
// 접속객체인 Connection 객체로부터 인스턴스를 얻올 수 있다.
ResultSet rs;// select 쿼리문 수행결과에 의해 표가 반환되는데, 이떄 이 표를 담는 객체
String sql = "select * from emp";

pstmt = con.prepareStatement(sql); // Connection객체로부터 PerparedStatement인스턴스얻기
rs = pstmt.executeQuery();// select문의 경우엔 executeQuery() 이용해야한다..
//rs에는 표가 들어있다!! 따라서 원하는 레코드로 커서를 옮기자!!
            
while(rs.next()) { //데이터가 존재하면, 한칸 전진 후 true까지 반환
	rs.getString("컬럼명"); //테이블의 컬럼명을 통해 가져올 수 있다
    rs.getInt("컬럼명2") //반환받는 데이터의 자료형에 따라 메서드가 다르다!
}

- INSERT, UPDATE, DELETE의 경우

  • INSERT의 경우의 성공 시 1, 실패 시 0 
  • UPDATE, DELETE의 경우엔 성공 시 UPDATE, DELETE된 행들의 수만큼, 실패 시 0
PreparedStatement pstmt; // 쿼리문 수행 객체, 인터페이스이므로 new로 생성하는 것이 아니라
// 접속객체인 Connection 객체로부터 인스턴스를 얻올 수 있다.
ResultSet rs;// select 쿼리문 수행결과에 의해 표가 반환되는데, 이떄 이 표를 담는 객체
String sql = "select * from emp";

pstmt = con.prepareStatement(sql); // Connection객체로부터 PerparedStatement인스턴스얻기
int result = pstmt.executeUpdate();//DML(insert, update, delete) 쿼리 실행 시 이 메서드(executeUpdate())를 사용함
if(result!=1){
System.out.println("insert 실패");
}else{
System.out.println("insert 성공");
}

4) 접속해제 (특히, 스트림 및 DB는 사용 후 반드시 해제하자!!!) 

if(rs!=null) {
  try {
    	rs.close();
    	System.out.println("rs 연결해제");
  	} catch (SQLException e1) {
    	e1.printStackTrace();
  	}
  }
if(pstmt!=null) {
  try {
    	pstmt.close();
    	System.out.println("pstmt 연결해제");
    } catch (SQLException e1) {
    	e1.printStackTrace();
    }
  }
if(con!=null) {
	try {
  	con.close();
  	System.out.println("con 연결해제");
  } catch (SQLException e1) {
 	 e1.printStackTrace();
  }
}

원하는 쿼리 실행한 뒤에, 반드시 !!!! 접속을 해제시켜줘야한다!! 

Database Server는 동시에 연결가능한 횟수에 제한을 두고 있기 때문에 사용하지 않을 때는 닫아야 한다!!

'프로그래밍 > Java' 카테고리의 다른 글

java - mail 보내기  (0) 2021.01.06
싱글톤 패턴 알아보기  (0) 2020.12.14
JavaFX - 개발환경 구축 및 생명주기  (0) 2020.11.23
Java - JSON & XML 파싱  (0) 2020.11.17
Java - 소켓프로그래밍 기초 Echo System  (0) 2020.11.09

+ Recent posts