ON/Servlet

통합연결 실습하기

박도비 2023. 7. 5. 08:00
728x90

view                < - >      service       < - >    dao     < - > db

(HTML/ JSP)

 

 

DB에 있는 member 테이블에 대해서 웹 화면에 가지고 올 것 이다. 

 

📌 비쥬얼 스튜디오 코드 작성 

1. VIEW 만들기 

 

1. index.html 

<a href="member.html">5.통합테스트</a>
 
2. member.html
 
위에 만들어 놓은 주소로 이동하기 위해 HTML 한개 더 만든다. 
 
확인해보면 이렇게 화면에 출력되는데,
현재로서는 servlet를 만들지 않았기 때문에 링크를 눌러도 오류가 발생된다. 

! servelt : 자바 어플리케이션 코딩을 하듯 웹 브라우저용 출력 화면 (HTML)을 만드는 방법

그렇다면 자바로 가 servlect 을 만들러 가자. 

 

📌 자바 작성 

1.  servlet 만들기 

: 웹에서 어떤 요청이 왔어! 그럼 내가 가지고 있는 것 중에 뭐를 보여주지 ? 보여줘야하니까 controller에 작성해둔다 

근데 우리는 member/selectAll 에 대한 요청이 오면 보여줄 servlet을 만들어 준다!

package edu.kh.jsp.controller;

import java.io.IOException;
import java.util.List;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import edu.kh.jsp.common.JDBCTemplate;
import edu.kh.jsp.model.service.MemberService;
import edu.kh.jsp.model.vo.Member;

@WebServlet("/member/selectAll")
public class SelectAllServlet extends HttpServlet {

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

	}

}

1) Servlet 클래스 생성시 무조건 HTTPServlet 추상클래스 상속

2)doGet() / doPost()를 필요한 형태로 오버라이딩 진행 (a태그로 요청 받았으니 get방식)

3) 어떤 요청에 대해서 처리할지 주소 /member/selectAll  작성하고 어노테이션 ! 

4) 파라미터로 얻어올거 작성해야하지만 ! html에서 input 태그를 작성하지 않아서 얻어올 필요가 없다.

 

우리는 ! 데이터 베이스에 있는 member을 얻어 올것이다 ! 즉 JDBC를 해야한다. 

5) DB를 왔다갔다 하다보면 그에 따른 오류가 발생할 수 있기에 try-catch를 해준다.

6) 이전에 만들었던 JDBCTemplet을 이용해서 공통된 부분을 가져오기! 

 

- SQL 패키지 만들고 driver.xml 만들었다! 

   DB에 접속할 수 있도록 주소, 아이디, 비밀번호 잘 작성하기

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">

<!-- 마크업 언어 주석 -->

<properties>

   <!--  comment : properties XML 파일 설명 -->
   <comment>DB Connection data</comment>
   
   <!-- entry : Map의 Key, Value를 묶어서 부르는 명칭 -->
   <entry key="driver">oracle.jdbc.driver.OracleDriver</entry>   
   

   <entry key="url">jdbc:oracle:thin:@localhost:1521:xe</entry>
   <entry key="user">pja_member</entry>
   
   <entry key="password">member1234</entry>
   
   
</properties>

 

- JDBCTemplet 경로를 읽어져 오는 부분 변경하기. 

String filePath = JDBCTemplate.class.getResource("/edu/kh/jsp/sql/driver.xml").getPath();
prop.loadFromXML(new FileInputStream(filePath));

 

전체 코드 

package edu.kh.jsp.common;


import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Properties;

public class JDBCTemplate {

	/** DB연결, JDBC 자원 반환, 트렌잭션 제어 같은
	 * 반복적으로 사용되는 JDBC 관련 코드를 모아둔 클래스 
	 * 
	 * get connection () 메소드
	 * 
	 * close ( Connection | Statement | ResultSet) 메소드
	 * --> PropearedStatement 는 Statement 의 자식이므로 
	 *     매개변수 다형성으로 한번에 처리 
	 * 
	 * commit(Connection)
	 * rollback(Connection)
	 * 
	 * */
	
