[Servlet] 서블릿 비즈니스 로직 (DAO, VO)

sang·2024년 2월 1일

서블릿 비즈니스 처리

서블릿이 클라이언트로부터 받은 요청에 대해 작업을 수행하는 것
대부분 데이터베이스 연동 관련 작업
다른 서버와 연동하여 데이터 얻는 작업도 수행

대표적인 작업

  • 회원 등록 요청 처리
  • 로그인 요청 처리
  • 쇼핑몰 상품 주문 처리

서블릿 비즈니스 처리 과정

  1. 클라이언트의 요청
  2. 비즈니스 로직 처리
  3. 처리 결과 클라이언트에 반환


데이터베이스 연동

회원 정보 테이블 조회

  1. 웹 브라우저 -> MemberServlet: 회원정보 요청
  2. MemberServlet: MemberDAO 객체 생성
  3. listMembers() 호출 -> connDB() 호출: DB 연결
  4. SQL문 실행: 회원정보 조회
  5. MemberVO 속성 - 조회한 데이터 설정 -> ArrayList에 저장
  6. MemberServlet으로 ArrayList 반환
  7. ArrayList -> MemberVO -> 회원 정보 -> HTML 문자열 만들기
  • SQL: 회원 테이블 생성 및 회원 추가
  • MemberServlet: 요청 처리
  • MemberDAO: DB 연결 관리
  • MemberVO: 정보를 담을 객체

회원 정보 테이블 생성 및 데이터 추가 SQL

--회원 테이블 생성
create table t_member(
  id varchar2(10) primary key,
  pwd varchar2(10),
  name varchar2(50),
  email varchar2(50),
  joinDate date default sysdate
);

--회원 정보 추가
insert into t_member values('hong','1212','홍길동','hong@gmail.com',sysdate);
insert into t_member values('lee','1212','이순신','lee@test.com',sysdate);
insert into t_member values('kim','1212','김유신','kim@jweb.com',sysdate);
commit;

select * from t_member;

pro07/src/sec01/ex01/MemberServlet.java

package sec01.ex01;
...

@WebServlet("/member") // 주석 해제
protected class MemberServlet extends HttpServlet
{
  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    response.setContentType("text/html;charset=utf-8");
    PrintWriter out = response.getWriter();
    MemberDAO dao = new MemberDAO(); //MemberDAO 객체 생성
    List<MemberVO> list = dao.listMembers(); //회원정보 조회

    out.print("<html><body>");
    out.print("<table border=1><tr align='center' bgcolor='lightgreen'>");
    out.print("<td>아이디</td><td>비밀번호</td><td>이름</td><td>이메일</td><td>가입일</td></tr>");

    //조회한 회원정보 출력
    for (int i = 0; i < list.size(); i++) {
      MemberVO memberVO = list.get(i);
      String id = memberVO.getId();
      String pwd = memberVO.getPwd();
      String name = memberVO.getName();
      String email = memberVO.getEmail();
      Date joinDate = memberVO.getJoinDate();
      out.print("<tr><td>" + id + "</td><td>" + pwd + "</td><td>" + name + "</td><td>" + email + "</td><td>" + joinDate + "</td></tr>");
    }
    out.print("</table></body></html>");
  }
}

Statement

DBMS에 단순 문자열 전달
데이터베이스 연동 시 마다 DBMS에서 SQL문 컴파일 수행
느린 속도

pro07/src/sec01/ex01/MemberDAO.java
: Statement 인터페이스 이용

package sec01.ex01;
...

public class MemberDAO {
  private Statement stmt;
  private Connection con;
  ...
  
  public List<MemberVO> listMembers() {
    List<MemberVO> list = new ArrayList<MemberVO>();
    try {
      /* 데이터베이스 연결 및 조회 */
      connDB();
      String query = "select * from t_member ";
      System.out.println(query);
      ResultSet rs = stmt.executeQuery(query);
      
      while (rs.next()) {
        /* 조회한 칼럼 받아오기 */
        String id = rs.getString("id");
        String pwd = rs.getString("pwd");
        String name = rs.getString("name");
        String email = rs.getString("email");
        Date joinDate = rs.getDate("joinDate");
        
        /* MemberVO 객체 속성 설정 */
        MemberVO vo = new MemberVO();
        vo.setId(id);
        vo.setPwd(pwd);
        vo.setName(name);
        vo.setEmail(email);
        vo.setJoinDate(joinDate);
        
        list.add(vo); //ArrayList에 저장
      }
      
      rs.close();
      stmt.close();
      con.close();
    } catch (Exception e) {
      e.printStackTrace();
    }
    return list; //ArrayList 반환
  }
  
