Learn/KH정보교육원

[KH정보교육원 당산] 41일차(쇼핑몰 - 회원가입부분)

Dahoon06 2021. 5. 6. 14:22
728x90
반응형

필요한 데이터

회원 : 조회 / 삽입 / 수정 / 삭제

MemberMgr => DAO역할
MemberBean => DTO

상품 :  조회 / 삽입 / 수정 / 삭제 

ProductMg r=> DAO역할
ProductBean => DTO

주문 : 조회 / 삽입 / 수정 / 삭제 

OrderMgr => DAO역할
OrderBean => DTO

장바구니 : 조회 / 삽입 / 수정 / 삭제

CartMgr => DAO역할

 

** 기존에 사용했던 방식(DAO,DTO 하나를 만들어서 이 안에 모든 코드를 넣는다.)대로 하게되면 코드양이 너무 길어진다. 그렇기에 각각의 클래스를 따로 만들어서 사용한다.

 

기존에 했던 쇼핑몰 프로젝트에 데이터베이스 연동을 시켰다.

오늘은 기존에 했던 방식(사용자 1명)과 달리 여러명의 사용자가 접속할 수 있도록 여러개의 커넥션 객체를 생성 하여 사용하는 방법으로 만들었다. => 서브 클래스를 만들어서 Connection객체와 그 객체의 사용여부를 저장

 

DBConnectionMgr (순서대로) -> 서브클래스를 만든다.

서브 클래스)

class ConnectionObject{
	public Connection connection=null; //Connection 객체
	public boolean inuse=false;			// 사용여부
	
	public ConnectionObject(Connection c, boolean useFlag) {
		connection=c;
		inuse=useFlag;
	}

** 서브 클래스는 절대로 접근제한자를 가질 수 없다.

서브 클래스 -> Connection 객체와 그 객체의 사용여부를 저장할 수 있는 클래스 선언

 

 

.Connection / 자원해제

.Connection 객체를 미리 여러개를 만들어 놓고, 다수의 사용자가 접속했을때 사용되지 않는 Connection객체를 제공
.Connection 객체를 미리 여러개를 생성 => POOL

public class DBConnectionMgr_ {
	private Vector<ConnectionObject> connections=new Vector<ConnectionObject>(10); 
	private String driver="oracle.jdbc.driver.OracleDriver";
	private String url="jdbc:oracle:thin:@127.0.0.1:1521:XE";
	private String id="dahoon226";
	private String pw="ekgns00";
	
	private boolean _traceOn=false;   //사용가능 여부 확인
	private boolean initialize=false; // 객체 초기화 여부 확인
	private int _openConnections=50;  // 최대 가능 개수
	
    //DBConnectionMgr객체는 어플리케이션 내에서 단 하나만 존재할 수 있도록
	private static DBConnectionMgr_ instance=null;
	