	// 필드 
	private static Connection conn; // 초기값 null
//	== private static Connection conn = null; 초기값 null 똑같음
	
	// 메소드 
	
	// DB 연결 정보를 담고 있는 Connection 객체 반환 메소드 
	public static Connection getConnection() { //반환형이 Connection이고 getConnection()이름을 가진다
		
		try {
			
			// 계속 공용으로 사용되는 conn 변수에 
			// 커넥션이 대입된적이 없거나 (null) 
			// 또는 이전 커넥션이 있었으나 닫힌 경우 
			// --> 새로운 커녁션이 필요한 상황!
			
			// 커넥션을 계속 닫고, 만들고... 닫고, 만들고 반복 
			// -> 프로그램 하나에 커넥션 1개만을 운용
			
			if(conn == null || conn.isClosed()) {
				
				Properties prop = new Properties();
				// K,V 모두 String인 MAP, XML 파일 입출력에 특화
				
				//driver.xml 파일 읽어오기 
				String filePath = JDBCTemplate.class.getResource("/edu/kh/jsp/sql/driver.xml").getPath();
				prop.loadFromXML(new FileInputStream(filePath));
				
				//커넥션 생성 준비 
				String driver = prop.getProperty("driver");
				
				String url = prop.getProperty("url");
				String user = prop.getProperty("user");
				String password = prop.getProperty("password");
				
				// 커넥션 생성 
				// 1) jdbc 드라이버 메모리 로드
				Class.forName(driver);
				
				// 2) DriverManger를 통해 커넥션생성 
				conn = DriverManager.getConnection(url,user,password);
				
				// 3) 트랜잭션 제어를 위한 자동 커밋 비활성화 
				conn.setAutoCommit(false);
				
			}
			
			
		} catch (Exception e) {
			e.printStackTrace();
		} 
		return conn;
	}
	
	// close() 메소드 작성
	
