저장소 & action tag

jinkyung·2021년 1월 20일
0

JSP

목록 보기
8/20

servletContext : 톰캣이 동작을 실행하는 순간 공간이 생성되고 종료되기 전까지 계속 저장하기때문에 가장 수명이 길다.

HttpSession: 브라우저 - 서버 연결.
브라우저를 켜놓고 작업하면 그동안 존재.
너무 오랫동안 반응이 없으면 session을 종료시킨다.(타임아웃)

servletRequest : 매 요청마다 생성, 응답전까지 유지됨
주소를 쳤을 때(요청), 브라우저로 돌아오는 것(응답)
포워드, 인클루드 서블릿끼리 데이터 공유할 때 적합

jspContext : jsp파일 페이지를 실행하는 동안 존재. 가장 적은 수명


servlet context를 활용하면 connection 객체를 생성 후 공유해서 쓸 수 있다.



Servlet Context

web.xml
:AppInitServlet 추가

<?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" version="3.1">
  <display-name>_12_JDBCServlet_ServletInitParam</display-name>
  
  
  <!-- 컨텍스트 초기화 매개변수(모든 서블릿에서 공유가능) -->

  	<context-param>
  		<param-name>driver</param-name>
  		<param-value>com.mysql.cj.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>
  	
  	
  	<!-- 서블릿 선언 주소와 매핑하지 않는다. 외부에 의해서 호출되지 않고 시작하자마자 실행되는 서블릿이기 때문이다.  -->
  <!-- 	주소와 매핑을 안해서 브라우저 요청에 의해서 호출되는 것이 아니라 
  	웹어플리케이션이 시작하면 최초로 실행되는 서블릿이다. -->
  	<servlet>
  		<servlet-name>AppInitServlet</servlet-name>
  		<servlet-class>spms.servlets.AppInitServlet</servlet-class>
  		
  		<!-- 시작하면 1순위로 올려라. 1순위가 여러개면 위에서부터 아래 순서대로 호출 --> 
  		<load-on-startup>1</load-on-startup>
  	</servlet>



<!-- Servlet 2.4이전에는 '컨텍스트 초기화 매개변수' 다음에 위치해야 한다 
			 2.4 이상부터는 순서에 관계 없다  -->
  <!--  필터 설정  -->
  <filter>
  	<filter-name>CharacterEncodingFilter</filter-name>
  	<filter-class>spms.filters.CharacterEncodingFilter</filter-class>
  	<init-param>
  		<param-name>encoding</param-name>
  		<param-value>UTF-8</param-value>
  	</init-param>
  </filter>
 
 
 <!-- 모든 주소에 필터를 적용 --> 
  <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>

AppInitServlet
: 가장 먼저 시작될 것이고, init()메서드를 실행할 것이다.

package spms.servlets;

import java.sql.Connection;
import java.sql.DriverManager;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;

@SuppressWarnings("serial")
public class AppInitServlet extends HttpServlet {

//	웹 어플리케이션 시작시 DB접속 객체를 만들어서 ServletContext 영역에 공유한다 
	@Override
	public void init() throws ServletException {
		System.out.println("AppInitServlet 준비...");
		try {
			ServletContext sc = this.getServletContext();
			String driver = sc.getInitParameter("driver");
			String url = sc.getInitParameter("url");
			String id = sc.getInitParameter("id");
			String pwd = sc.getInitParameter("password");
			Class.forName(driver);
			Connection conn = DriverManager.getConnection(url,id,pwd);
			
			// servlet context 영역에 conn 객체를 저장 
			// 이곳에 저장하면 웹 어플리케이션 가동 내내 모든 서블릿/jsp에서 사용가능하다.
			sc.setAttribute("conn", conn);
			
		} catch(Exception e){
			e.printStackTrace();
		}
	}

//	웹 어플리케이션 종료시 DB접속 객체가 연결되어 있다면 종료한다 
	@Override
	public void destroy() {
		System.out.println("AppInitServlet 마무리...");
		
		super.destroy();
		ServletContext sc = this.getServletContext();
		Connection conn = (Connection)sc.getAttribute("conn");
		
		try {
			// 객체가 존재하고, 닫히지 않았다면 연결 종료 
			if(conn != null && conn.isClosed()==false) {
				conn.close();
			}
		}catch(Exception e){
			e.printStackTrace();
		}
	}
}

