반응형
반응형
package multi_thread.thread_synchronized;

public class Calculator {
	private int memory;
	
	public int getMemory() {
		return memory;
	}
	
	public synchronized void setMemory (int memory) {
		this.memory = memory;
		try {
			Thread.sleep(2000);
		}catch(InterruptedException e) {}
		System.out.println(Thread.currentThread().getName() + " : " + this.memory);
	}
	/* 임계구역 설정 안 한 메소드
	public void setMemory (int memory) {
		this.memory = memory;
		try {
			Thread.sleep(2000);
		}catch(InterruptedException e) {}
		System.out.println(Thread.currentThread().getName() + " : " + this.memory);
	}
	*/
}
package multi_thread.thread_synchronized;

public class User1 extends Thread{
	private Calculator calculator;
	
	public void setCalculator(Calculator calculator) {
		this.setName("User1");
		this.calculator = calculator;
	}
	
	public void run() {
		calculator.setMemory(100);
	}
}
package multi_thread.thread_synchronized;

public class User2 extends Thread{
	private Calculator calculator;
	
	public void setCalculator(Calculator calculator) {
		this.setName("User2");
		this.calculator = calculator;
	}
	
	public void run() {
		calculator.setMemory(50);
	}
}
package multi_thread.thread_synchronized;

public class MainThreadExample {

	public static void main(String[] args) {
		
		Calculator calculator = new Calculator();
		
		User1 user1 = new User1();
		user1.setCalculator(calculator);
		user1.start();
		
		User2 user2 = new User2();
		user2.setCalculator(calculator);
		user2.start();

	}

}

 

스레드가 2개가 실행 될 때 동시에 같은 객체(calculator)를 이용한다면 번갈아 실행 됩니다.

User1스레드에서 calculator 에서 memory 라는 변수의 값을 100으로 바꾸고

User2스레드로 넘어가서 User2스레드에서 memory 변수 값을 다시 50으로 바꿉니다. 

원래는 바로 User1스레드에서의 memory가 100일텐데 Thread.sleep이 2초로 설정되어 있기 때문에

User2스레드가 진행하면서 이미 memory값을 50으로 바꿨기 때문에 둘다 출력값이 50이 나오게 됩니다.

 

이러한 스레드가 사용 중인 객체다른 스레드가 변경할 수 없도록 하려면 잠금을 걸어서

다른 스레드가 사용할 수 없게 해야합니다. 그 코드의 영역을 임계 영역이라고 합니다.

 

자바는 임계 영역을 지정하기 위해 동기화메소드와 동기화 블록을 제공합니다.

동기화 메소드를 만드는 법synchronized를 붙이면 됩니다.

 

동기화 메소드인 setMemory는 임계영역이라서 한 번에 한 스레드만 실행할 수 있고 다른 스레드는 실행할 수 없게 됩니다.

 

반응형
반응형
package multi_thread;

import java.awt.Toolkit;

public class ThreadPriority {

	public static void main(String[] args) {
		
		// 방법1
		Thread thread = new BeepThread();
		thread.start();

		thread.setPriority(Thread.MAX_PRIORITY); // 우선순위 10
		thread.setPriority(Thread.NORM_PRIORITY); // 우선순위 5
		thread.setPriority(Thread.MIN_PRIORITY); // 우선순위 1
		
		// 방법2 (익명 객체를 이용한 방법)
		/*
		Thread thread2 = new Thread() {
			public void run() {
				Toolkit toolkit = Toolkit.getDefaultToolkit();
				for(int i = 0 ; i < 5 ; i++) {
					toolkit.beep();
					try {Thread.sleep(500);} catch(Exception e) {}
				}
			}
		};
		thread2.start();
		*/
		
		for (int i = 0 ; i < 5 ; i++) {
			System.out.println("띵");
			try {Thread.sleep(500);} catch(Exception e) {}
		}

	}

}

위는 저번에 했던 예제를 그냥 가져왔습니다. 이번 내용은 큰 실습내용이 없기 때문입니다.


멀티스레드가 병렬적으로 실행되는 거라고 했는데 실제로는 번갈아가면서 실행하는 작업입니다.

자바에서 스레드 스케줄링은 우선순위(Priority) 방식과 순환 할당 (Round-Robin) 방식을 사용합니다.
우선순위가 높은 스레드가 실행 상태를 더 많이 가져가게 되는 것이소
시간 할당량(Time slice)를 정해서 하나의 스레다가 정해진 시간만큼 실행 하고 다른 스레드를 실행하는 방식입니다.

