Study Web Development

1월 5일

이전으로

Servlet & JSP

2. Servlet

2-2 HTTP 프로토콜과 HTTP 메서드

POST 방식
  1. views 폴더에 새 HTML 파일 member_form.html 생성
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원 가입</title>
</head>
<body>
	<form action="/servletMain/member" method="post">
		이름 : <input type="text" name="name"><br>
		나이 : <input type="text" name="age"><br>
		직업 : <input type="text" name="job"><br>
		전화번호 : <input type="text" name="phone" size=3 maxlength=3> -
				<input type="text" name="phone" size=4 maxlength=4> - 
				<input type="text" name="phone" size=4 maxlength=4><br>
		<input type="submit" value="전송">
	</form>
</body>
</html>
  1. 패키지 kr.web.ch02에 새 클래스 MemberServlet 생성
package kr.web.ch02;

import java.io.IOException;
import java.io.PrintWriter;

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("/member")
public class MemberServlet extends HttpServlet {
	@Override
	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 전송된 데이터 인코딩 처리
		request.setCharacterEncoding("UTF-8");
		
		String name = request.getParameter("name");
		String age = request.getParameter("age");
		String job = request.getParameter("job");
		
		// 문서 타입 및 캐릭터셋 지정
		response.setContentType("text/html;charset=UTF-8");
		
		// HTML 출력을 위한 출력 스트림 생성
		PrintWriter out = response.getWriter();
		out.println("<html>");
		out.println("<head><title>회원 가입</title></head>");
		out.println("<body>");
		out.println("회원 가입을 축하합니다.<br>====회원 정보====</br>");
		out.println("이름 : " + name + "<br>");
		out.println("나이 : " + age + "<br>");
		out.println("직업 : " + job + "<br>");
		
		String[] phones = request.getParameterValues("phone"); // <input> 태그 type 중 checkbox, radio는 선택하지 않으면 아예 파라미터가 전송되지 않지만(getParamterValeus() 메서드는 파라미터가 존재하지 않으면 null 반환), 그 외의 type은 입력하지 않아도 빈 문자열이 전송됨
		if(!phones[0].equals("") && !phones[1].equals("") && !phones[2].equals("")) {
			for(int i=0;i<phones.length;i++) {
				if(i>0) out.println("-");
				out.println(phones[i]);
			}
		}
		else { // 전화번호 3개 칸 중 하나라도 입력하지 않은 경우
			out.println("잘못 명시했습니다!");
		}

		out.println("</body>");
		out.println("</html>");
		out.close();
	}
}

2-5 라이프 사이클

  1. 패키지 kr.web.ch02에 새 클래스 LifeCycle 생성
package kr.web.ch02;

import java.io.IOException;
import java.io.PrintWriter;

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("/lifeCycle")
public class LifeCycle extends HttpServlet {
	@Override
	public void init() throws ServletException {
		System.out.println("init() 메서드 호출");
	}
	
	@Override
	public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("service() 메서드 호출");
		
		// 문서 타입 및 캐릭터셋 지정
		response.setContentType("text/html;charset=utf-8");
		
		// HTML 출력을 위한 출력 스트림 생성
		PrintWriter out = response.getWriter();
		out.println("<html>");
		out.println("<head><title>Servlet Life Cycle</title></head>");
		out.println("<body>");
		out.println("서블릿 생명 주기 학습하기");
		out.println("</body>");
		out.println("</html>");
		out.close();
	}
	
	@Override
	public void destroy() {
		System.out.println("destroy() 메서드 호출 : 본 메서드는 Servlet이 더 이상 사용되지 않을 때만 호출됨");
	}
}

2-6 서블릿 매핑

  1. 패키지 kr.web.ch01의 클래스 HelloWorld에서 @WebServlet을 주석 처리
  2. WEB-INF 폴더의 web.xml를 열고, 왼쪽 하단의 Source 탭 선택