MemberListServlet
직접 db에 연결할 필요 없이 공유하여 사용

package spms.servlets;

import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import spms.vo.Member;

@SuppressWarnings("serial")
@WebServlet("/member/list")
public class MemberListServlet extends HttpServlet{
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		Connection conn = null;	// MySQL 연결담당
		Statement stmt = null;	// SQL문 담당
		ResultSet rs = null;	// SELECT문의 결과 담당
		
		final String sqlSelect = "SELECT mno,mname,email,cre_date" + "\r\n" +
								"FROM members" + "\r\n" +
								"ORDER BY mno ASC";
		
//		Servelet Context 영역에 공유한 conn 객체를 가져와서 사용하겠다 
		ServletContext sc = this.getServletContext();
		conn = (Connection)sc.getAttribute("conn");
		
		try {
		
			stmt = conn.createStatement();
			rs = stmt.executeQuery(sqlSelect);
			
			resp.setContentType("text/html; charset=UTF-8"); // 먼저 호출
			
			/* members테이블의 전체 인원을 저장하기 위해
			 * ArrayList를 사용한다
			 * */
			ArrayList<Member> members = new ArrayList<Member>();
			
			// DB로부터 members테이블의 정보를 가져와서 member객체에 담고
			// member객체를 ArrayList에 차례로 저장한다.
			while(rs.next()) {
				members.add(new Member()
							.setNo(rs.getInt("mno"))
							.setName(rs.getString("mname"))
							.setEmail(rs.getString("email"))
							.setCreatedDate(rs.getDate("cre_date")));
			}
			
			// jsp에 전달하기 위해 request의 공유 공간에 저장한다
			req.setAttribute("members", members);
			
			// jsp로 request를 전달한다
			RequestDispatcher rd = 
					req.getRequestDispatcher("/member/MemberList.jsp");
			rd.include(req, resp);
			/* jsp로 전달(위임)하는 방식 2가지
			 * 1) forward : 제어권을 아예 넘겨준다(네가 알아서 처리해라)
			 * 2) include : 실행할 동안 제어권을 줬다가 처리가 끝나면 다시 넘겨 받는다
			 *              (마지막 확인은 내가 처리한다)
			 * */
			
		}catch(Exception e) {
			//throw new ServletException(e);
			
			req.setAttribute("error", e);
			RequestDispatcher rd = req.getRequestDispatcher("/Error.jsp");
			rd.forward(req, resp);
		}finally {
			try {
				if(rs!=null) 
					rs.close();
			}catch(Exception e) {
				e.printStackTrace();
			}
			try {
				if(stmt!=null) 
					stmt.close();
			}catch(Exception e) {
				e.printStackTrace();
			}
            
            
 //여기서 connection을 닫아버리면 list에서 한번 쓰고 닫아 버리는 것이므로 없애줘야 한다. 
/*			try {	
				if(conn!=null) 
					conn.close();
			}catch(Exception e) {
				e.printStackTrace();
			}
*/
		}
	}
}

HttpSession

LoginServlet

package spms.servlets;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


@WebServlet("/auth/login")
@SuppressWarnings("serial")
public class LoginServlet extends HttpServlet {
	
	
	// 주소로 요청이 들어오면 login form을 보여준다.
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// "사용자에게 화면을 전송해줘" jsp로 넘긴다 
		RequestDispatcher rd = req.getRequestDispatcher("/auth/LogInForm.jsp");
		rd.forward(req, resp);
	
	}
}

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">
<!-- 2초 후에 login 화면으로 이동  -->
<meta http-equiv="Refresh" content="2;url=login">
<title>로그인 실패</title>
</head>
<body>
	<p>
		로그인 실패입니다<br/>
		이메일 또는 암호가 일치하지 않습니다<br/>
		잠시 후에 다시 로그인 화면으로 갑니다 
	</p>
	
</body>
</html>