thread.setPriorty(우선순위); 를 이용해 우선순위를 정해줄 수 있습니다.
1 ~ 10까지 값이 들어갑니다. 기본적으로 모든 스레드는 5 우선순위를 할당 받습니다.
1은 가장 낮고 10이 가장 높습니다.

우선순위는 최소한 5개 이상의 스레드가 실행 되어야 우선순위의 영향을 받습니다.

thread.setPriority(Thread.MAX_PRIORITY)
thread.setPriority(Thread.NORM_PRIORITY)
thread.setPriority(Thread.MIN_PRIORITY)

 

이런식으로 10 5 1이라는 숫자를 대신 넣을 수 있습니다.

MAX는 가장 큰 수라는 의미 10 NORM은 평균이라는 의미 5 MIN은 가장 적은 수라는 의미 1을 의미합니다.

반응형
반응형
package multi_thread;

public class SetAndGetThread extends Thread{
	public SetAndGetThread() {
		setName("ThreadA");
	}
	
	public void run() {
		for(int i = 0 ; i < 2 ; i++) {
			System.out.println(getName() + "가 출력한 내용");
		}
	}
}

생성자setName을 이용해 스레드 이름을 설정할 수 있습니다.

그리고 getName으로 스레드의 이름을 가져올 수 있습니다.

 

이번엔 귀찮아서 메인스레드는 안 만들었습니다.

반응형
반응형
package multi_thread;

import java.awt.Toolkit;

public class BeepThread extends Thread {
	@Override
	public void run() {
		Toolkit toolkit = Toolkit.getDefaultToolkit();
		for(int i = 0 ; i < 5 ; i++) {
			toolkit.beep();
			try {Thread.sleep(500);} catch(Exception e) {}
		}
	}
}
package multi_thread;

import java.awt.Toolkit;

public class BeepPrintExample2 {

	public static void main(String[] args) {

		// 기존 방법
        // Runnable beepTask = new BeepTask(); // Runnable 상속 받은 BeepTask 클래스
		// Thread thread = new Thread(beepTask);

		// 방법1 (Runnable 객체 선언 후 Injection 안 해줘도 된다.
		Thread thread = new BeepThread();
		thread.start();
        

		
		// 방법2 (익명 객체를 이용한 방법)
		/*
		Thread thread2 = new Thread() {
			public void run() {
				Toolkit toolkit = Toolkit.getDefaultToolkit();
				for(int i = 0 ; i < 5 ; i++) {
					toolkit.beep();
					try {Thread.sleep(500);} catch(Exception e) {}
				}
			}
		};
		thread2.start();
		*/
		
		for (int i = 0 ; i < 5 ; i++) {
			System.out.println("띵");
			try {Thread.sleep(500);} catch(Exception e) {}
		}

	}

}

Runnable을 이용하지 않고 Thread의 하위 클래스로 스레드를 정의하면서 작업 내용을 포함 시킬 수도 있습니다.

 

extends로 Thread를 받고 run() 안에 스레드 실행할 코드를 정의합니다.

아니면 저번에 한 거 처럼 익명객체로 이용해 클래스 생성하지 않고 사용할 수 있습니다.

 

Thread thread = new BeepThread();

 

Thread를 상속 받는 BeepThread하위 클래스 입니다.

큰 Thread에 담게 되는 것이죠 Runnable역할을 해주면서 코드를 더 줄일 수 있습니다.

 

반응형
반응형
package multi_thread;

import java.awt.Toolkit;

public class BeepTask implements Runnable{
	public void run() {
		Toolkit toolkit = Toolkit.getDefaultToolkit();
		for(int i = 0 ; i < 5 ; i++) {
			toolkit.beep();
			try {Thread.sleep(500);} catch(Exception e) {}
			}
		}
	}
package multi_thread;

import java.awt.Toolkit;

public class BeepPrintExample {

	public static void main(String[] args) {
		
		// 방법 1
		Runnable beepTask = new BeepTask(); // Runnable 상속 받은 BeepTask 클래스
		Thread thread = new Thread(beepTask);
		thread.start();

		// 방법 2 (익명 객체 이용)
		/* 
		Thread thread2 = new Thread(new Runnable() {
			@Override
			public void run() {
				Toolkit toolkit = Toolkit.getDefaultToolkit();
				for(int i = 0 ; i < 5 ; i++) {
					toolkit.beep();
					try {Thread.sleep(500);} catch(Exception e) {}
					}
				}
			});
		thread2.start();
		*/
		
		for (int i = 0 ; i < 5 ; i++) {
			System.out.println("띵");
			try {Thread.sleep(500);} catch(Exception e) {}
		}
		
		
	}
}

스레드하나를 실행시키는 역할을 하는 것을 의미합니다. 