	private DBConnectionMgr_() {
	} //기본 생성자

여러개의 Connection 객체들을 담을 수 있도록 Vector를 생성 ( 또는 ArrayList ) 초기값 10개

불린 변수를 선언하여 Connection객체를 사용가능한지 확인하고 초기화가 되었는지 확인한다.

 

공유 Connection 메소드)

public static DBConnectionMgr_ getInstance() {
		if(instance != null) {
			instance = new DBConnectionMgr_();
		}
		return instance;
	}

 

열려있는 Connection 객체 확인 메소드

/**  열려있는 Connection 객체의 수 **/
	public void setOpenConnectionCount(int count) {
		_openConnections=count;
	}

전역변수로 최대 50개까지 열리도록 선언 되어있다.

 

사용가능한 Connection 객체가 있는지 확인

/** 사용가능여부 설정 **/
	public void setEnablcTrace(boolean enable) {
		_traceOn=enable;
	}

Vector 객체 반환

/** Vector<ConnectionObject> connections를 반환 **/
	public Vector<ConnectionObject> getConnections(){
		
		return connections;
	}

현재 열려있는 Connection 객체가 몇개인지 확인

/** 현재 열려있는 Connection객체 **/
	public int getConnectionCount(){
		return connections.size();
	}

 

사용자 접속에 따라 새로운 Connection 객체 생성

/** 새로운 Connection 객체를 생성 **/
	private Connection createConnection() {
		Connection conn = null;
		try {
			if(id == null) {
				id = "";
			}
			if(pw == null) {
				pw = "";
			}
			//실무에서 자주 사용되는 방법
			Properties props = new Properties();
			props.put("user", id);
			props.put("password", pw);
			
			conn = DriverManager.getConnection(url,props);
			
		} catch(SQLException e) {
			System.err.println("CONNECT ERR "+e.getMessage());
		}
		return conn;
	}

if문은 다른 사용자가 접속을 시도 할 때 null값이 아닌 ""으로 초기화 시키기 위한 조건문이다.

Properties 객체를 생성하여 계정과 비밀번호를 담아 Connection객체를 생성할 때 사용할 수 있다.

 

모든 Connection객체를 자원해제할 때 

/** 모든 연결을 닫고(해제) 연결 pool(vector)내의 모든 내용을 삭제 **/
	public void finalize() {
		ConnectionObject conns = null;
		
		for(int i=0;i<connections.size();i++) {
			conns=(ConnectionObject)connections.elementAt(i);
			
			try {
            // Vector안의 ConnectionObject 내의 객체를 자원해제(close()) 
				conns.connection.close(); 
			} catch (SQLException e) {
				System.err.println("자원해제 실패"+e.getMessage());
			}
			conns = null;
		}
		connections.removeAllElements(); // Vector안의 모든 객체를 제거
	}

Vector에서 값을 꺼낼때는 Object타입으로 꺼내지기 때문에 타입 변환=>ConnectionObject

 

 

사용되지 않지만 연결이 되어있는 Connection객체 자원해제

/** 현재 사용되지 않지만 연결되어 있는 Connection 자원 해제 **/
	public void releaseFreeConneciont() {
		ConnectionObject conns = null;
		
		for(int i=0;i<connections.size();i++) {
			conns=(ConnectionObject)connections.elementAt(i);
			if(conns.inuse) {
				removeConnection(conns.connection);
			}
		}
	}

 

 

사용되지 않는 Connection 객체 제거

/** 사용되지 않는 Connection 객체 제거 **/
	public void removeConnection(Connection c) {
		if(c == null) {
			return;
		}
		ConnectionObject conns = null;
		for(int i=0;i<connections.size();i++) {
			conns=(ConnectionObject)connections.elementAt(i);
			
			if(c == conns.connection) {
				try {
					c.close();
					connections.removeElementAt(i);
				}catch (SQLException e) {
					System.err.println("CONNECTION REMOVE ERR "+e.getMessage());
				}
				break;
			}
		}
	}

 

finally에 if문을 넣고 일일이 나열해서 자원해제를 하지않고 자원 해제 메소드를 따로 만들어 호출함으로써 간단하게 자원해제 시킬 수 있다.

 

/** PreparedStatement, Statement, ResultSet 다양한 자원 해제 메소드 (Overloading) **/
	public void freeConnection(PreparedStatement pstmt, ResultSet rs) {
		try {
			if(rs != null) {
				rs.close();
			}
			if(pstmt != null) {
				pstmt.close();
			}
		}catch (SQLException e) {
			System.err.println("PreparedStatement, ResultSet CLOSE ERR"+e.getMessage());
		}
	}
public void freeConnection(Statement stmt, ResultSet rs) {
		try {
			if(rs != null) {
				rs.close();
			}
			if(stmt != null) {
				stmt.close();
			}
		}catch (SQLException e) {
			System.err.println("Statement, ResultSet CLOSE ERR"+e.getMessage());
		}
	}
public void freeConnection(PreparedStatement pstmt) {
		try {
			if(pstmt != null) {
				pstmt.close();
			}
		}catch (SQLException e) {
			System.err.println("PreparedStatement CLOSE ERR"+e.getMessage());
		}
	}
public void freeConnection(Statement stmt) {
		try {
			if(stmt != null) {
				stmt.close();
			}
		}catch (SQLException e) {
			System.err.println("Statement CLOSE ERR"+e.getMessage());
		}
	}

 

새로운(현재 사용하지 않거나) Connection 객체를 반환

public Connection getConnection() {
		Connection conn=null;
		ConnectionObject conns=null;
		
		if(initialize) {
			try {
				Class.forName(driver);
				conn = DriverManager.getConnection(url, id,pw);
			} catch (ClassNotFoundException e) {
				System.err.println("NEW DRIVER ERR"+e.getMessage());
			} catch(SQLException e) {
				System.err.println("NEW CONN ERR"+e.getMessage());
			}
			//연결이 잘못되었을 경우 상태값 저장
			boolean badConnection = false;
			
			for(int i=0;i<connections.size();i++) {
				conns = (ConnectionObject)connections.elementAt(i);
				
				//연결이 유효한지 테스트
				if(!conns.inuse) {
					try {
						badConnection=conns.connection.isClosed(); // 기존 Connection 객체가 닫혀있는지 확인
								
						if(!badConnection) {
							badConnection=(conns.connection.getWarnings() != null); //경고 발생
						}
					} catch(SQLException e) {
						System.err.println(e.getMessage());
					}
					//잘못연결
					if(badConnection) {
						connections.removeElementAt(i);
						continue;
					}
					conn=conns.connection;
					conns.inuse=true;
					break;
				} // 연결이 유효한지 테스트
				
				if(conn==null) {
					conn=createConnection();
					conns=new ConnectionObject(conn, true);
					connections.addElement(conns);
				}
			}
			
		}
		return conn;
	}

 

DB연결은 여기까지

DTO => 각 데이터 테이블에 해당하는 자바빈즈를 만들어 준다.

 


오늘 작업한 내용은 회원가입 부분이다.

기존에 회원가입 폼까지는 작성을 해둔 상태였고 오늘은 주소와 아이디 중복체크, 그리고 회원가입 완료시 데이터베이스에 해당 데이터가 추가되는 부분까지

회원가입 폼

 

 

아이디 체크 => idCheck 함수 호출

까지는 저번 시간에 했던 부분

 

우편번호에 zipCheck()함수 부분

기존 script.js에

function zipCheck(){
	url="zipSearch.jsp?search=n";
	window.open(url, "post", "width=500,height=300");
}

zipSearch.jsp에 search라는 파라미터명으로 값을 넘겨 준다.

 

zipSearch.jsp 코드가 좀 복잡하다...

 

 

검색

 

해당 데이터 

 

가입창으로 넘어온다.

 

회원가입 버튼을 누르게 되면 가입 하기전 입력한 데이터가 맞는지 확인하는 페이지로 이동하게 된다.

 

폼양식은 member.jsp (회원가입폼)을 사용하지만 값을 전달 받는 것이기 때문에 조금 달라진 부분이 있다.

 

회원가입 폼(member.jsp)에서 post방식으로 전달하기 때문에 먼저 인코딩을 해줘야한다.

회원가입에서 넘어온 값을 데이터베이스에 저장하기 위하여 자바빈즈를 임포트 시켜놓고

 

값을 넣어준다. => property="*" 사용하지않는 영역이 없기때문에 전체로 설정하여 값이 자리에 맞게 알아서 들어간다.

** 단, 데이터베이스 컬럼명, 빈즈 변수명, 파라미터명이 다 같아야 된다.

 

전달된 값을 꺼내기 위하여 value속성을 사용

** gender => <%=mBean.getGender().equals("1")?"cheked" : ""%>

넘어온 값에 맞게 체크

 

취미의 경우는 다중값선택 가능으로 배열로 선언 했기 때문에 배열로 선언

 

memberProc.jsp

회원가입 폼에서 틀린 값이 없으면 가입이 완료되면서 데이터베이스 값이 저장되고

아니라면 다시 입력해야한다.

 

 

 

simple_shopping_mall.V05.06(회원가입).war
5.92MB

 


수업시간에 이해를 못하고 코드만 따라 쳤더니

오류가 발생했을때 해결하는데 시간이 좀 걸렸다

 

블로그로 한번 더 정리하면서 이해할려고 했는데 코드 양도 그렇고 페이지도 많이 나눠져서 어떻게 정리를 해야할지 모르겠다..

 

정리하면서 조금 이해 되긴 했지만 완전히 내걸로 만든게 아니여서 걱정이다..

 

기사 시험도 다음주에 있고 세미 프로젝트도 해야하는데 큼...

728x90
반응형