<?xml version="1.0" encoding="UTF-8"?> <!-- XML 선언 -->
<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_4_0.xsd" id="WebApp_ID" version="4.0">
  <display-name>servletMain</display-name> <!-- 프로젝트명 -->
  <servlet> <!-- 식별자와 서블릿 클래스를 매핑 -->
  	<servlet-name>HelloWorld</servlet-name> <!-- 서블릿명을 식별자로 사용 -->
  	<servlet-class>kr.web.ch01.HelloWorld</servlet-class> <!-- 패키지명을 포함한 실제 클래스명 -->
  </servlet>
  <servlet-mapping> <!-- 식별자와 URL 주소를 매핑 -->
  	<servlet-name>HelloWorld</servlet-name>
  	<url-pattern>/hello</url-pattern> <!-- Context Root 이후의 상세 경로 -->
  </servlet-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>

3. JSP

JSP의 개요

  1. 새 다이나믹 웹 프로젝트를 생성하여 프로젝트명에 jspMain 입력 후 Next-Next-Generate web.xml depolyment descriptor 선택 후 Finish
  2. 프로젝트를 오른쪽 클릭하여 Build Path-Configure Build Path... 선택하고 Libraries 탭에서 JRE System Library를 선택 후 Edit...에서 JavaSE-1.8(jre)로 변경
  3. 프로젝트를 오른쪽 클릭하여 Properties 선택하고 좌측 목록에서 Project Facets 선택 후 Java의 Version을 1.8로 변경
  4. src/main/webapp 폴더 오른쪽 클릭하고 새 JSP 파일 index.jsp 생성
<!-- JSP 설정 정보 -->
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!-- HTML -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>First JSP</title>
</head>
<body>
Hello JSP!
</body>
</html>
  1. src/main/webapp 폴더 오른쪽 클릭하고 새 폴더 ch01-basic 생성 후 새 JSP 파일 s01_now.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.util.Date" %>
<%@ page import="java.text.SimpleDateFormat" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>오늘의 날짜와 시간</title>
</head>
<body>
<%
	// 객체 생성
	Date nowTime = new Date();
%>
현재 날짜와 시간은 <%= nowTime %>입니다.
<br>--------<br>
<%
	// 객체 생성
	SimpleDateFormat sf = new SimpleDateFormat("yyyy년 MM월 DD일 a hh:mm:ss");
%>
현재 날짜와 시간은 <%= sf.format(nowTime) %>입니다.
</body>
</html>
  1. 새 JSP 파일 s02_hundred.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>1부터 100까지의 합</title>
</head>
<body>
<h1>1부터 100까지의 합</h1>
<%
	int total = 0;
	for(int i=1;i<=100;i++) {
		total += i;
	}
	// 출력
	out.println("1부터 100까지의 합 : " + total);
%>
</body>
</html>
  1. 새 JSP 파일 s03_gugudan.jsp 생성
><%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>구구단 - 5단</title>
</head>
<body>
<%
	for(int i=1;i<=9;i++) {
		// 출력
		out.println("5 * " + i + " = " + 5 * i + "<br>");
	}
%>
</body>
</html>

3-2 스크립트

  1. 새 폴더 ch02-script 생성하고 새 JSP 파일 s01_script.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>
<%!
	// 선언부 : 변수 선언, 메서드 선언
	String[] str = {"JSP가", "정말", "재미", "있다"};
%>
<table border="1">
	<tr>
		<th>배열의 인덱스</th>
		<th>배열의 내용</th>
	</tr>
	<%
		// 스크립트릿 : 변수 선언, 연산, 제어문, 출력
		for(int i=0;i<str.length;i++) {
			out.println("<tr>"); // 스크립트릿에서 출력하는 것은 서블릿과 같은 방식으로, 문자열로 태그를 작성하기 때문에 속성 지정이나 JavaScript, CSS 등을 활용하기 불편해서 권장되지 않음
			out.println("<td>" + i + "</td>");
			out.println("<td>" + str[i] + "</td>");
			out.println("</tr>");
		}
	%>