(말이 하나지 100개의 업무를 한 사람이 하는 거라고 생각하시면 됩니다.)

(예를 들어 자바를 실행시키면 메인스레드만 돌아감)

 

멀티스레드란 여러개를 동시에 실행 시킬 수 있게 만들어서 병렬적으로 처리할 수 있는 것이죠

병렬적으로 처리하면 여러개의 일을 분담하니 효율적이겠죠?


메인 스레드가 작업스레드보다 먼저 종료되더라도

다른 스레드가 계속 실행중이라면 프로세스는 종료되지 않는 특징이 있습니다.

Runnable작업 스레드가 실행 할 수 있는 코드가지고 있는 객체라고 해서 붙여진 이름입니다.
인터페이스 타입이기 때문에 구현 객체를 만들어 대입해야한다. run()을 재정의해서 실행할 코드를 적어야합니다.

class Task implements Runnable{
	public void run(){
		실행할 자바코드
	}
}

이런 식이 기본 구조입니다. 

 

위에 예제는 컴퓨터에서 띵소리를 내게 하는 toolkit이라는 걸을 이용해 소리를 내면서

그와 동시에 for문을 이용해 띵이라는 걸 출력해보려고 합니다. 그러면 두개가 동시에 작동해야 겠죠?

 

public class BeepTask implements Runnable{
	public void run() {
		Toolkit toolkit = Toolkit.getDefaultToolkit();
		for(int i = 0 ; i < 5 ; i++) {
			toolkit.beep();
			try {Thread.sleep(500);} catch(Exception e) {}
			}
		}
	}

 

run안에 스레드 내용에는 toolkit.beep()이 0.5초의 간격을두고 5번 반복하게 끔 만들었습니다.

 

beepTask라는 객체를 만듭니다.

또한 Runnable내용을 실행시킬 스레드만듭니다.(thread)

그리고 Runnable 내용을 그 안에 넣습니다. ( Thread thread = new Thread(beepTask) ) 선언과 Runnable 내용 넣기

thread.start로 Thread를 실행시킵니다.

 

이러면 메인 Thread에서는 이걸 일 하고 다른 스레드에서는 컴퓨터에서 띵소리를 내게하는 일을 합니다. (병렬)

 

Runnable을 상속받는 클래스를 만들어서 쓰는 위에 방법과 그렇지 않고 바로 메인쓰레드에서 선언과 동시에

쓰는 익명 객체를 이용하는 방식이 있습니다.

익명 객체란 일회성이고 파일을 줄일 수 있는 장점이 있습니다. 자세한 건 나중에 포스팅하겠습니다.

 

Thread thread2 = new Thread (new Runnable() {
    @Override
    public void run() {
        스레드내용
    }
});

이러한 구조가 됩니다. Thread 매개변수에는 Runnable객체가 들어가야하는데 그걸 밑에 바로 정의시켜주는 것이죠

 

반응형
반응형
package error_throws;

public class Calculator {
	
	public static int add (int x, int y) throws 천을_넘는_예외, 음수가_되는_예외 {
		int result = x + y;
		if(result > 1000) {
			throw new 천을_넘는_예외();
			// throw new NullPointerException();
		}
		
		if(result < 0) {
			throw new 음수가_되는_예외();
		}
		return x + y;
	}
}
package error_throws;

public class 음수가_되는_예외 extends Exception {
	
	@Override
	public String getMessage() {
		return "입력 값이 음수인 오류가 발생했습니다.";
	}
	
}
package error_throws;

public class 천을_넘는_예외 extends Exception {
	
}​
package error_throws;

public class ErrorThrows {
	

	public static void main(String[] args) {
	
		Calculator calc = new Calculator();
		int result = 0;
		// result = Calculator.add(6, 4); 예외처리를 해줘야한다.
		try {
			result = Calculator.add(-6, 4);
			
		}catch(음수가_되는_예외 e) {
			System.out.println(e.getMessage());
			System.out.println("음수가 발생 되었습니다.");
		}catch(천을_넘는_예외 e) {
			
		}
		System.out.println("add : " + result);
	}
}

컴파일하기 전에 빨간줄이 그어지는 에러가 있고 그렇지 않은 것이 있는데요 만약 값이 제대로 안 넘어갈 경우

컴파일은 됐지만 NullPointException이라는 에러가 나오게 됩니다. 이러한 것들을 처리하기 위해서 저번에

try catch문을 썼는데요 그걸 이제 더 발전 시켜서 사용해보려고 합니다.

 

