ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 백엔드 (2) - 서블릿 로직 처리, 커넥션 풀
    백엔드 프로그래밍 2021. 12. 29. 23:43

    서블릿 응답 처리 예제

    -패키지 생성 : sec03
    -login2.html
    -LoginServlet2
    -매핑 이름 : /login2
    -연습문제 
    -newMember2.html
    -NewMemberServlet2.java
    -매핑 이름 : newMember2
    -폼 데이터 서버로 전송된 데이터를 다시 클라이언트로 응답해서 HTML 형식으로 출력
    아이디 :
    비밀번호:
      

    </body> </html>

     

    protected void doProcess(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // 클라이언트 요청 처리
    //클라이언트 -> 서버로 전송되는 데이터 인코딩
    request.setCharacterEncoding("utf-8");
    String id = request.getParameter("user_id");
    String pw = request.getParameter("user_pw");
    
    // 응답 처리
    // 서버 -> 클라이언트로 setContentType
    response.setContentType("text/html;charset=utf-8");
    
    //서버에서 클라이언트로 데이터 전송에 자바 I/O 스트림을 이용
    PrintWriter out = response.getWriter(); // cmd + shift + o = Import 해주기
    //HTML 문서 형식으로 데이터 전송
    out.println("<html><head></head><body>");
    out.println("아이디 : " + id + "<br>");
    out.println("비밀번호 : " + pw + "<br>");
    out.println("</body></html>");
    }
    }

    자바스크립트로 서블릿에 요청하기

    • DOM 사용
    /* 자바스크립트로 서블릿에 요청하기 */
       /* DOM 사용 */
       window.onload = function() {
    document.getElementById('frmLogin').onsubmit = function() {
    
    var id = document.getElementById('user_id');
    var pw = document.getElementById('user_pw');
    
    if(id.value == "" || pw.value == ""){
    alert("아이디와 비밀번호는 필수입니다.");
    }else {
    frmLogin.method = "post";
    frmLogin.action = "login3";
    frmLogin.submit();
    }
    
    }; // onsubmit 끝
    }; // window.onload 끝
    protected void doProcess(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    //클라이언트 -> 서버로 전송되는 데이터 인코딩
    request.setCharacterEncoding("utf-8");
    // 서버 -> 클라이언트로 setContentType
    response.setContentType("text/html;charset=utf-8");
    //서버에서 클라이언트로 데이터 전송에 자바 I/O 스트림을 이용
    PrintWriter out = response.getWriter();
    
    // 클라이언트 요청 처리
    String id = request.getParameter("user_id");
    String pw = request.getParameter("user_pw");
    
    // 응답 처리
    //HTML 문서 형식으로 데이터 전송
    out.println("<html><head></head><body>");
    out.println("아이디 : " + id + "<br>");
    out.println("비밀번호 : " + pw + "<br>");
    out.println("</body></html>");
    }
    • name 속성
    /* 자바스크립트로 서블릿에 요청하기 */
       /* name 속성 사용 */
       function fn_faildate(){
    var frmLogin = document.frmLogin;
    var id = frmLogin.user_id.value;
    var pw = frmLogin.user_pw.value;
    ​
    if(id == "" || pw == ""){
    alert("아이디와 비밀번호는 필수입니다.4");
    return false;
    }else {
    frmLogin.method = "post";
    frmLogin.action = "login3";
    frmLogin.submit();
    }
    }
    • jQuery 사용
    /* 자바스크립트로 서블릿에 요청하기 */
       /* jQuery 속성 사용 */
       $(document).ready(function(){
        $('#login').on('click',function(){
        var id = $('#user_id').val();
        var pw = $('#user_pw').val();
        
        if(id == "" || pw == ""){
    alert("아이디와 비밀번호는 필수입니다.55");
    return false;
    }else {
    //$('#frmLogin').attr('method','post').attr('action','login3').submit();
    $('#frmLogin').attr({
    method: "post",
    action: 'login3'
    }).submit(); 
    }  
        });    
       });

    서블릿 DB 연동

    DB 연동 : MySQL 사용
    -MySQL JDBC 드라이버 필요
    ​
    MySQL JDBC 드라이버 사용하기 위한 작업
    -이전에 다운로드 받은 mysql jdbc 드라이버 필요
    -mysql-connector-java-8.0.27.zip
    -mysql-connector-java-8.0.27.jar
    -압축 해제한 jar 파일을 복사해서 톰캣의 lib 폴더에 저장
    -mysql-connector-java-8.0.27.jar 복사해서 
    -C:\apache-tomcat-9.0.55\lib 폴더에 저장
    -Servlet01 프로젝트에서 Java Build Path에 라이브러리 추가
    -Servlet01 프로젝트에서 우클릭
    -Properties
    -Java Build Path
    -Libraries 탭에서 Module Path에서 [Add External JARs…] 선택
    -톰캣의 lib 폴더에서 mysql-connector-java-8.0.27.jar 찾아서 선택

    서블릿의 비즈니스 로직 처리 !!!

    • 데이터베이스 관련 작업
    • 다른 서버 연동해서 데이터 얻는 작업 등
      • 회원 등록 요청 처리 (DB에 회원 정보 저장)
      • 로그인 처리 (DB에 있는 회원 정보와 입력하여 전송된 로그인 정보가 일치하는지 검사)
      • 쇼핑몰 주문 처리 작업
    • 비즈니스 로직 처리 과정
      • 클라이언트로부터 요청
      • 데이터베이스 연동과 같은 비즈니스 로직 처리
      • 결과를 클라이언트에게 응답
      • HTML로 요청 -> 서블릿에서 요청 받음 -> DAO에서 비즈니스 로직 처리. 결과 반환 -> 서블릿에서 결과 받아서 클라이언트에게 응답 -> 클라이언트에서 결과 출력
    • 나중에 스프링에서 처리하는 과정
      • JSP로 요청 -> 컨트롤러가 요청 받음 -> DAO에서 비즈니스 로직 처리. 결과 반환 -> 컨트롤러가 결과 받아서 클라이언트에게 응답 -> 클라이언트에서 결과 출력

    DTO vs VO

    DTO (Data Transfer Object)

    • 데이터 저장 (전송) 담당 클래스
    • Controller, Service, View 등 계층간 데이터 교환을 위해 사용되는 객체
    • 비즈니스 로직을 갖지 않는 순수한 데이터 객체
    • getter, setter 메소드만 포함
    • 가변의 성격 (setter를 사용해서 데이터 변경 가능)

    VO (Value Object)

    • 데이터 저장 담당 클래스
    • DTO와 혼용해서 사용되지만
    • VO는 값(Value)를 위해 사용되는 객체로 불변(read only)의 속성
    • 보통 getter의 기능만 포함
    • 일반적으로 DTO와 같은 용도로 사용
    • 우리도 VO로 사용하지만 getter/setter 모두 포함시켜서 사용할 것임

    연습문제 DB 연동

    연습문제
    -패키지 생성 : sec05
    -BookVO
    -BookDAO
    -BookSelectServlet
    -도서 테이블 생성
    -도서번호
    -도서명
    -저자
    -가격
    -발행일
    -출판사번호
    -데이터 3개 입력

    BookVO

    public class MemberVO {
    private String id;
    private String pwd;
    private String name;
    private String email;
    private Date joinDate;
    
    source - Generate Constructor using fields
    ​
    source - Getters / Setters

    BookDAO

    // 회원 정보 조회 메소드 (전체 회원 정보 SELECT 해서 반환 : MemberVO 반환)
      // MemberVO를 여러 행 반환 : ArrayList<MemberVO>
      
      public ArrayList<BookVO> bookSelect() {
        Connection con = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
         
        ArrayList<BookVO> bookList = new ArrayList<BookVO>();
         
        try {
            con = connDB();
            
        String query = "select*from book";
        pstmt = con.prepareStatement(query);
        rs = pstmt.executeQuery();
            
        while(rs.next()) {   // 결과 세트에서 한 행씩 처리
            // 한 행(회원 1명당) 처리
            String no = rs.getString("bookno");
            String name = rs.getString("bookName");
            String author = rs.getString("bookAuthor");
            String price = rs.getString("bookPrice");
            String date = rs.getString("bookDate");
            String number = rs.getString("bookNumber");
            Date joinDate = rs.getDate("bookJoinDate");
            
            // 한 행 정보 가져와서 MemberVO에 저장 : setter 메소드 사용
            BookVO vo = new BookVO();
            vo.setNo(no);
            vo.setName(name);
            vo.setAuthor(author);
            vo.setPrice(price);
            vo.setDate(date);
            vo.setNumber(number);
            vo.setJoinDate(joinDate);
            
            // 각 MemberVO를 ArrayList에 추가(저장)
          bookList.add(vo);
            }   
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            
            try {
              rs.close();
              pstmt.close();
              con.close();
               
            } catch (Exception e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
            }
        }
        return bookList;
      }

    BookSelectServlet

    protected void doProcess(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // (1) 요청 받음
    //클라이언트 -> 서버로 전송되는 데이터 인코딩
    request.setCharacterEncoding("utf-8");
    // 서버 -> 클라이언트로 setContentType
    response.setContentType("text/html;charset=utf-8");
    //서버에서 클라이언트로 데이터 전송에 자바 I/O 스트림을 이용
    PrintWriter out = response.getWriter();
    
    // (2) 비즈니스 로직 처리 : DAO 호출하고 결과 받아옴
    BookDAO dao = new BookDAO();
    
    ArrayList<BookVO> bookList = dao.bookSelect();
    
    // (3) 응답 처리 : 클라이언트에게 결과 전송
    out.print("<html><head></head><body>");
    out.print("<table border=1><tr align='center' bgcolor='gold'>");
    out.print("<td>도서번호</td><td>도서명</td><td>저자</td>"
    + "<td>가격</td><td>발행일</td><td>출판사번호</td><td>데이터 입력 날짜</td></tr>");
    
    for(int i=0; i<bookList.size(); i++) {
    BookVO vo = (BookVO) bookList.get(i); // 형 변환(오브젝트 반환해서)
    String no = vo.getNo();
    String name = vo.getName();
    String author = vo.getAuthor();
    String price = vo.getPrice();
    String date = vo.getDate();
    String number = vo.getNumber();
    Date joinDate = vo.getJoinDate();
    ​
    // 한 행씩 출력
    out.print("<tr><td>" + no + "</td><td>" +
    name + "</td><td>" +
    author + "</td><td>" +
    price + "</td><td>" +
    date + "</td><td>" +
    number + "</td><td>" +
    joinDate + "</td></tr>");
    }
    out.print("</table></body></html>");
    }
    }

    커넥션 풀 (DBCP : DataBase Connection Pool)

    Connection Pool 등장 배경

    • 기본 데이터베이스 연동 방법의 문제점
    • 애플리케이션에서 데이터베이스 연결 과정에서 시간이 많이 소요
    • 해결 방안
    • 애플리케이션 실행 시 미리 Connection 객체를 생성해 놓고, 미리 데이터베이스 연결을 해 놓음
    • 애플리케이션은 데이터베이스 연동 작업 발생 시 이 미리 생성되어 있는 Connection 객체를 이용해서 작업

    커넥션 풀 (DBCP : DataBase Connection Pool)

    • 일정량의 DB Connection 객체를 Pool에 저장해 두고
    • 클라이언트 요청이 있을 때마다 가져다 사용하고 반환
    • 클라이언트에서 다수의 요청이 발생될 경우 요청 마다 DB Connection 객체를 생성하게 되면 데이터베이스에 부하가 발생하기 때문에 커넥션 풀 기법 이용
    • JDBC를 통하여 DB에 연결하게 되면 사용자의 요청이 있을 때마다 매번 드라이버를 로드하고 커넥션 객체를 생성하여 연결하고 종료 작업을 반복 - 비효율적

    커넥션 풀

    커넥션 풀의 장점

    • 풀 속에 미리 커넥션이 생성되어 있기 때문에 커넥션 생성하는데 시간이 걸리지 않음
    • 커넥션을 계속해서 사용하고 반환하기 때문에 재사용 가능하므로 많은 수의 커넥션을 만들지 않아도 됨
    • 매번 커넥션을 생성하고 해제하는데 시간이 소요되지 않으므로 애플리케이션 실행 속도가 빨라지고
    • 생성되는 커넥션 수를 제어하기 때문에 동시 접속자 수가 증가해도 애플리케이션이 쉽게 다운되지 않음
    • 접속 시 사용할 커넥션이 없으면 대기 상태로 전환되고,
    • 커넥션이 반환되면 대기 순서대로 커넥션 제공

    커넥션 풀 동작 과정

    • 톰캣 컨테이너를 실행한 후 응용프로그램 실행
    • 톰캣 컨테이너 실행 시 ConnectionPool 객체 생성
    • 생성된 커넥션객체는 DBMS와 미리 연결
    • 데이터베이스 연동 작업이 필요할 경우 응용 프로그램은 ConnectionPool에서 제공하는 메소드를 호출하여 연동

    커넥션 풀 사용법

    • context.xml 파일에 <Resource> 정보 추가
    • 톰캣 컨테이너가 데이터베이스 인증 작업 수행

    커넥션 풀 사용하여 DB 연결

    Server의 context.xml 파일 열고 <Resource> 태그 추가 <Resource name="jdbc/mysql" type="javax.sql.DataSource" auth="Container" driverClassName="com.mysql.cj.jdbc.Driver" url="jdbc:mysql://localhost:3306/servletdb?serverTimezone=UTC" username="root" password="1234" maxActive="50" maxWait="1000" />

    maxWait : 커넥션이 없을 때 대기 시간 (1000 : 1초)

    • 음수이면 무한 대기

    저장하고 Server 중단 Publish to the Server

    • Synchronize 수행
    • 현재 이클립스에 있는 context.xml에 입력한 것을 톰캣에 있는 context.xml과 일치시킴

    —---------------------------------------------------------------------------------- 커넥션 풀을 이용한 DB 연동 예제

    • sec06
    • MemberVO 복사
    • MemberDAO 복사해서 수정

    연습문제

    • HTML에서 입력한 회원 등록 정보를 DB에 저장
    • sec06에 추가
    • MemberDAO에 insertMember() 추가
    • MemberInsertServlet
    • join.html
    • 아이디
    • 비밀번호
    • 성명
    • 이메일 MemberDAO 클래스
    • memberSelect()
    • memberInsert()

    연습문제

    • sec07
    • 앞에서 한 Book 테이블 사용
    • 커넥션 풀 사용해서 DB 연동
    • BookVO
    • BookDAO
    • BookSelectServlet
    • BookInsertServlet
    • BookDeleteServlet
    • BookForm.html
    • index.html에 도서 정보 관리 추가
    • 도서 정보 조회
    • 도서 정보 등록

    주의!!

    • 오류 메시지
      • javax.naming.NamingException: Naming 컨텍스트가 이 클래스로더에 바인딩되지 않았습니다.
      • 서블릿 매핑 이름이 중복된 경우
    • 프로젝트(Servlet01)에 서블릿 매핑 이름은 유일해야 함
      • 동일한 이름이 존재할 경우 오류

    댓글

Designed by Tistory.