  private void connDB() {
    try {
      Class.forName(driver);
      System.out.println("Oracle 드라이버 로딩 성공");
      con = DriverManager.getConnection(url, user, pwd);
      System.out.println("Connection 생성 성공");
      stmt = con.createStatement();
      System.out.println("Statement 생성 성공");
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

PreparedStatement

DBMS에 미리 컴파일된 SQL문 전달
SQL문을 미리 컴파일하여 재사용 가능
빠른 반복 처리 가능
SQL문에 '?' 사용 가능

pro07/src/sec01/ex01/MemberDAO.java
: PreparedStatement 인터페이스 이용

package sec01.ex01;
...

public class MemberDAO {
  private PreparedStatement pstmt; //PreparedStatement 이용
  private Connection con;
  ...
  
  public List<MemberVO> listMembers() {
    List<MemberVO> list = new ArrayList<MemberVO>();
    try {
      /* 데이터베이스 연결 및 조회 */
      connDB();
      String query = "select * from t_member ";
      System.out.println("preparedStatement: " + query);
      /* PreparedStatement 객체 생성 및 SQL 실행 */
      pstmt = con.prepareStatement(query);
      ResultSet rs = pstmt.executeQuery(query);
      
      while (rs.next()) {
        /* 조회한 칼럼 받아오기 */
        String id = rs.getString("id");
        String pwd = rs.getString("pwd");
        String name = rs.getString("name");
        String email = rs.getString("email");
        Date joinDate = rs.getDate("joinDate");
        
        /* MemberVO 객체 속성 설정 */
        MemberVO vo = new MemberVO();
        vo.setId(id);
        vo.setPwd(pwd);
        vo.setName(name);
        vo.setEmail(email);
        vo.setJoinDate(joinDate);
        
        list.add(vo); //ArrayList에 저장
      }
      
      rs.close();
      stmt.close();
      con.close();
    } catch (Exception e) {
      e.printStackTrace();
    }
    return list; //ArrayList 반환
  }
  
  private void connDB() {
    try {
      Class.forName(driver);
      System.out.println("Oracle 드라이버 로딩 성공");
      con = DriverManager.getConnection(url, user, pwd);
      System.out.println("Connection 생성 성공");
      // Statement 생성 생략
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

pro07/src/sec01/ex01/MemberVO.java

package sec01.ex01;

import java.sql.Date;

public class MemberVO {
  /* 칼럼 이름과 동일한 자료형과 이름의 속성 */
  private String id;
  private String pwd;
  private String name;
  private String email;
  private Date joinDate;
 
  public MemberVO() {
    System.out.println("MemberVO 생성자 호출");
  }
  
  /* 각 속성별 getter/setter */
  public String getId() {
    return id;
  }
  public void setId(String id) {
    this.id = id;
  }
  public String getPwd() {
    return pwd;
  }
  public void setPwd(String pwd) {
    this.pwd = pwd;
  }
  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;
  }
  public Date getJoinDate() {
    return joinDate;
  }
  public void setJoinDate(Date joinDate) {
    this.joinDate = joinDate;
  }
}

커넥션 풀 ConnectionPool

미리 데이터베이스와 연결시킨 상태를 유지하는 기술
웹 애플리케이션 실행과 동시에 연동할 데이터베이스 연결을 미리 설정
오래 걸리는 데이터베이스 연결 작업의 반복을 줄임

커넥션 풀 동작 과정

  1. 톰캣 컨테이너 실행 & 응용 프로그램 실행
  2. ConnectionPool 객체 생성
  3. DBMS와 커넥션 객체 연결
  4. ConnectionPool 메소드 호출 -> 데이터베이스 연동

JNDI

커넥션풀 객체에 접근하는 방법
Key-value쌍 이용 (키를 이용해 자원 접근)

  • 사용처
    • 웹 브라우저 - 서블릿
    • 해시맵, 해시테이블
    • DNS 서버 요청 시 도메인 네임 - IP 주소

톰캣 DataSource 설정

  1. JDBC 드라이버 설치
  2. 커넥션풀 기능 관련 jar 파일 설치
  3. 연결할 데이터베이스 정보로 JNDI 설정
  4. DAO 클래스에서 데이터베이스 연동 -> JNDI 이름으로 연결
  • DBCP 라이브러리
    톰캣에서 커넥션풀 기능을 사용하기 위해 필요한 jar 압축 파일

context.xml

<Resource
    name="jdbc/oracle" // DataSource 접근명
    auth ="Container"
    type="javax.sql.DataSource"

    // 데이터베이스 연결에 필요한 값 4가지 설정
    driverClassName="oracle.jdbc.OracleDriver"
    url="jdbc:oracle:thin:@localhost:1521:XE"
    username="scott"
    password="tiger"
   
    maxActive="50"
    maxWait="-1" />

커넥션풀 데이터베이스 속성

driverClassName: 드라이버 클래스 이름
url: 주소, 포트번호, SID
user: 데이터베이스 접속 ID
password: 데이터베이스 접속 비밀번호

name: JNDI 이름
auth: 인증 주체
factory: 커넥션풀 클래스 생성 이름
maxActive: 동시 연결 커넥션 최대 수
maxIdle: 동시 idle 상태 대기 최대 수
maxWait: 새 연결 대기 최대 시간
type: 데이터베이스 종류별 DataSource



*자바 웹을 다루는 기술

profile
CS 메모장

0개의 댓글