더하기 계산 기능을 넣으려고 합니다. 

	public static int add (int x, int y) throws 천을_넘는_예외, 음수가_되는_예외 {
		int result = x + y;
		if(result > 1000) {
			throw new 천을_넘는_예외();
			// throw new NullPointerException();
		}
		
		if(result < 0) {
			throw new 음수가_되는_예외();
		}
		return x + y;
	}

static으로 선언해 주세요 throws는 신경 쓰지마시고 저희가 임의로 에러를 만드려고 합니다.

1000이라는 합이 나오면 에러가 나오도록 그리고 합이 음수가 나오면 에러가 나오도록 하려고 합니다.

 

throw new라는 건 에러를 강제로 발생시키는 것입니다. 

여기에서 우리가 만든 걸 쓸 수도 원래 있는 에러를 넣을수도 있습니다.

throw new 천을_넘는_예외(); 이런식으로 하면 천을_넘는_예외를 만들라고 빨간줄이 그어집니다.

가져다대시고 class를 만든다를 클릭해서 만들어주세요

 

package error_throws;

public class 천을_넘는_예외 extends Exception {
	
}

이렇게 만들어지게 됩니다.

 

이 클래스에서는 에러를 처리해주는 역할을 해줍니다. 어떤식으로 메세지를 반환할지 등...

아무것도 안 적을 수도 있습니다.

 

그리고 throws를 추가해줘야합니다.

