-
백엔드 (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)에 서블릿 매핑 이름은 유일해야 함
- 동일한 이름이 존재할 경우 오류
'백엔드 프로그래밍' 카테고리의 다른 글
백엔드 (5) - JSP, EL, JSTL, Core 태그 (1) 2022.01.01 백엔드 (4) - JSP(Java Server Page) (1) 2021.12.30 백엔드 (3) - 서블릿 포워드, 쿠키와 세션 (0) 2021.12.29 백엔드(1) - Servlet (1) 2021.12.28