</table>
<br>
<h2>배열의 내용 출력 - 선언부, 스크립트릿, 표현식</h2>
<table border="1">
	<tr>
		<th>배열의 인덱스</th>
		<th>배열의 내용</th>
	</tr>
<%
	for(int i=0;i<str.length;i++) { // 스크립트릿 내부에는 표현식을 사용할 수 없으므로, 스크립트릿 영역을 분할 후 스크립트릿 영역 바깥에 표현식을 사용해야 함
%>
	<tr>
		<!-- 표현식 : 변수의 값 출력, 메서드의 결과 값 출력, 연산의 결과 값 출력  -->
		<%-- JSP 주석 : Java 주석과 마찬가지로 컴파일시 제외되어 HTML 페이지 원본 보기에 나타나지 않음 --%>
		<td><%= i %></td>
		<td><%= str[i] %></td>
	</tr>
<%
	} // for문 시작과 끝 영역을 분할한 경우, 두 영역 사이에 오는 HTML 영역은 for문에 의해 반복됨
%>
</table>
<br>
<h2>배열의 내용 출력 : 확장 for문</h2>
<table border="1">
	<tr>
		<th>배열의 내용</th>
	</tr>
<%
	for(String s : str) {
%>
	<tr>
		<td><%= s %></td>
	</tr>
<%
	}
%>
</table>
<style type="text/css"> /* 테이블의 행과 열을 pivot */
	table {border-collapse: collapse;}
	tbody {display: flex; flex-direction: row;}
	tr {display: flex; flex-direction: column;}
</style>
</body>
</html>
  1. 새 JSP 파일 s02_script.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>
<%--
[실습 문제]
배열 생성(score) 국어, 수학, 영어
[출력 예시]
국어 : 88
수학 : 99
영어 : 86
총점 : 273
평균 : 91
 --%>
<%!
	String[] subject = {"국어", "수학", "영어"};
	int[] score = {88, 99, 86};
	// int sum = 0, avg = 0; // 변수를 선언부에서 선언하면 서블릿에서 멤버 변수로 만들어져 HTML 요청(새로고침 등)이 반복될 때 변수의 값이 계속 유지됨; 즉, 두 번째 요청시 sum의 값이 273인 상태에서 다시 한 번 for문을 수행하므로 요청시마다 값이 계속해서 증가
%>
<%
	int sum = 0, avg = 0; // 변수를 스크립트릿에서 선언하면 서블릿에서 service() 메서드의 지역 변수로 만들어져 HTML 요청시마다 변수가 새로 생성 및 초기화됨
	for(int i=0;i<score.length;i++) {
		sum += score[i]; // 총점 구하기
%>
<%= subject[i] %> : <%= score[i] %><br> <%-- 과목명과 점수 출력 --%>
<%
	}
	avg = sum/score.length; // 평균 구하기
%>
<%--
국어 : <%= score[0] %><br>
수학 : <%= score[1] %><br>
영어 : <%= score[2] %><br>
 --%>
총점 : <%= sum %><br>
평균 : <%= avg %>
</body>
</html>

C:\javaWork\workspace_jsp\.metadata\.plugins\org.eclipse.wst.server.core temp0에 Tomcat과 거의 같은 디렉토리 구조가 있음

C:\javaWork\workspace_jsp\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\work\Catalina\localhost\jspMain\org\apache\jsp\ch02_002dscript

3-1 디렉티브

page 디렉티브의 주요 속성
JSP 구동 원리

3-3 기본 객체