	// Conncection 반환 메소드,
	public static void close(Connection conn) {
		
		try {
			// 참조하는 Connection이 있으면서 닫혀있지 않은 경우
			if(conn != null&& !conn.isClosed()) {
				// conn.isClosed : 닫혀있으면true 
				conn.close();
			}
				
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	

	// Statement(부모) PreparedStatement(자식) 반환 메소드(다형성 적용)
	public static void close(Statement stmt) {
		
		try {
			// 참조하는 Statement가 있으면서 닫혀있지 않은 경우
			if(stmt != null && !stmt.isClosed()) {
				// stmt.isClosed : 닫혀있으면true 
				stmt.close();
			}
				
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	// ResultSet 반환 메소드
		public static void close(ResultSet rs) {
			
			try {
				// 참조하는 ResultSet가 있으면서 닫혀있지 않은 경우
				if(rs != null && !rs.isClosed()) {
					// rs.isClosed : 닫혀있으면true 
					rs.close();
				}
					
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
	
		// commit 반환 메소드
		public static void commit(Connection conn) {
			
			try {
				// 참조하는 Connection이 있으면서 닫혀있지 않은 경우
				if(conn != null && !conn.isClosed()) {
					// conn.isClosed : 닫혀있으면true 
					conn.commit();
				}
					
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
		// rollback 반환 메소드
		public static void rollback(Connection conn) {
			
			try {
				// 참조하는 Connection이 있으면서 닫혀있지 않은 경우
				if(conn != null && !conn.isClosed()) {
					// conn.isClosed : 닫혀있으면true 
					conn.rollback();
				}
					
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
}

이제, db에서 목록을 받아와야하니 servlet에서 세팅 진행하기. 

아까 만든 servlect에서 호출할 serivce 만들고  db에서 목록을 조회해야하니 list로 담아오기. 

package edu.kh.jsp.controller;

import java.io.IOException;
import java.util.List;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import edu.kh.jsp.common.JDBCTemplate;
import edu.kh.jsp.model.service.MemberService;
import edu.kh.jsp.model.vo.Member;

@WebServlet("/member/selectAll")
public class SelectAllServlet extends HttpServlet {

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

		// view <-> service <-> DAO <-> DB

		try {
			
			MemberService service = new MemberService();
			
			//회원 목록 조회 service 호출 후 결과 반환 (db접근)                    2
			List<Member>memberList = service.selectAll();
			
		
			
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

}

2. service 만들기 

1) 아까 만들어 놓은 JDBCTemplate 쓰기 위해서 import 로 받기 

import static edu.kh.jsp.common.JDBCTemplate.*;

 

2) dao 호출 할거니까 dao 필드에 작성하기 

private MemberDAO dao = new MemberDAO();

 

3) JDBC 갈 수 있도록 Connection 연결해주기 

 

package edu.kh.jsp.model.service;

//JDBCTemplate 쓰려고 import 받아오기 
import static edu.kh.jsp.common.JDBCTemplate.*;

import java.sql.Connection;
import java.util.List;

import edu.kh.jsp.model.dao.MemberDAO;
import edu.kh.jsp.model.vo.Member;

public class MemberService {
	
	private MemberDAO dao = new MemberDAO();


	/** 회원 목록 조회 
	 * @return memberList
	 * @throws Exception
	 */
	public List<Member> selectAll() throws Exception{
		
		//JDBCTemplate부터! 
		Connection conn = getConnection();
		
		List<Member> memberList = dao.selectAll(conn);
		
		close(conn);
		
		return memberList;
	}

}

3.  DAO 만들기 

1) 아까 만들어 놓은 JDBCTemplate 쓰기 위해서 import 로 받기 

import static edu.kh.jsp.common.JDBCTemplate.*;

 

2) 변수 선언

private Statement stmt = null;
private PreparedStatement pstmt = null;
private ResultSet rs = null;

 

3) 결과 저장할 변수 선언 

List<Member> memberList = new ArrayList<Member>();

 

4) DB 왔다갔다 하면 예외 발생할 것이니 Try- finally 회원 목록 조회 할 수 있도록  SQL 작성 

    버스 태워서 보내야하니까 'Statement 작성하기'

    버스에 결과 반환 받아서 가져와야하니까 ResultSet 작성하기 

    sql 에 대한 결과값을 하나씩 가져와야하니까 

    while(rs.next()) 작성해서 가져오기!

   

char 자료형 가져오는 방법 !  

char secessionFlag = rs.getString("SECESSION_FL").charAt(0); 

 

5) 

package edu.kh.jsp.model.dao;

//JDBCTemplate 쓰려고 import 받아오기 
import static edu.kh.jsp.common.JDBCTemplate.*;
import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import edu.kh.jsp.model.vo.Member;

public class MemberDAO {

	private Statement stmt = null;
	private PreparedStatement pstmt = null;
	private ResultSet rs = null;

	/**
	 * 회원 목록 조회
	 * 
	 * @param conn
	 * @return memberList
	 * @throws Exception
	 */
	public List<Member> selectAll(Connection conn) throws Exception {

		// 결과 저장할 변수 선언
		List<Member> memberList = new ArrayList<Member>();

		// DB랑 왔다갔다 할때 예외처리가 발생할 수 있으니 예외처리 해야함 catch는 안써도 됨! 위에서 예외처리 던진다고 함!
		try {
			String sql = "SELECT * FROM MEMBER ORDER BY 1";
			stmt = conn.createStatement();
			rs = stmt.executeQuery(sql);

			while (rs.next()) {
				int memberNo = rs.getInt("MEMBER_NO");
				String memberId = rs.getString("MEMER_ID");
				String memberPw = rs.getString("MEMBER_PW");
				String memberName = rs.getString("MEMBER_NM");
				// DB char 자료형이 없으니 String으로 받아 한글자만 얻어오기 !
				char memberGender = rs.getString("MEMBER_GENDER").charAt(0);
				Date enrollDate = rs.getDate("ENROLL_DATE");
				char secessionFlag = rs.getString("SECESSION_FL").charAt(0);

				Member member = new Member(memberNo, memberId, memberPw, memberName, memberGender, enrollDate,
						secessionFlag);
				
				memberList.add(member);
			}
		} finally {
			close(rs);
			close(stmt);
			
		}

		return memberList;
	}

}

4.  member 만들기

package edu.kh.jsp.model.vo;

import java.sql.Date;

public class Member {

	// 필드
	private int memberNo;
	private String memberId;
	private String memberPw;
	private String memberName;
	private char memberGender;
	private Date enrollDate;
	private char secessionFlag;

	public Member() {}

	
	
	public Member(int memberNo, String memberId, String memberPw, String memberName, char memberGender, Date enrollDate,
			char secessionFlag) {
		super();
		this.memberNo = memberNo;
		this.memberId = memberId;
		this.memberPw = memberPw;
		this.memberName = memberName;
		this.memberGender = memberGender;
		this.enrollDate = enrollDate;
		this.secessionFlag = secessionFlag;
	}



	public int getMemberNo() {
		return memberNo;
	}

	public void setMemberNo(int memberNo) {
		this.memberNo = memberNo;
	}

	public String getMemberId() {
		return memberId;
	}

	public void setMemberId(String memberId) {
		this.memberId = memberId;
	}

	public String getMemberPw() {
		return memberPw;
	}

	public void setMemberPw(String memberPw) {
		this.memberPw = memberPw;
	}

	public String getMemberName() {
		return memberName;
	}

	public void setMemberName(String memberName) {
		this.memberName = memberName;
	}

	public char getMemberGender() {
		return memberGender;
	}

	public void setMemberGender(char memberGender) {
		this.memberGender = memberGender;
	}

	public Date getEnrollDate() {
		return enrollDate;
	}

	public void setEnrollDate(Date enrollDate) {
		this.enrollDate = enrollDate;
	}

	public char getSecessionFlag() {
		return secessionFlag;
	}

	public void setSecessionFlag(char secessionFlag) {
		this.secessionFlag = secessionFlag;
	}



}

5. 위에 내용으로 반환 받아 화면을 만들거니까 JSP 경로 만들기!  위임해주기 

package edu.kh.jsp.controller;

import java.io.IOException;
import java.util.List;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import edu.kh.jsp.common.JDBCTemplate;
import edu.kh.jsp.model.service.MemberService;
import edu.kh.jsp.model.vo.Member;

@WebServlet("/member/selectAll")
public class SelectAllServlet extends HttpServlet {

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

		// view <-> service <-> DAO <-> DB

		try {
			
			MemberService service = new MemberService();
			
			//회원 목록 조회 service 호출 후 결과 반환 (db접근)                    
			List<Member>memberList = service.selectAll();
			
			//응답 화면을 만들 JSP로 요청 위임하기 --> vs코드 jsp 만들기!  
			String path = "/WEB-INF/views/selectAll.jsp";
			RequestDispatcher dispatcher =req.getRequestDispatcher(path);
			
			req.setAttribute("list", memberList);
			
			dispatcher.forward(req, resp);
			
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

}

 

6. 비쥬얼스튜디오 와서 JS 만들기 

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>회원목록조회</title>
</head>
<body>
    
</body>
</html>

 

7. 화면에 뿌려줄 JSP 만들어주기 

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>회원목록조회</title>
</head>
<body>
    
    <table border="1">
    
    	<thead>
    		<tr>
    			<th>회원번호</th>
    			<th>아이디</th>
    			<th>비밀번호</th>
    			<th>이름</th>
    			<th>성별</th>
    			<th>가입일</th>
    			<th>탈퇴여부</th>
    		</tr>
    	</thead>
    	
    	<tbody>
    		<c:forEach var="member" items="${ requestScope.list }">
    		<tr>
    			<td>${member.memberNo}</td>
    			<td>${member.memberId}</td>
    			<td>${member.memberPw}</td>
    			<td>${member.memberName}</td>
    			<td>${member.memberGender}</td>
    			<td>${member.enrollDate}</td>
    			<td>${member.secessionFlag}</td>
    		
    		</tr>
    			
    		</c:forEach>
    		
    	
    	</tbody>   	
    	
    	<!-- <tfoot></tfoot> -->
 
    
    
    
    
    </table>
    
    
</body>
</html>

최종 출력 화면 

728x90