1. 개요
■ 지난 포스팅 : [JSP개발] 회원가입 - MVC 패턴 적용
MVC 패턴 적용 이후 이번에는 방문자 수를 보여주는 부분을 추가할 것이다. 방문자 수를 구하는 방법은 여러 가지가 있는데 여기에서는 세션과 DB를 사용할 것이다.
■ Java
VisitSessionListener.java : 방문자 수를 계산하는 클래스로 web.xml에 listener 등록을 해두었다.
VisitCountDAO.java : Visit 테이블의 DAO
■ JSP
Footer.jsp : 하단 영역 JSP를 추가 하였다. 여기에는 방문자 수가 표시된다.
2. 소스 코드
■ 테이블
먼저 테이블을 생성하고 아래의 쿼리를 실행시켜 몇 개의 데이터를 집어넣는다.
1 2 3 4 | <테이블 생성 쿼리> CREATE TABLE VISIT (V_DATE DATE NOT NULL); | cs |
1 2 3 | INSERT INTO VISIT (V_DATE) VALUES ( TO_DATE('10-06-2016','MM-DD-YYYY') ); INSERT INTO VISIT (V_DATE) VALUES ( TO_DATE('11-07-2016','MM-DD-YYYY') ); INSERT INTO VISIT (V_DATE) VALUES ( TO_DATE('11-08-2016','MM-DD-YYYY') ); | cs |
■ VisitSessionListener.java
22 ~ 24 줄
세션이 새로 생성될 경우 방문자 수를 처리하는 메서드인 execute( )를 실행시킨다.
33 ~ 37줄
방문자 수를 처리하는 부분이다. setTotalCount( )를 실행시켜 총방문자 수를 층가시킨다. 그리고 총방문자 수와 오늘 방문자 수를 가져온다.
39 ~ 43 줄
세션에 총방문자 수와 오늘 방문자 수를 담는다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | package jsp.visit.action; import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; import jsp.visit.model.VisitCountDAO; /** * 방문자 수를 계산하는 클래스<br> * web.xml에 listener 등록을 해두었다. 이렇게 할 경우 톰캣이 실행되면서 * 리스너가 실행된다. */ public class VisitSessionListener implements HttpSessionListener { @Override public void sessionCreated(HttpSessionEvent sessionEve) { // 세션이 새로 생성되면 execute() 실행한다. if(sessionEve.getSession().isNew()){ execute(sessionEve); } } private void execute(HttpSessionEvent sessionEve) { VisitCountDAO dao = VisitCountDAO.getInstance(); try { // 전체 방문자 수 증가 dao.setTotalCount(); // 총 방문자 수 int totalCount = dao.getTotalCount(); // 오늘 방문자 수 int todayCount = dao.getTodayCount(); HttpSession session = sessionEve.getSession(); // 세션에 방문자 수를 담는다. session.setAttribute("totalCount", totalCount); session.setAttribute("todayCount", todayCount); } catch (Exception e) { System.out.println("===== 방문자 카운터 오류 =====\n"); e.printStackTrace(); } } @Override public void sessionDestroyed(HttpSessionEvent arg0) {} } | cs |
■ web.xml
VisitSessionListener 클래스를 등록한다. <listener>에 패키지 경로를 모두 적어준다. 이렇게 listener로 등록을 해두면 톰캣이 실행될 때 listener가 실행된다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>JSP_create</display-name> <servlet> <description>Controller</description> <display-name>MemberController</display-name> <servlet-name>MemberController</servlet-name> <servlet-class>jsp.member.action.MemberController</servlet-class> </servlet> <servlet-mapping> <servlet-name>MemberController</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> <listener> <listener-class>jsp.visit.action.VisitSessionListener</listener-class> </listener> <resource-ref> <description>connection</description> <res-ref-name>jdbc/orcl</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> </resource-ref> </web-app> | cs |
■ VisitCountDAO.java
31 ~ 68 줄
총방문자 수를 증가시키는 부분이다. 테이블에 현재 날짜를 추가한다. 추가된 날짜의 수가 곧 방문자 수가 된다.
74 ~ 109 줄
총방문자 수를 구한다. COUNT(*)를 이용해 테이블에 저장된 레코드의 수를 읽어 온다. 읽어온 값이 총방문자 수이다.
115 ~ 149 줄
오늘 방문자 수를 가져온다. 쿼리의 Where 절을 살펴보자.
WHERE TO_DATE(V_DATE, 'YYYY-MM-DD') = TO_DATE(sysdate, 'YYYY-MM-DD')
TO_DATE(V_DATE, 'YYYY-MM-DD') 부분은 V_DATE 칼럼에 입력된 날짜의 포맷을 YYYY-MM-DD로 변경한다. TO_DATE(sysdate, 'YYYY-MM-DD') 에서는 sysdate, 즉 현재 날짜의 포맷을 YYYY-MM-DD로 변경한다. 이후 현재 날짜와 V_DATE 칼럼에 날짜 값을 비교하여 같은 경우만 출력한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | package jsp.visit.model; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import javax.naming.NamingException; import jsp.util.DBConnection; /** * Visit 테이블의 DAO<br> * 방문자 관련 처리를 한다. */ public class VisitCountDAO { private static VisitCountDAO instance; // 싱글톤 패턴 private VisitCountDAO(){} public static VisitCountDAO getInstance(){ if(instance==null) instance=new VisitCountDAO(); return instance; } /** * 총방문자수를 증가시킨다. */ public void setTotalCount() throws SQLException { Connection conn = null; PreparedStatement pstmt = null; try { // 쿼리생성 // 총 방문자수를 증가시키기 위해 테이블에 현재 날짜 값을 추가시킨다. StringBuffer sql = new StringBuffer(); sql.append("INSERT INTO VISIT (V_DATE) VALUES (sysdate)"); // 커넥션을 가져온다. conn = DBConnection.getConnection(); // 자동 커밋을 false로 한다. conn.setAutoCommit(false); pstmt = conn.prepareStatement(sql.toString()); // 쿼리 실행 pstmt.executeUpdate(); // 완료시 커밋 conn.commit(); } catch (ClassNotFoundException | NamingException | SQLException sqle) { // 오류시 롤백 conn.rollback(); throw new RuntimeException(sqle.getMessage()); } finally { // Connection, PreparedStatement를 닫는다. try{ if ( pstmt != null ){ pstmt.close(); pstmt=null; } if ( conn != null ){ conn.close(); conn=null; } }catch(Exception e){ throw new RuntimeException(e.getMessage()); } } } // end setTotalCount() /** * 총 방문자수를 가져온다. * @return totalCount : 총 방문자 수 */ public int getTotalCount() { Connection conn = null; PreparedStatement pstmt = null; ResultSet rs = null; int totalCount = 0; try { // 테이블의 테이터 수를 가져온다. // 데이터 수 = 총 방문자 수 StringBuffer sql = new StringBuffer(); sql.append("SELECT COUNT(*) AS TotalCnt FROM VISIT"); conn = DBConnection.getConnection(); pstmt = conn.prepareStatement(sql.toString()); rs = pstmt.executeQuery(); // 방문자 수를 변수에 담는다. if (rs.next()) totalCount = rs.getInt("TotalCnt"); return totalCount; } catch (Exception sqle) { throw new RuntimeException(sqle.getMessage()); } finally { // Connection, PreparedStatement를 닫는다. try{ if ( pstmt != null ){ pstmt.close(); pstmt=null; } if ( conn != null ){ conn.close(); conn=null; } }catch(Exception e){ throw new RuntimeException(e.getMessage()); } } } // end getTotalCount() /** * 오늘 방문자 수를 가져온다. * @return todayCount : 오늘 방문자 */ public int getTodayCount() { Connection conn = null; PreparedStatement pstmt = null; ResultSet rs = null; int todayCount = 0; try { StringBuffer sql = new StringBuffer(); sql.append("SELECT COUNT(*) AS TodayCnt FROM VISIT"); sql.append(" WHERE TO_DATE(V_DATE, 'YYYY-MM-DD') = TO_DATE(sysdate, 'YYYY-MM-DD')"); conn = DBConnection.getConnection(); pstmt = conn.prepareStatement(sql.toString()); rs = pstmt.executeQuery(); // 방문자 수를 변수에 담는다. if (rs.next()) todayCount = rs.getInt("TodayCnt"); return todayCount; } catch (Exception sqle) { throw new RuntimeException(sqle.getMessage()); } finally { // Connection, PreparedStatement를 닫는다. try{ if ( pstmt != null ){ pstmt.close(); pstmt=null; } if ( conn != null ){ conn.close(); conn=null; } }catch(Exception e){ throw new RuntimeException(e.getMessage()); } } }// end getTodayCount() } | cs |
■ MemberLogoutAction.java
19 줄
기존의 세션을 삭제하는 부분에서 세션에 담긴 sessionID 값만 삭제하도록 변경하였다. 세션을 삭제해 버리면 세션이 변경이 되어 로그아웃 시 방문자 수가 증가하게 된다. 그렇기에 sessionID 값만 삭제하도록 처리했다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | package jsp.member.action; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * 로그아웃 작업을 처리하는 Action 클래스 */ public class MemberLogoutAction implements Action { @Override public ActionForward execute(HttpServletRequest request, HttpServletResponse response) throws Exception { ActionForward forward = new ActionForward(); // 로그아웃시 세션에 담긴 아이디 값을 삭제한다. request.getSession().removeAttribute("sessionID"); // 로그아웃 후 메인화면으로 돌아간다. forward.setRedirect(true); forward.setNextPath("MainForm.do"); return forward; } } | cs |
■ MemberDeleteAction.java
31 줄
MemberLogoutAction과 마찬가지로 sessionID 값만 삭제하도록 변경하였다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | package jsp.member.action; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import jsp.member.model.MemberDAO; /** * 회원삭제 작업을 처리하는 Action 클래스 */ public class MemberDeleteAction implements Action { @Override public ActionForward execute(HttpServletRequest request, HttpServletResponse response) throws Exception { ActionForward forward = new ActionForward(); // 세션이 가지고있는 로그인한 ID 정보를 가져온다 HttpSession session = request.getSession(); String id = session.getAttribute("sessionID").toString(); String password = request.getParameter("password"); MemberDAO dao = MemberDAO.getInstance(); int check = dao.deleteMember(id, password); if(check == 1){ // 세션의 회원정보 삭제 session.removeAttribute("sessionID"); forward.setRedirect(true); forward.setNextPath("Result.do"); } else{ System.out.println("회원 삭제 실패"); return null; } return forward; } } | cs |
■ Footer.jsp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <%@ page language="java" contentType="text/html; charset=EUC-KR" pageEncoding="EUC-KR"%> <html> <head> <title>하단 영역</title> </head> <body> <br> 전체 : <%=session.getAttribute("totalCount") %> <br> 오늘 : <%=session.getAttribute("todayCount") %> <br> </body> </html> | cs |
3. 소스코드 다운로드 (war파일)
'코딩 > JSP' 카테고리의 다른 글
[JSP개발] 모든 회원보기 추가 (2) | 2016.12.07 |
---|---|
[JSP개발] Controller 변경 - properties 적용 (0) | 2016.12.06 |
[JSP개발] 회원가입 - MVC 패턴 적용 (5) | 2016.12.04 |
[JSP개발] 회원탈퇴, 회원수정 구현 (10) | 2016.11.24 |
[JSP개발] 페이지 모듈화 <jsp:include> 적용 (8) | 2016.11.24 |