JSP가 제공하는 기본 객체
기본 객체 자료형 설명
request javax.servlet.HttpServletRequest 클라이언트의 요청 정보를 저장
response javax.servlet.HttpServletResponse 응답 정보를 저장
pageContext javax.servlet.jsp.PageContext JSP 페이지에 대한 정보를 저장
session javax.servlet.HttpSession HTTP 세션 정보를 저장
application javax.servlet.ServletContext 웹 어플리케이션에 대한 정보를 저장
out javax.servlet.jsp.JspWriter JSP 페이지가 생성하는 결과를 출력할 때 사용되는 출력 스트림
config javax.servlet.ServletConfig JSP 페이지에 대한 설정 정보를 저장
page java.lang.Object JSP 페이지를 구현한 자바 클래스 인스턴스
exception java.lang.Throwable 예외 객체(에러 페이지에서만 사용)
request
  1. 새 폴더 ch03-nestedObject 생성하고 새 JSP 파일 s01_requestInfo.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>
<%-- request는 HttpServletRequest 객체의 참조 변수 --%>
클라이언트의 IP : <%= request.getRemoteAddr() %><br> <%-- getRemoteAddr() 메서드는 요청을 보낸 클라이언트 혹은 마지막 프록시의 IP 주소를 IPv6 형식으로 반환하며, localhost로 접속시에는 실제 IP 주소가 아닌 0:0:0:0:0:0:0:1을 반환 --%>
요청 정보 프로토콜 : <%= request.getProtocol() %><br>
요청 정보 전송 방식 : <%= request.getMethod() %><br> <%-- URL로 요청했으므로 GET 방식 --%>
요청 URL(Uniform Resource Locator) : <%= request.getRequestURL() %><br> <%-- 전체 주소(=절대 주소) --%>
요청 URI(Uniform Resource Identifier) : <%= request.getRequestURI() %><br> <%-- Root를 생략한(=Context Root부터 시작하는) 부분 주소(=상대 주소) --%>
컨텍스트 경로 : <%= request.getContextPath() %><br>
서버 이름 : <%= request.getServerName() %><br>
서버 포트 : <%= request.getServerPort() %> <%-- 상용 서비스는 80이 기본이지만, Tomcat의 경우 테스트용으로 8080이 설정되어 있음 --%>
</body>
</html>
  1. 새 JSP 파일 s02_viewHeaderList.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.util.Enumeration" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>헤더 목록 출력</title>
</head>
<body>
<%
	Enumeration headerEnum = request.getHeaderNames();
	while(headerEnum.hasMoreElements()) { // while 시작
		// 헤더명 구하기
		String headerName = (String)headerEnum.nextElement();
		// 헤더 값 구하기
		String headerValue = request.getHeader(headerName);
%>
	<%= headerName %> = <%= headerValue %><br>
<%
	} // while 끝
%>
</body>
</html>
  1. 새 JSP 파일 s03_makeTestForm.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>
폼에 데이터를 입력한 후 &quot;전송&quot; 버튼을 클릭하세요.
	<form action="s04_viewParameter.jsp" method="post">
		이름 : <input type="text" name="name" size="10"><br>
		주소 : <input type="text" name="address" size="30"><br>
		좋아하는 동물 :
		<label><input type="checkbox" name="pet" value="dog">강아지</label>
		<label><input type="checkbox" name="pet" value="cat">고양이</label>
		<label><input type="checkbox" name="pet" value="bird"></label><br>
		<input type="submit" value="전송">
	</form>
</body>
</html>
  1. 새 JSP 파일 s04_viewParameter.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
	// 전송된 데이터 인코딩 처리
	request.setCharacterEncoding("UTF-8");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>요청 파라미터 출력</title>
</head>
<body>
<h3>request.getParameter() 메서드 사용</h3>
name 파라미터 = <%= request.getParameter("name") %><br>
address 파라미터 = <%= request.getParameter("address") %><br>
	
<h3>request.getParameterValues() 메서드 사용</h3>
<%
	String[] values = request.getParameterValues("pet");
	if(values!=null) { // 체크박스의 경우 선택하지 않으면 파라미터가 아예 전송되지 않으므로 배열로 처리시 NPE가 발생할 수 있음
		for(int i=0;i<values.length;i++) { // for 시작
%>
		<%= values[i] %>
<%
		} // for 끝
	}
%>
</body>
</html>

다음으로