public static int add (int x, int y) throws 천을_넘는_예외, 음수가_되는_예외 {
....

throws란 무엇이냐면 던진다는 뜻인데 s라서 여러개를 던질 수 있게 한다는 의미입니다.

여기에선 2개를 넘기도록 되어있는데 이게 어디로 던지냐고한다면 해당 에러가 발생한다면

예를 들어 result가 1000이 넘어가서 예외가 발생하면 그걸

위에 천을_넘는_예외라는 클래스에서 처리하겠다는 의미입니다.

 

package error_throws;

public class 음수가_되는_예외 extends Exception {
	
	@Override
	public String getMessage() {
		return "입력 값이 음수인 오류가 발생했습니다.";
	}
	
}

또한 예외 메세지를 넘길 때 이러한 방법으로도 넘길 수 있습니다.

getMessage()를 오버라이드 해서 사용 가능합니다.

	try {
			result = Calculator.add(-6, 4);
			
		}catch(음수가_되는_예외 e) {
			System.out.println(e.getMessage());
			System.out.println("음수가 발생 되었습니다.");
		}catch(천을_넘는_예외 e) {
			
		}

getMessage()를 통해서 메세지를 출력할수도 있고

저번에 try catch에서 한 거처럼 catch문에다가 에러처리를 할 수도 있습니다.

반응형
반응형
package nesting_interface_class.nesting_interface;

public class Button {
	
	OnClickListener listener; // 인터페이스 타입 필드
	
	void setOnClickListner(OnClickListener listener) {
		this.listener = listener;
	}

	void touch() {
		listener.onClick();
	}
	
	interface OnClickListener{ // 중첩 인터페이스
		void onClick();
	}
}
package nesting_interface_class.nesting_interface;

public class CallListener implements Button.OnClickListener{
	
	@Override
	public void onClick() {
		System.out.println("전화를 겁니다.");
	}
}​
package nesting_interface_class.nesting_interface;

public class MessageListener implements Button.OnClickListener{

	@Override
	public void onClick() {
		System.out.println("메시지를 보냅니다.");
	}
}
package nesting_interface_class.nesting_interface;

public class ButtonExample {

	public static void main(String[] args) {
		
		Button btn = new Button();
		
		btn.setOnClickListner(new CallListener());
		btn.touch();
		
		btn.setOnClickListner(new MessageListener());
		btn.touch();
	}

}

 

클래스 내부안에 선언한 인터페이스
주로 UI프로그래밍에서 이벤트 처리할 목적으로 사용 됩니다.

Button 이라는 클래스 안에 OnClickListener라는 인터페이스가 있고 무조건 구현해야하는 onClick 메소드가 있습니다.

 

void touch() 와 void setOnClickListener는 listener라고 선언한 인터페이스 타입 필드에 값이 들어갔을 때 

사용할 메소드입니다.

 

btn.setOnClickListner(new CallListener());
btn.setOnClickListner(new MessageListener());

이렇게 인터페이스를 상속받은 클래스를 넣는 것입니다. 그러면 각각 클래스에서 구현한 interface부분 메소드

다르게 출력이 되는 것입니다.

 

 

반응형
반응형
package nesting_interface_class;

public class NestingClassA {
	int aField = 5;
	void aMethod1() {};
	
	static int aField2 = 10;
	static void aMethod2() {};
	
    class NestingClassB{
		NestingClassB() {} 	// 생성자
		int field1; // 인스턴스 필드
		// static int field2; // 정적 필드 사용불가(x)
		void method1() { System.out.println("중첩 클래스B");} // 인스턴스 메소드
		// static void method2() {} // 정적 메소드 사용불가(x)
		
		void method2() {
			class NestingClassD { // *로컬 클래스*
				NestingClassD() {} 	// 생성자
				int field1;	// 인스턴스 필드
				// static int field2;	// 정적 필드 사용불가(x)
				void method1() {System.out.println("로컬 클래스");} // 인스턴스 메소드
				// static void method2() {}	// 정적 메소드 사용불가(x)
			}
			NestingClassD  D = new NestingClassD();
			D.field1 =3 ;
			D.method1();
		}
		
		// 멤버 클래스 에서 사용 제한 가능 여부
		void callA () {
			aField = 10; // A 인스턴스 필드
			aMethod1();  // A 인스턴스 메소드
			
			aField2 = 10; // A 정적 필드
			aMethod2(); // A 정적 메소드
			

			NestingClassA.this.aMethod1();  // 바깥 클래스 메소드 참조 (A 인스턴스 메소드)
			NestingClassA.this.aField = 10; // 바깥 클래스 필드 참조 (A 인스턴스 필드)
			this.field1 = 10; // 현재 클래스의 필드 참조 (B 인스턴스 필드)
			this.method1();	// 현재 클래스의 메소드 참조 (B 인스턴스 메소드)
		}
	}
	
	static class NestingClassC{
		NestingClassC() {};  // 생성자
		int field1; // 인스턴스 필드
		static int field2; // 정적 필드
		void method1() {System.out.println("중첩 클래스C");}; // 인스턴스메소드
		static void method2() {System.out.println("static 중첩 클래스C");}; // 정적 메소드
		
		void callA () {
			// aField = 10; // A 인스턴스 필드 사용불가(x)
			// aMethod1(); // A 인스턴스 메소드 사용불가(x)
			
			aField2 = 10; // A 정적 필드
			aMethod2();	// A 정적 메소드
		}
	}
}
package nesting_interface_class;

public class NestingClass {

	public static void main(String[] args) {
		
		NestingClassA A = new NestingClassA();
		NestingClassA.NestingClassB B = A.new NestingClassB();				
		B.field1 = 3; // 인스턴스 필드
		B.method1(); // 인스턴스 메소드
		
		NestingClassA.NestingClassC C = new NestingClassA.NestingClassC();
		C.field1 =3; // 인스턴스 필드
		C.method1(); // 인스턴스 메소드
		NestingClassA.NestingClassC.field2 = 3; // 정적 필드
		NestingClassA.NestingClassC.method2(); // 정적 메소드
	}

}


클래스 내부에 선언한 클래스입니다.
두 클래스의 멤버들을 서로 쉽게 접근할 수 있다는 특징과
클래스를 감춤으로서 코드의 복잡성을 줄일 수 있다는 특징을 가지고 있습니다.

멤버클래스도 하나의 클래스이기 때문에 컴파일하면 바이트 코드파일이 별도로 생성됩니다.

 

NestingClassA A = new NestingClassA();
NestingClassA.NestingClassB B = A.new NestingClassB();				
B.field1 = 3; // 인스턴스 필드
B.method1(); // 인스턴스 메소드

먼저 A객체(바깥클래스)를 생성후 B객체(내부클래스)를 생성해야 합니다.

 

static class NestingClassC{
		NestingClassC() {};  // 생성자
		int field1; // 인스턴스 필드
		static int field2; // 정적 필드
		void method1() {System.out.println("중첩 클래스C");}; // 인스턴스메소드
		static void method2() {System.out.println("static 중첩 클래스C");}; // 정적 메소드
		
		void callA () {
			// aField = 10; // A 인스턴스 필드 사용불가(x)
			// aMethod1(); // A 인스턴스 메소드 사용불가(x)
			
			aField2 = 10; // A 정적 필드
			aMethod2(); // A 정적 메소드
		}

또한 내부 클래스를 static으로 만든 경우에만 static으로 필드나 메소드를 정의할 수 있습니다.

 

  class NestingClassB{
  	...
    void callA () {
        aField = 10; // A 인스턴스 필드
        aMethod1();  // A 인스턴스 메소드

        aField2 = 10; // A 정적 필드
        aMethod2(); // A 정적 메소드


        NestingClassA.this.aMethod1();  // 바깥 클래스 메소드 참조 (A 인스턴스 메소드)
        NestingClassA.this.aField = 10; // 바깥 클래스 필드 참조 (A 인스턴스 필드)
        this.field1 = 10; // 현재 클래스의 필드 참조 (B 인스턴스 필드)
        this.method1();	// 현재 클래스의 메소드 참조 (B 인스턴스 메소드)
	}
}

내부 클래스가 static이 아니라면 바깥 클래스가 정적으로 정의되든 안 되든 접근이 가능합니다.

 

또 다른 접근 방법은 this를 이용해 접근할 수 있습니다. (바깥클래스.this.필드 or 메소드)

현재 클래스의 필드나 메소드도 접근할 수 있습니다. (this.필드 or 메소드)

 

static class NestingClassC{
	....
	void callA () {
			// aField = 10; // A 인스턴스 필드 사용불가(x)
			// aMethod1(); // A 인스턴스 메소드 사용불가(x)
			
			aField2 = 10; // A 정적 필드
			aMethod2();	// A 정적 메소드
	}
}

내부 클래스 static 선언된 경우에는 static으로 선언된 필드 메소드만 접근이 가능합니다.

 

class NestingClassB{
		void method2() {
			class NestingClassD { // *로컬 클래스*
				NestingClassD() {} 	// 생성자
				int field1;	// 인스턴스 필드
				// static int field2;	// 정적 필드 사용불가(x)
				void method1() {System.out.println("로컬 클래스");} // 인스턴스 메소드
				// static void method2() {}	// 정적 메소드 사용불가(x)
			}
			NestingClassD  D = new NestingClassD();
			D.field1 =3 ;
			D.method1();
		}
}

내부 클래스안에 메소드 안에 클래스를 또 만들어서 사용할 수도 있습니다.

이걸 로컬 클래스라고 합니다.

반응형
반응형

 

이번에는 JSP파일에 DB를 연결하는 걸 해보도록 하겠습니다.

 

1. DB는 MySQL 쓸겁니다.

2. JDBC라는 DB랑 JSP랑 연결해주는 게 필요합니다.

 

https://dev.mysql.com/downloads/

 

MySQL :: MySQL Community Downloads

The world's most popular open source database

dev.mysql.com

다운 받아서 압축을 풀면 mysql-connector-java-버전명.jar이라는게 있는데 이걸 WEB-INF - lib넣어주세요

 

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>

    
<html>
<head><title>MEMBER 테이블 레코드 삽입</title></head>
<body>
<header>
	<%@ include file="topMenu.jsp" %>
</header>
<contents>
	<%@ include file="insertForm.jsp" %>
</contents>

</body>
</html>

join.jsp 입니다.

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1> <a href="join.jsp">[ 회원 가입 ]</a> <a href="memberList.jsp">[회원 목록]</a> </h1>
</body>
</html>

topMenu.jsp 입니다.

 

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<html>
<head><title>MEMBER 테이블 레코드 삽입</title></head>
<body>
<form action="useBeanInsert.jsp" method="post">
	<table border="1">
		<tr>
			<td>아이디</td>
			<td><input type="text" name="memberID" size="10"></td>
			<td>암호</td>
			<td><input type="text" name="password" size="10"></td>
		</tr>
		<tr>
			<td>이름</td>
			<td><input type="text" name="name" size="10"></td>
			<td>이메일</td>
			<td><input type="text" name="email" size="10"></td>
		</tr>
		<tr>
			<td colspan="4"><input type="submit" value="삽입"></td>
		</tr>
	</table>
</form>
</body>
</html>

insertForm.jsp 입니다.

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import = "com.member.*"%>

<jsp:useBean class = "com.member.RegisterBean" id= "regBean" scope ="session"/>
<jsp:setProperty property ="*" name = "regBean"/>
<jsp:useBean class = "com.member.RegisterMgr" id ="regMgr" scope = "session"/>

<% regMgr.insertMember(regBean);%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	
</body>
</html>

useBeanInsert.jsp 입니다.

 

2개의 자바빈을 사용할 건데 한 개는 Setter Getter로 이루어져있는 일반 POJO클래스입니다.

한 개는 DB와 연결해 상황에 맞는 쿼리문을 작동시킬 수 있게 만든 클래스입니다. 

여기에선 회원가입인 거이고 그에 대한 정보가 INSERT 쿼리문을 이용해 DB에 저장하는 방식입니다.

 

package com.member;

public class RegisterBean {

		private String memberID;
		private String password;
		private String name;
		private String email;
		
		public String getMemberID() {
			return memberID;
		}
		public void setMemberID(String memberID) {
			this.memberID = memberID;
		}
		
		public String getPassword() {
			return password;
		}
		public void setPassword(String password) {
			this.password = password;
		}
		public String getName() {
			return name;
		}
		public void setName(String name) {
			this.name = name;
		}
		public String getEmail() {
			return email;
		}
		public void setEmail(String email) {
			this.email = email;
		}
		

}
package com.member;

 import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.PreparedStatement;
import java.sql.Statement;
import java.util.Vector;


 
 public class RegisterMgr {
    
 	private final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
 	private final String JDBC_URL = "jdbc:mysql://:3307/jsp?characterEncoding=utf-8";
 	// 타임존 에러시
 	// jdbc:mysql://localhost:3306/DB이름?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC";
 	// jdbc:mysql://ip:port/testdb?characterEncoding=UTF-8&serverTimezone=UTC
 	private final String USER = "root";
 	private final String PASS = "1234";
 
 	public RegisterMgr() {
 	 try{
 	   Class.forName(JDBC_DRIVER);
 	   }catch(Exception e){
 	      System.out.println("Error : JDBC 드라이버 로딩 실패");
 	   }
     }//MemberMgr()
 
    public Vector getMemberList() {
	   Connection conn = null;
	   Statement stmt = null;
       ResultSet rs = null;
       Vector vecList = new Vector();
       try {
          conn = DriverManager.getConnection(JDBC_URL,USER,PASS);
          String strQuery = "select * from membertbl";
          stmt = conn.createStatement();
          rs = stmt.executeQuery(strQuery);
		  while (rs.next()) {
             RegisterBean regBean = new RegisterBean();
		 	 regBean.setMemberID (rs.getString("memberid"));
			 regBean.setPassword (rs.getString("password"));
 			 regBean.setName (rs.getString("name"));
 			 regBean.setEmail (rs.getString("email"));
             vecList.add(regBean);
          }
       } catch (Exception ex) {
          System.out.println("Exception" + ex);
       } finally {
          if(rs!=null)   try{rs.close();}  catch(SQLException e){}
		  if(stmt!=null) try{stmt.close();}catch(SQLException e){}
	      if(conn!=null) try{conn.close();}catch(SQLException e){}
       }
       return vecList;
    }
    public void insertMember(RegisterBean mem) {

 	   Connection conn = null;
 	   Statement stmt = null;
       ResultSet rs = null;
        try {
           conn = DriverManager.getConnection(JDBC_URL,USER,PASS);
           stmt =  conn.createStatement();
           stmt.executeUpdate("insert into membertbl values ("+ mem.getMemberID() +", "+ mem.getPassword() + ", "+ 
                   mem.getName() + "," + mem.getEmail() + ")" );

        } catch (Exception ex) {
           System.out.println("Exception" + ex);
        } finally {
           if(rs!=null)   try{rs.close();}  catch(SQLException e){}
 		  if(stmt!=null) try{stmt.close();}catch(SQLException e){}
 	      if(conn!=null) try{conn.close();}catch(SQLException e){}
        }
        return ;
     }
 }
private final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
private final String JDBC_URL = "jdbc:mysql://127.0.0.1:3307/jsp?characterEncoding=utf-8";

먼저 com.mysql.jdbc.Driver 저장해주시고

jdbc:mysql://아이피:포트번호/DB명?characterEncoding=utf-8 이렇게 작성하시면 됩니다.

 

저기에선 localhost:3306이나 127.0.0.1:3307 인 것이죠

 	private final String USER = "root";
 	private final String PASS = "1234";

아이디를 USER에 넣고 비밀번호를 PASS에 넣습니다.

 

Class.forName(JDBC_DRIVER); 는 jar파일을 이용하는 과정입니다.

 

지금은 삽입과정이니까 삽입부분만 보도록 하겠습니다.

 

public void insertMember(RegisterBean mem) {

 	   Connection conn = null;
 	   Statement stmt = null;
       ResultSet rs = null;
        try {
           conn = DriverManager.getConnection(JDBC_URL,USER,PASS);
           stmt =  conn.createStatement();
           stmt.executeUpdate("insert into membertbl values ("+ mem.getMemberID() +", "+ mem.getPassword() + ", "+ 
                   mem.getName() + "," + mem.getEmail() + ")" );

        } catch (Exception ex) {
           System.out.println("Exception" + ex);
        } finally {
           if(rs!=null)   try{rs.close();}  catch(SQLException e){}
 		  if(stmt!=null) try{stmt.close();}catch(SQLException e){}
 	      if(conn!=null) try{conn.close();}catch(SQLException e){}
        }
        return ;
     }

DriverManager.getConnection(내가 연결할 서버, 아이디, 비밀번호)로 내가 만든 서버와 연결합니다.

DriverManager.getConnection(JDBC_URL,USER,PASS);

 

DB연결객체.createStatement();

conn.createStatement();

 

쿼리문을 작성할 장소를 만들어 줍니다.

 

stmt.executeUpdate("insert into membertbl values ("+ mem.getMemberID() +", "+ mem.getPassword() + ", "+ 
                   mem.getName() + "," + mem.getEmail() + ")" );

 

쿼리문 작성장소.executeUpdate("쿼리문") 이런식으로 작성하면 됩니다.

getMemberID(), getMemberPassword(), getMemberName(), getMemberEmail()을 이용해

회원가입에 적은 값을 불러와서 저장하면 됩니다. 쿼리문은 " 내용 " 으로 작성되어야 하니까 

더블쿼테이션을 많이 씁니다. mem.getMeberID()의 경우는 자바코드이기 때문에 더블 쿼테이션을 뺀 것이고요

 

이제 회원목록을 누르면 DB에 저장된 걸 SELECT문으로 불러오도록 하겠습니다.

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<html>
<head><title>MEMBER 테이블 레코드 삽입</title></head>
<body>
<header>
	<%@ include file="topMenu.jsp" %>   
</header>
<contents>
	<%@ include file="viewMemberList.jsp"  %>
</contents>

</body>
</html>

memberList.jsp 입니다.

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import= "java.sql.* , java.util.*, com.member.*" %>
<jsp:useBean class="com.member.RegisterMgr" id="regMgr" scope="session" />

MEMBMER 테이블의 내용
<table width="100%" border="1">
<tr>
	<td>아이디</td><td>비번</td><td>이름</td><td>이메일</td>
</tr>
<%
        Vector vResult= regMgr.getMemberList();
		
		for(int i=0; i<vResult.size(); i++){
		RegisterBean rs = (RegisterBean)vResult.get(i);
		%>
		<tr> 
		<td align="center"><%= rs.getMemberID() %></td>
		<td align="center"><%= rs.getPassword() %></td>
		<td align="center"><%= rs.getName() %></td>
		<td align="center"><%= rs.getEmail()%></td>
		
		</tr>
		<%}%>


</table>

viewMemberList.jsp 입니다.

 

public Vector getMemberList() {
	   Connection conn = null;
	   Statement stmt = null;
       ResultSet rs = null;
       Vector vecList = new Vector();
       try {
          conn = DriverManager.getConnection(JDBC_URL,USER,PASS);
          String strQuery = "select * from membertbl";
          stmt = conn.createStatement();
          rs = stmt.executeQuery(strQuery);
		  while (rs.next()) {
             RegisterBean regBean = new RegisterBean();
		 	 regBean.setMemberID (rs.getString("memberid"));
			 regBean.setPassword (rs.getString("password"));
 			 regBean.setName (rs.getString("name"));
 			 regBean.setEmail (rs.getString("email"));
             vecList.add(regBean);
          }
       } catch (Exception ex) {
          System.out.println("Exception" + ex);
       } finally {
          if(rs!=null)   try{rs.close();}  catch(SQLException e){}
		  if(stmt!=null) try{stmt.close();}catch(SQLException e){}
	      if(conn!=null) try{conn.close();}catch(SQLException e){}
       }
       return vecList;

똑같이 getConnection을 이용해 서버와 쓸 DB를 연결합니다.

createStatement쿼리문을 쓸 공간을 만들어주세요

executeQuery(쿼리문)SELECT문을 안에 작성합니다.

 

executeQuery문SELECT문을 쓸 경우에만 쓰고 나머지는 executeUpdate를 씁니다.

 

그 결과를 ResultSet이라는 걸로 주게 되는게 테이블에 대한 정보가 들어있는 자료형입니다.

그리고 getString을 이용해 해당 필드명에 있는 값을 가져올 수 있습니다.

그걸 지금 Vector에다가 regBean객체를 넣는 것입니다. 왜냐하면 값이 여러개 일테니깐요

 

Vector vResult= regMgr.getMemberList();
		
		for(int i=0; i<vResult.size(); i++){
		RegisterBean rs = (RegisterBean)vResult.get(i);
		%>
		<tr> 
		<td align="center"><%= rs.getMemberID() %></td>
		<td align="center"><%= rs.getPassword() %></td>
		<td align="center"><%= rs.getName() %></td>
		<td align="center"><%= rs.getEmail()%></td>
		
		</tr>
<%}%>

Vector에 받은 값은 인덱스 하나에 RegisterBean형식이기 때문에 하나씩 받아서 각각 출력시키는 형태입니다.

 

반응형