LoginServlet
로그인 폼의 method=post이므로 doPost 메서드 추가
해당 id가 있으면 vo객체에 저장 후 session객체에 저장 => 타임아웃이 걸리기 전까지 로그인상태로 공유객체가 존재

package spms.servlets;

import java.io.IOException;
import java.sql.*;

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;

@WebServlet("/auth/login")
@SuppressWarnings("serial")
public class LogInServlet extends HttpServlet {

	/* 주소로 접근을 하면 
	 * 로그인 폼을 보여준다
	 * */
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// "사용자에게 화면을 전송해줘" jsp로 넘긴다 
		RequestDispatcher rd = 
				req.getRequestDispatcher("/auth/LogInForm.jsp");
		rd.forward(req, resp);
	}
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		Connection conn= null;
		PreparedStatement stmt = null;
		ResultSet rs = null;
		String sqlLogIn = "SELECT mname,email " + "\r\n" +
						  "FROM members WHERE " + "\r\n" +
						  "email=? AND pwd=?";
		try {
			ServletContext sc = this.getServletContext();
			conn = (Connection)sc.getAttribute("conn");
			stmt = conn.prepareStatement(sqlLogIn);
			stmt.setString(1, req.getParameter("email"));
			stmt.setString(2, req.getParameter("password"));
			rs = stmt.executeQuery();
			
			// 결과가 존재한다면 '로그인 성공!'
			if(rs.next()) {		//rs.next()
				Member member = new Member().setEmail(rs.getString("email"))
							    .setName(rs.getString("mname"));
				// 로그인 정보를 session 공유 공간에 저장한다 
				// 세션 timeout 전까지는 보관된다 
				HttpSession session = req.getSession();
				session.setAttribute("member", member);
                
                	/*
				현재 경로가 /auth/login이므로 
				../ auth 경로 위로 이동하고
				다시 거기서부터 /member/list로 진입
			*/
				resp.sendRedirect("../member/list");
                
			}
			// 로그인 실패
			else {
				RequestDispatcher rd = req.getRequestDispatcher("/auth/LogInFail.jsp");
				rd.forward(req, resp);
			}
		} catch(Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if(rs != null)
					rs.close();
			}catch(Exception e) {
				e.printStackTrace();
			}
			
			try {
				if(stmt != null)
					stmt .close();
			}catch(Exception e) {
				e.printStackTrace();
			}
			
		}
	}
}

결과

로그인 성공시

로그인 실패시



Header.jsp
로그아웃 추가

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="spms.vo.Member" %>

<%
	Member member = (Member)session.getAttribute("member");
%>

<div style="background-color:#00008b; color:white; 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>

LogOutServlet

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;

@WebServlet("/auth/logout")
@SuppressWarnings("serial")
public class LogOutServlet extends HttpServlet {
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		HttpSession session = req.getSession();
		session.invalidate();	// 세션 저장 객체 무효화
		
		// 다시 로그인 화면으로 이동
		resp.sendRedirect("login");
	}
}

결과


Action tag

jsp:useBean 이용하여 request 공간에서 객체 가져오기

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!-- 페이지 지시자 추가. java의 import와 동일 -->
<%@ page import="spms.vo.Member" %>
<%@ page import="java.util.ArrayList" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원 목록</title>
</head>
<body>
	<jsp:include page="/Header.jsp" />
	<h1>회원 목록</h1>
	<p><a href='add'>신규 회원</a></p>
	
	<!-- request공간에서 members이름의 객체를 가져와라 -->
	<jsp:useBean id="members"
				scope="request"
				class="java.util.ArrayList"
				type="java.util.ArrayList<spms.vo.Member>"/>
	<%
	
	/*		
		ArrayList<Member> members = 
				(ArrayList<Member>)request.getAttribute("members");
	*/
		for(Member member : members){
	%>
		<%=member.getNo() %>,
		<a href='update?no=<%=member.getNo() %>'>
			<%=member.getName() %>
		</a>,
		<%=member.getEmail() %>,
		<%=member.getCreatedDate() %>
		<a href='delete?no=<%=member.getNo() %>'>
			[삭제]
		</a>
		<br/>
	<%
		}
	%>
	<jsp:include page="/Tail.jsp" />
</body>
</html>

0개의 댓글