5.6 데이터 보관소
1. 생성과 소멸 시점
- 4가지의 보관소로 이루어짐
1) ServletContext : 시작될 때 만들어지고 종료될때 삭제가됨
2) HttpSession : 클라이언트의 요청이 들어왔을때 최초 생성되고 세션이 닫히면 삭제가 됨
3) ServletRequest : 클라이언트의 요청이 왔을때 생성되고 응답이 끝날 때 사라짐
4) JspContext : jsp 페이지가 실행되는 동안에만 데이터를 사용할 수 있는 보관소로 지정됨
2. 웹 애플리케이션
1) ServletContext : 웹 애플리케이션 시작 시 준비됨 웹 애플리케이션 당 1개
2) HttpSession : 최초 요청 시 생성되고 세션이 무효화 되기 전까지 유지됨 세션 ID를 통해 사용자 별
3) ServletRequest : 매 요청 때마다 보관소가 생성되고 응답 전까지 유지됨, 포워드와 인클루드 서블릿끼리 데이터 공유할 때 적합
5) JspContext : JSP 페이지를 실행하는 동안 존재함 태그 핸들러와 데이터를 공유할 때 사용
3. ServletContext 활용 전
- 이렇게 서블릿'마다' DB커넥션을 만들어주고 연결했음
4. ServletContext 활용 후
- 커넥션을 하나만 사용하도록 만듬
5. ServletContext 실습하기 ( _15_MVC_AppInit )
Servlet 파일 생성하기 - AppInitServlet.java
package spms.servlets;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class AppinitServlet
*/
//웹 애플리케이션을 이용해서 서버를 여는 것이므로 URL매핑을 따로 지정해줄 필요가 없음
//@WebServlet("/AppInitServlet")
public class AppInitServlet extends HttpServlet {
@Override
public void init(ServletConfig config) throws ServletException {
System.out.println("AppInitServlet 준비...");
super.init(config);
try {
ServletContext sc = this.getServletContext();
String driver = sc.getInitParameter("driver");
String mySqlUrl = sc.getInitParameter("url");
String id = sc.getInitParameter("username");
String pwd = sc.getInitParameter("password");
Class.forName(driver);
Connection conn = DriverManager.getConnection(mySqlUrl, id, pwd);
//servletcontext 데이터 보관소에 mysql 접속 객체를 저장
sc.setAttribute("conn", conn);
} catch(Exception e) {
throw new ServletException(e);
}
}
@Override
public void destroy() {
System.out.println("AppInitServlet 마무리...");
super.destroy();
//servletcontext 데이터 보관소에 저장되어 있는 mysql 접속 객체 꺼내옴
Connection conn = (Connection)this.getServletContext().getAttribute("conn");
try {
if(conn != null && conn.isClosed() == false) {
conn.close();
}
} catch(Exception e) {
e.printStackTrace();
}
}
}
web.xml
* URL매핑이 없어서 클라이언트가 요청을 할 수가 없음
* 클라이언트의 요청이 없어도 웹어플리케이션이 실행될 때 자동으로 서블릿이 생성되도록 함
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>_06_JDBCServlet</display-name>
<!-- 컨텍스트 초기화 매개변수 -->
<context-param>
<param-name>driver</param-name>
<param-value>com.mysql.jdbc.Driver</param-value>
</context-param>
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost/studydb?serverTimezone=UTC</param-value>
</context-param>
<context-param>
<param-name>username</param-name>
<param-value>study</param-value>
</context-param>
<context-param>
<param-name>password</param-name>
<param-value>study</param-value>
</context-param>
<!-- AppInitServlet 선언 -->
<servlet>
<servlet-name>AppInitServlet</servlet-name>
<servlet-class>spms.servlets.AppInitServlet</servlet-class>
<!-- 클라이언트의 요청이 없어도 웹어플리케이션이 실행될 때 자동으로 서블릿이 생성되도록 함 -->
<load-on-startup>1</load-on-startup>
</servlet>
<!-- 필터 선언 -->
<!-- <filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>spms.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>-->
<!-- 필터 url 매핑 -->
<!-- /* : 모든 url 요청에 적용 -->
<!--<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>-->
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
MemberListServlet.java 파일 수정 (Add 파일과 Update 파일도 마찬가지로 진행)
* mysql 서버 접속 정보 4줄 주석 처리
* try 구문 내에 DriverManager와 Class.forname 부분 주석 처리
* 대신 conn = (Connection)sc.getAttribute("conn"); 문장 추가
ServletContext sc = this.getServletContext();
//mysql 서버 접속정보
// String driver = sc.getInitParameter("driver");
// String mySqlUrl = sc.getInitParameter("url");
// String id = sc.getInitParameter("username");
// String pwd = sc.getInitParameter("password");
try {
// 1. MySQL 제어 객체를 로딩
//DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver());
// Class.forName(driver);
// 2. MySQL 연결
// conn = DriverManager.getConnection(mySqlUrl, id, pwd);
//servletcontext 데이터 보관소에 저장되어 있는 Connection 객체를 꺼내 씀
conn = (Connection)sc.getAttribute("conn");
// 3. sql문 객체 생성
stmt = conn.createStatement();
// 4. sql 전송 후 결과 값 리턴받기
rs = stmt.executeQuery(sqlSelect);
// 5. 결과를 브라우저로 전송
response.setContentType("text/html;charset=UTF-8");
ArrayList<Member> members = new ArrayList<Member>();
* servletcontext 데이터 보관소에 저장되어 있는 Connection 객체를 꺼내 씀
* 코드짜기가 훨씬 간편해짐 (코드 간소화)
6. 클라이언트 요청을 처리하지 않는 서블릿
7. 기존 서블릿 변경
8. HttpSession (로그인에 자주 사용됨)
* Tomcat 서버는 기본적으로 세션이 30분 뒤에 꺼지도록 설정이 되어있음
9. HttpSession 로그인, 로그아웃 실습하기 ( _16_MVC_Login_Logout )
실습1) 로그인 성공/실패
LoginServlet.java 파일 생성
package spms.servlets;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
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 javax.servlet.http.HttpSession;
import spms.vo.Member;
/**
* Servlet implementation class LoginServlet
*/
@WebServlet("/auth/login")
public class LoginServlet extends HttpServlet {
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
//get 방식으로 요청이 오면 로그인 페이지로 이동
RequestDispatcher rd = request.getRequestDispatcher("/auth/LoginForm.jsp");
rd.forward(request, response);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
//post 방식으로 요청이 오면 로그인 처리
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
String sqlLogin = "SELECT MNAME, EMAIL FROM MEMBERS WHERE EMAIL=? AND PWD=?";
try {
ServletContext sc = this.getServletContext();
conn = (Connection)sc.getAttribute("conn");
stmt = conn.prepareStatement(sqlLogin);
stmt.setString(1, request.getParameter("email"));
stmt.setString(2, request.getParameter("password"));
rs = stmt.executeQuery();
//로그인 성공 시
if(rs.next()) {
Member member = new Member()
.setEmail(rs.getString("EMAIL"))
.setName(rs.getNString("MNAME"));
HttpSession session = request.getSession();
session.setAttribute("Member", member);
response.sendRedirect("../member/list");
} //로그인 실패시
else {
RequestDispatcher rd = request.getRequestDispatcher("/auth/LoginFail.jsp");
rd.forward(request, response);
}
} catch(Exception e) {
throw new ServletException(e);
} finally {
try {
if(rs != null) {
rs.close();
}
} catch(Exception e) {
e.printStackTrace();
}
}
}
}
LoginForm.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>로그인</title>
</head>
<body>
<h2>사용자 로그인</h2>
<form action="login" method="post">
이메일 : <input type="text" name="email"><br>
암호 : <input type="password" name="password"><br>
<input type="submit" value="로그인"><br>
</form>
</body>
</html>
LoginFail.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="Refresh" content="1; url=login">
<title>로그인 실패</title>
</head>
<body>
<p>로그인 실패입니다. 이메일 또는 암호가 맞지 않습니다.
잠시 후에 다시 로그인 화면으로 갑니다.</p>
</body>
</html>
MemberListServlet.java 파일 수정 (맨 아래 try-catch문 지울것)
finally {
try {
if(rs != null) {
rs.close();
}
} catch(Exception e) {
e.printStackTrace();
}
try {
if(stmt != null) {
stmt.close();
}
} catch(Exception e) {
e.printStackTrace();
}
// try {
// if(conn != null) {
// conn.close();
// }
// } catch(Exception e) {
// e.printStackTrace();
// }
}
실행 화면 (로그인 실패 화면) - 목록에 없는 이메일 입력
- 이 화면에서 1초만에 바로 다시 로그인 화면으로 이동하게됨
실행 화면 (로그인 성공 화면) - 목록에 있는 이메일 입력
- 목록에 있는 이메일로 로그인 하는 경우 회원 목록 페이지로 이동하게 됨
실습2) 헤더 우측에 로그인 정보 띄우기
Header.jsp 파일 수정
<%@ page import="spms.vo.Member" %>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
//HttpSession 데이터 보관소에 저장된 member 객체 꺼내서 사용
Member member = (Member)session.getAttribute("Member");
%>
<div style="background-color:#00008b; color:#ffffff; height:20px; padding:5px">
SPMS(Simple Project Management System)
<span style="float:right;">
<%=member.getName() %>
<a style="color:white;" href="<%=request.getContextPath() %>/auth/logout">로그아웃</a>
</span>
</div>
실행 화면
실습3) HttpSession 무효화 - 로그아웃
LogoutServlet.java 파일 생성
package spms.servlets;
import java.io.IOException;
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 javax.servlet.http.HttpSession;
/**
* Servlet implementation class LogoutServlet
*/
@WebServlet("/auth/logout")
public class LogoutServlet extends HttpServlet {
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
HttpSession session = request.getSession();
//세션 무효화 처리
session.invalidate();
response.sendRedirect("login");
}
}
실행 화면
실습4) 회원 정보 삭제
MemberList.jsp
<%@ page import="spms.vo.Member"%>
<%@ page import="java.util.ArrayList" %>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원 목록</title>
</head>
<body>
<!-- jsp action tag
jsp:useBean, jsp:setProperty, jsp:getProperty, jsp:forward, jsp:include.....
actiontag를 이용하면 jsp의 자바 소스를 줄일 수 있다
-->
<jsp:include page="/Header.jsp"/>
<h1>회원 목록</h1>
<p><a href="add">신규 회원</a></p>
<!-- servletrequest 데이터 보관소에서 memberList라는 객체를 꺼내옴 -->
<!-- id : 사용할 객체 이름 -->
<!-- scope : 어느 데이터 보관소에서 객체를 꺼내올지 결정
request(servletrequest 데이터 보관소),
session(HttpSession 데이터 보관소),
application(Servletcontext 데이터 보관소) -->
<jsp:useBean id="memberList"
scope="request"
class="java.util.ArrayList"
type="java.util.ArrayList<spms.vo.Member>"></jsp:useBean>
<%
//MemberListServlet에서 request.setAttribute로 전달한 결과 값 꺼내쓰기
//ArrayList<Member> members = (ArrayList<Member>)request.getAttribute("memberList");
for(Member member : memberList) {
%>
<%=member.getNo() %>,
<a href="update?no=<%=member.getNo()%>"><%=member.getName() %></a>,
<%=member.getEmail() %>,
<%=member.getCreateDate() %>
<a href="delete?no=<%=member.getNo()%>">삭제</a><br>
<%} %>
<jsp:include page="/Tail.jsp"/>
</body>
</html>
MemberDeleteServlet.java
package spms.servlets;
import java.io.IOException;
import java.sql.Connection;
import java.sql.Statement;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class MemberDeleteServlet
*/
@WebServlet("/member/delete")
public class MemberDeleteServlet extends HttpServlet {
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
Connection conn = null;
Statement stmt = null;
String sqlDelete = "DELETE FROM MEMBERS WHERE MNO=" + request.getParameter("no");
try {
ServletContext sc = this.getServletContext();
conn = (Connection)sc.getAttribute("conn");
stmt = conn.createStatement();
stmt.executeLargeUpdate(sqlDelete);
response.sendRedirect("list");
} catch(Exception e) {
e.printStackTrace();
request.setAttribute("error", e);
RequestDispatcher rd = request.getRequestDispatcher("/error.jsp");
rd.forward(request, response);
} finally {
try {
if(stmt != null) {
stmt.close();
}
} catch(Exception e) {
e.printStackTrace();
}
}
}
}
Header.jsp
<%@ page import="spms.vo.Member" %>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<jsp:useBean id="Member"
scope="session"
class="spms.vo.Member">
</jsp:useBean>
<%
//HttpSession 데이터 보관소에 저장된 member 객체 꺼내서 사용
//Member member = (Member)session.getAttribute("Member");
%>
<div style="background-color:#00008b; color:#ffffff; height:20px; padding:5px">
SPMS(Simple Project Management System)
<span style="float:right;">
<%=Member.getName() %>
<a style="color:white;" href="<%=request.getContextPath() %>/auth/logout">로그아웃</a>
</span>
</div>
실행 화면
- 일지매 회원이 삭제됨
'👨💻 2. 웹개발_Back end > 2-4 JSP & Servlet' 카테고리의 다른 글
[JSP & Servlet] 5장 MVC 아키텍처 (5) - DAO객체 만들기 (0) | 2021.10.14 |
---|---|
[JSP & Servlet] 5장 MVC 아키텍처 (4) - 뷰와 서블릿 분리 및 JSP 컨텍스트와 Action Tag (1) | 2021.10.14 |
[JSP & Servlet] 5장 MVC 아키텍처 (2) - 뷰 분리 및 포워딩과 인클루딩 (0) | 2021.10.14 |
[JSP & Servlet] 5장 MVC 아키텍처 (1) - MVC 이해하기 (0) | 2021.10.14 |
[JSP & Servlet] 4장 서블릿과 JDBC (4) - 필터 사용하기 (0) | 2021.10.14 |
댓글