Deployment Descriptor

- Deployment Descriptor(배치 기술서)는 보통 Web Document Root 디렉토리에 WEB-INF 폴더 아래 web.xml 파일로 존재한다.

- Servlet 설정, Error Page 설정, Listener 및 Filter 설정, 보안 설정 등을 위한 Web Application의 설정 파일이다.

- URL과 실제 서블릿의 매핑 정보를 설정한다.

- 서버 자원(DB 설정) 등도 설정할 수 있으며, 설정된 서버 자원은 소스 코드 변경 없이 수정이 가능하다.

- 하나의 웹 어플리케이션에 하나만 존재한다.

- Servlet 3.0(jsp 2.2, Tomcat 7.0)부터는 web.xml 파일은 선택 사항으로 변경 되었다.

 

web.xml 에서의 서블릿 설정

- url-pattern의 유형

(1) Exactly matching

- 해당 URL 요청만 지정한 서블릿으로 처리하며, 반드시 "/"로 시작해야 한다.

- 형식 : /[경로/]이름

- 사용 예 : /bbs/list

(2) Directory matching

- "/경로/*" 형식으로 설정하며, "*" 부분은 모든 경로가 가능한 패턴이다.

- 사용 예 : /board/* -> /board/list, /board/article 처럼 * 자리에는 모든 경로가 가능하다.

(3) Extension matching

- 해당 확장자 요청을 지정한 서블릿으로 처리하며, "/"로 시작할 수 없고 확장자로 끝나야 한다.

- 형식 : *.확장자

- 사용 예 : *.do

(4) /

DefaultServlet에 대한 URL 패턴으로 DefaultServlet은 정적 리소스를 처리하는 톰캣의 기본 서블릿이다.

 

서블릿 실행과정 및 서블릿 작성

실행과정

1. 사용자가 URL로 요청하면 HTTP Request를 Servlet Container에 보낸다.

2. Servlet Container는 HttpServletRequest, HtttpServletResponse 두 객체를 생성한다.

3. 사용자가 요청한 URL을 분석하여 어느 서블릿에 대한 요청인지 찾는다. Deployment Descriptor파일인 web.xml을 분석하여 해당 서블릿을 찾는다.

4. 컨테이너는 해당 서블릿의 service() 메소드를 호출하며, HttpServlet클래스를 상속 받은 경우 POST, GET 여부에 따라 doGet() 또는 doPost()가 호출된다.

5. service()메소드는 클라이언트 요청을 처리 한 후 HttpServletResponse 객체에 응답을 보낸다. HttpServlet 클래스를 상속 받은 경우에는 doGet() 또는 doPost() 메소드가 클라이언트 요청을 처리한 후 HttpServletResponse 객체에 응답을 보낸다.

6. 응답이 완료되면 HttpServletRequest, HttpServletResponse 두 객체를 소멸시킨다. 

 

Servlet Architecture

개요

- 서블릿 아키텍처는 javax.servlet 과 javax.servlet.http의 패키지로 구성된다.

- javax.servlet 패키지는 모든 서블릿이 상속하거나 구현하는 일반적인 인터페이스와 클래스로 구성되어 있다.

- javax.servlet.http 패키지는 HTTP 프로토콜에 맞춘 클래스 및 인터페이스로 구성되어 있다.

 

Servlet 인터페이스

개요

- javax.servlet.Servlet 인터페이스는 서블릿이 구현해야 하는 메소드가 선언된 인터페이스이다.

- Servlet 인터페이스의 구현은 javax.servlet.GenericServlet 또는 GenericServlet 클래스를 상속 받은 javax.servlet.http.HttpServlet 클래스를 상속 받아 서블릿 클래스를 작성할 수 있다.

- Servlet 인터페이스는 서블릿을 초기화하고 클라이언트 요청을 처리하며 서블릿을 서버에서 제거하는 메소드를 가지고 있다. 이러한 메소드는 라이프 사이클 메소드라고 하며 다음 순서로 호출된다.

(1) 서블릿이 생성된 다음 init() 메소드로 초기화 한다.

(2) 클라이언트의 요청은 service() 메소드에서 처리한다.

(3) 서블릿을 제거해야 하는 경우에는 컨테이너는 destroy() 메소드를 호출한 다음 garvage collected 후 종료한다.

 

GenericServlet 추상 클래스

개요

- javax.servlet.GenericServlet 추상 클래스는 Servlet 과 ServletConfig 인터페이스를 구현한 클래스이다.

- 서블릿을 작성하기 위해서 GenericServlet 클래스를 상속 받아 쉽게 작성할 수 있지만, HttpServlet과 같은 프로토콜 별 하위 클래스를 작성하는 것이 더 일반적이다.

- 웹에서 사용하는 HTTP 서블릿은 일반적으로 GenericServlet 대신 HttpServlet을 상속 받아 작성한다.

- GenericServlet을 상속받아 서블릿 클래스를 작성하기 위해서는 추상 메소드인 service() 메소드만 재정의 하면 된다.

 

HttpServlet 추상 클래스

개요

- javax.servlet.http.HttpServlet 추상 클래스는 GenericServlet 클래스를 상속받은 하위클래스로 웹사이트에 적합한 HTTP 서블릿을 만들기 위해 상속 받는다.

- HttpServlet 의 하위 클래스는 최소한 하나의 메소드를 재정의하며, 재정의하는 메소드는 일반적으로 다음 중 하나의 메소드이다.

: 서블릿이 HTTP GET 요청을 처리하는 경우 doGet()

: 서블릿이 HTTP POST 요청을 처리하는 경우 doPost()

: 서블릿이 HTTP PUT 요청을 처리하는 경우 doPut()

: 서블릿이 HTTP DELETE 요청을 처리하는 경우 doDelete()

doOptions() 및 doTrace() 메소드도 있지만 재정의할 이유가 거의 없으며, 일반적으로 웹 서비스는 doGet()메소드와 doPost() 메소드를 재정의하여 개발한다.

- 서블릿은 일반적으로 멀티 스레드 서버에서 실행되므로 서블릿은 동시 요청을 처리하고 공유 리소스에 대한 액세스를 동기화하는 데 주의 해야한다. 공유 리소스에는 인스턴스 또는 클래스 변수와 같은 메모리 내 데이터와 파일, 데이터베이스 연결 및 네트워크 연결과 같은 외부 개체가 포함된다.

 

ex12 - POST 방식으로 파라미터를 서버에 넘길 때

더보기
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>폼 예제</h3>

<form method='post' action="ex12_ok.jsp">
	<p>이름 : <input type='text' name='name'></p>
	<p>학번 : <input type='text' name='studentId'></p>
	<p>성별 :
		남자 <input  type='radio' name='gender' value='M' checked="checked">
		여자 <input type='radio' name='gender' value='F'>
	</p>
	<p>좋아하는 과목 :
		<input type="text" name="subject">
		<input type="text" name="subject">
		<input type="text" name="subject">
	</p>
	<p>출신도 :
		<select name="city">
			<option value="">::선택::</option>
			<option value="서울">서울</option>
			<option value="경기">경기</option>
			<option value="인천">인천</option>
			<option value="기타">기타</option>
		</select>
	</p>
	<p>취미 :
		<select name="hobby" multiple="multiple" size="5">
			<option value="운동">운동하기</option>
			<option value="영화">영화보기</option>
			<option value="등산">등산가기</option>
			<option value="여행">여행하기</option>
			<option value="게임">게임하기</option>
		</select>
	</p>
	<p>
		<button type="submit">등록하기</button>
	</p>
</form>

</body>
</html>
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<%
	request.setCharacterEncoding("utf-8");
	
	String name = request.getParameter("name");
	String studentId = request.getParameter("studentId");
	String gender = request.getParameter("gender");
	
	String[] sub = request.getParameterValues("subject");
	String subject = "";
	for(String s : sub) {
		if(s.length() != 0) {
			subject += s + "  ";
		}
	}

	String city = request.getParameter("city");
	
	String[] hob = request.getParameterValues("hobby");
	String hobby = "";
	if(hob != null) {
		for(String h : hob) {
			hobby += h + "  ";
		}
	}

%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>서버에서 넘겨 받은 파라미터</h3>

<p>이름 : <%=name %></p>
<p>학번 : <%=studentId %></p>
<p>성별 : <%=gender %></p>
<p>좋아하는 과목 : <%=subject %></p>
<p>출신도 : <%=city %></p>
<p>취미 : <%=hobby %></p>

</body>
</html>

 

ex13 - hidden 객체 : 화면에 출력되지 않지만 서버에 전송해야 하는 경우 (하지만 많으면 프로그래밍이 어려워짐)

더보기
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
<script type="text/javascript">
function send(operator) {
	var f = document.myForm;
	
	if(! /^\d+/.test(f.num1.value) ) {
		f.num1.focus();
		return;
	}
	
	if(! /^\d+/.test(f.num2.value) ) {
		f.num2.focus();
		return;
	}
	
	f.operator.value = operator;
	
	f.submit();
}
</script>

</head>
<body>

<h3>hidden 객체 : 화면에 출력되지 않지만 서버에 전송해야 하는 경우에 사용 </h3>

<form name="myForm" action="ex13_ok.jsp" method="post">
<p>
	<input type="text" name="num1" placeholder="첫번째 수">
	<input type="text" name="num2" placeholder="두번째 수">
	<input type="hidden" name="operator">
</p>
<p>
	<button type="button" onclick="send('+')">더하기</button>
	<button type="button" onclick="send('-')">빼기</button>
	<button type="button" onclick="send('*')">곱하기</button>
	<button type="button" onclick="send('/')">나누기</button>
</p>
</form>

</body>
</html>
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<%
	request.setCharacterEncoding("utf-8");

	int num1 = Integer.parseInt( request.getParameter("num1") );
	int num2 = Integer.parseInt( request.getParameter("num2") );
	
	String op = request.getParameter("operator");
	String s = "";
	
	// if(op.equals("+")) String.format("%d + %d = %d", num1, num2, num1+num2);
	
	switch(op) {
	case "+" : s = String.format("%d + %d = %d", num1, num2, num1+num2); break;
	case "-" : s = String.format("%d - %d = %d", num1, num2, num1-num2); break;
	case "*" : s = String.format("%d * %d = %d", num1, num2, num1*num2); break;
	case "/" : s = String.format("%d / %d = %d", num1, num2, num1/num2); break;
	}
	
%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>결과</h3>
<p> <%= s %> </p>

</body>
</html>

 

ex14 - 폼태그 안의 disabled 속성의 객체는 서버로 전송되지 않는다.

더보기
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>폼예제 : disabled 속성의 객체는 서버로 전송되지 않는다.</h3>

<form action="ex14_ok.jsp" method="post">
	<p>번호 : <input type="text" name="num" value="1111" readonly="readonly"></p>
	<p>이름 : <input type="text" name="name"></p>
	<p>나이 : <input type="text" name="age" value="20" disabled="disabled"></p>
	<p>
		<button type="submit">보내기</button>
	</p>
</form>

</body>
</html>
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<%
	request.setCharacterEncoding("utf-8");

	String num = request.getParameter("num");
	String name = request.getParameter("name");
	String age = request.getParameter("age");
	
	
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<p>번호 : <%=num %></p>
<p>이름 : <%=name %></p>
<p>나이 : <%=age %></p>
</body>
</html>

나이는 null로 나옴.

 

 

ex17 - redirect : 웹 컨테이너는 웹 브라우저에게 주어진 페이지로 이동하라고 명령을 내림. request, response는 초기화된다.

★ 로그인 후, 로그아웃 후, DB의 INSERT, UPDATE, DELETE 작업 후에 실시

더보기
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3> response 객체 : 요청에 대한 응답 정보를 담고 있는 객체</h3>

<%
	response.sendRedirect("ex17_ok.jsp");
%>

<%--
	- redirect
	  : 웹 컨테이너는 웹 브라우저에게 주어진 페이지로 이동하라고 명령을 내림(302 응답 코드를 보냄)
	    -> 웹브라우저는 주어진 주소의 새로운페이지 접속
	  : request, response는 초기화 됨
	  : 로그인 후, 로그아웃 후, DB의 INSERT, UPDATE, DELETE 작업 후 
 --%>

</body>
</html>
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>정보</h3>
<p>
  안녕하세요. redirect된 페이지입니다.
</p>

</body>
</html>

 

ch05

 

ex01 - 계산 : 자바클래스를 이용해서, 스크립릿을 이용해 자바 클래스 생성해서, 스크립릿만을 이용해서

더보기
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<form action="ex01_ok.jsp" method="post">
<p>
	<input type="text" name="num1" required="required" placeholder="수" pattern="\d+">
	<select name="operator">
		<option value="+">더하기</option>
		<option value="-">뻬기</option>
		<option value="*">곱하기</option>
		<option value="/">나누기</option>
	</select>
	<input type="text" name="num2" required="required" placeholder="수" pattern="\d+">
<button type="submit">확인</button>
</form>

</body>
</html>

 

JSP 액션 태그(자바 빈즈)

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<%
	request.setCharacterEncoding("utf-8");
%>
<%-- JSP 액션 태그 --%>
<%--
	Calculator vo = new Calculator(); 와 유사
 --%>
<jsp:useBean id="vo" class="ch05.Calculator"/>

<%-- 
	클래스 안의 동일한 이름을 찾아감 
	vo.setNum1( Integer.parseInt( request.getParameter("num1")) );
	vo.setNum2( Integer.parseInt( request.getParameter("num2")) );
	vo.setOperator( request.getParameter("operator") );
	역할을 함
	
	form 태그 input 요소의 name 속성과 동일한 Calculator 클래스의 필드에 값을 전달
--%>
<jsp:setProperty name="vo" property="*"/>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>액션 태그(자바 빈즈)를 이용한 연산</h3>
<p> <%=vo.toString() %> </p>

</body>
</html>
package ch05;

public class Calculator {
	private int num1;
	private int num2;
	private String operator;

	public int getNum1() {
		return num1;
	}

	public void setNum1(int num1) {
		this.num1 = num1;
	}

	public int getNum2() {
		return num2;
	}

	public void setNum2(int num2) {
		this.num2 = num2;
	}

	public String getOperator() {
		return operator;
	}

	public void setOperator(String operator) {
		this.operator = operator;
	}

	@Override
	public String toString() {
		String s = null;
		
		if(operator == null) return s;
		
		switch(operator) {
		case "+" : s = String.format("%d + %d = %d", num1, num2, num1+num2); break;
		case "-" : s = String.format("%d - %d = %d", num1, num2, num1-num2); break;
		case "*" : s = String.format("%d * %d = %d", num1, num2, num1*num2); break;
		case "/" : s = String.format("%d / %d = %d", num1, num2, num1/num2); break;
		}
		
		return s;
	}
}

 

스크립릿을 이용해서 자바 객체 생성

<%@page import="ch05.Calculator"%>
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<%
	request.setCharacterEncoding("utf-8");

	Calculator vo = new Calculator();
	vo.setNum1( Integer.parseInt( request.getParameter("num1")) );
	vo.setNum2( Integer.parseInt( request.getParameter("num2")) );
	vo.setOperator( request.getParameter("operator") );
	
	String s = vo.toString();
%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>자바 객체를 이용한 연산</h3>
<p> <%= s %> </p>

</body>
</html>

 

스크립릿만을 이용해서

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<%
	request.setCharacterEncoding("utf-8");

	int num1 = Integer.parseInt( request.getParameter("num1") );
	int num2 = Integer.parseInt( request.getParameter("num2") );
	
	String op = request.getParameter("operator");
	String s = "";
	
	// if(op.equals("+")) String.format("%d + %d = %d", num1, num2, num1+num2);
	
	switch(op) {
	case "+" : s = String.format("%d + %d = %d", num1, num2, num1+num2); break;
	case "-" : s = String.format("%d - %d = %d", num1, num2, num1-num2); break;
	case "*" : s = String.format("%d * %d = %d", num1, num2, num1*num2); break;
	case "/" : s = String.format("%d / %d = %d", num1, num2, num1/num2); break;
	}
	
%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>결과</h3>
<p> <%= s %> </p>

</body>
</html>

 

ex02 - 자바 필드의 이름이 다를 경우 자바빈즈를 이용해서 속성값 이름 변경

더보기
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<form action="ex02_ok.jsp" method="post">
 <p> 번호 : <input type="text" name="no"> </p>
 <p> 이름 : <input type="text" name="name"> </p>
 <p> 좋아하는 과목 : <input type="text" name="subject"> </p>
 <p>
 	<button type="submit">등록하기</button>
 </p>
</form>

</body>
</html>
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<%
	request.setCharacterEncoding("utf-8");
%>

<%-- 빈 생성 --%>
<jsp:useBean id="vo" class="ch05.User"/>

<%-- 생성된 빈에 속성 값(파라미터) 값 설정 --%>
<%-- property="*" 는 form안의 input 요소의 name과 User클래스의 필드가 동일한 경우만 설정--%>
<jsp:setProperty property="*" name="vo"/>

<%-- form input요소의 name과 User 클래스의 필드가 다른 경우 --%>
<jsp:setProperty name="vo" property="num" param="no"/>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<p> 번호 : <%= vo.getNum() %></p>
<p> 이름 : <%= vo.getName() %></p>
<p> 좋아하는 과목 : <%= vo.getSubject() %></p>

</body>
</html>

 

forward

더보기
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>forward</h3>
<%--
  - 클라이언트로부터 요청 받은 서블릿(JSP)은 서버의 다른 자원(서블릿, JSP)으로 요청 정보를 전달하여 처리
  - 포워딩은 서블릿 컨테이너에서 이루어 지므로 클라이언트는 알 수 없다.(브라우저 주소줄이 변하지 않음)
  - 요청 받은 페이지는 포워딩 페이지에 request, response 객체를 그대로 전달한다.
  - 요청 받은 페이지가 포워딩 페이지에 새로운 정보를 전달하기 위해서는 request.setAttribute()를 이용한다.
 --%>

<form action="ex03_ok.jsp" method="post">
	<p>이름 : <input type="text" name="name" required="required"></p>
	<p>나이 : <input type="text" name="age" required="required" pattern="\d+"></p>
	<p> <button type="submit">등록하기</button> </p>
</form>
 

</body>
</html>
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<%
	request.setCharacterEncoding("utf-8");

	int age = Integer.parseInt( request.getParameter("age") );
	String s = age >= 19? "성인" : "미성년자";

	
	// 포워딩하는 페이지에 state 전달
	request.setAttribute("state", s); // request.setAttribute(String, Object);
	
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>포워딩하면 이 페이지는 클라이언트 화면에 보이지 않는다.</h3>

<%-- JSP 액션 태그를 이용한 forward --%>
<jsp:forward page="ex03_result.jsp"/>

</body>
</html>
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<%
	request.setCharacterEncoding("utf-8");

	// 포워딩된 페이지는 포워딩한 페이지에서 request, response 객체가 전달되므로 클라이언트가 보낸
	// 파라미터를 받을 수 있다.
	String name = request.getParameter("name");
	int age = Integer.parseInt(request.getParameter("age"));
	
	// 포워딩한 페이지에서 설정한 속성 값 받기
	// request.getAttribute()의 리턴 타입은 Object 이므로 반드시 다운 캐스팅이 필요
	String s = (String)request.getAttribute("state");
	
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<p> <%=name %>님의 나이는 <%=age %>이므로 <%=s %>입니다.</p>

</body>
</html>

 

ex04 - 자바 클래스를 활용한 forward

더보기
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<%
	String cp = request.getContextPath(); // 프로젝트명
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>서블릿 forward</h3>

<form action="<%=cp%>/ch05/demo" method="post">
	<p>이름 : <input type="text" name="name" required="required"></p>
	<p>나이 : <input type="text" name="age" required="required" pattern="\d+"></p>
	<p> <button type="submit">등록하기</button> </p>
</form>

</body>
</html>
package ch05.demo;

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("/ch05/demo")
public class DemoServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// GET 방식으로 요청한 경우
		
		// /study2/ch05/ex04.jsp 로 포워딩
		// forward 할 때 /는 Context Path를 나타낸다.
		forward(req, resp, "/ch05/ex04.jsp");
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// POST 방식으로 요청한 경우
		req.setCharacterEncoding("utf-8"); // POST방식은 필수!
		
		String name = req.getParameter("name");
		int age = Integer.parseInt( req.getParameter("age") );
		
		String state = age >= 19 ? "성인" : "미성년자";
		String msg = name + "님의 나이는 " +age +"입니다. 따라서 " + state + "입니다.";
		
		req.setAttribute("message", msg);
		
		forward(req, resp, "/ch05/ex04_ok.jsp");
	}
	
	protected void forward(HttpServletRequest req, HttpServletResponse resp, String path) throws ServletException, IOException {
		// 서블릿 포워딩 방법
		RequestDispatcher rd = req.getRequestDispatcher(path);
		rd.forward(req, resp);
	}
	
}
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>결과</h3>

<p>
	<%=request.getAttribute("message") %>
</p>


</body>
</html>

인코딩과 디코딩

- 문자를 컴퓨터에 저장하거나 통신에 사용할 목적으로 부호화하는 것을 인코딩(encoding)이라 하며, 반대로 문자를 원래대로 되돌리는 것을 디코딩(decoding)이라 한다.

- HTTP와 같은 통신 프로토콜은 ASCII 문자만을 지원하며, ASCII 문자로 표현할 수 없는 영어 이외의 언어는 전송할 수 없다. 따라서 MIME은 ASCII가 아닌 문자를 인코딩을 이용해 영어가 아닌 다른 언어를 전송할 수 있는 방식을 정의한다.

- HTML 폼은 method="post"인 경우 기본적으로 문자열을 application/x-www-form-urlencoded MIME 형식(enctype 속성을 생략한 경우)으로 인코딩하여 전송한다.

- application/x-www-form-urlencoded MIME 형식 인코딩

공백은 +, 영숫자가 아닌 문자는%HH(문자코드의 16진수 2자리)로 인코딩 된다.

 

파라미터 값의 인코딩 및 디코딩

- 파라미터 값의 인코딩

웹브라우저 : 웹 서버에 파라미터를 전송할 때 알맞은 캐릭터 셋(charset)을 이용해서 파라미터 값을 인코딩

웹 서버 : 알맞은 캐릭터 셋(charset)을 이용해 웹 브라우저가 전송한 파라미터 데이터를 디코딩

캐릭터 셋(charset)종류 : ISO-8859-1(기본), UTF-8, euc-kr 등...

- 웹 브라우저가 'UTF-8'을 이용해 인코딩 했다면 웹 서버는 ;UTF-8'을 이용해 파라미터 값을 디코딩 해야 올바른 파라미터 값을 사용할 수 있다.

- 웹 브라우저가 인코딩 할 때 사용할 캐릭터 셋과 웹 서버가 디코딩 할 때 사용한 캐릭터 셋이 다를 경우 웹 서버가 잘못된 파라미터 값을 사용한다.

 

GET 방식의 파라미터 전송

- a 태그를 이용한 파라미터 전송

<a href="URL키1=값1&키2=값2">텍스트</a>

더보기
<%@ page import="java.net.URLEncoder"%>
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">

<script type="text/javascript">
function send() {
	var name = "자&바";
	var age = 20;
	
	// name을 인코딩하지 않으면 IE는 400에러가 발생하고, 크롬은 '자' 만 전달된다.
	// 자바스크립트를 이용한 인코딩
	name = encodeURIComponent(name); // 주소 형식으로 인코딩 // 매우 중요한 함수!
	
	// GET방식 파라미터(절대로 중간에 공백이 있으면 안됨) : 이름1=값&이름2&값&이름3=값
	var query = "name=" + name + "&age=" + age; // 따옴표 안에는 절대 띄어쓰기 하면 안됌!
	
	// 자바스크립트를 이용하여 GET 방식으로 파라미터 전송
	var url = "ex01_ok.jsp?"+query;
	location.href= url;
}

function sendOk() {
	var f = document.myForm;
	
	// 이름에 "홍%김" 으로 인코딩 안하고 보내면 500 에러
	var name = f.name.value;
	name = encodeURIComponent(name); // name을 인코딩한 것을 
	f.name.value = name; // 다시 form.name 에 넣어줌
	// form의 name에 인코딩된 것으로 변경
	
	f.submit(); // 일반 버튼 등에서 form의 정보를 서버로 전송
}

</script>

</head>
<body>

<h3>파라미터 전송 - GET 방식</h3>

<p>
  - 기본적으로 클라이언트가 서버에 접속하는 경우 파라미터 전송 방식은 GET 방식이다.<br>
  - Query String : GET 방식으로 전송되는 파라미터<br>
  - 주소줄에 파라미터를 실어서 보냄<br>
    <%-- 형식 : 주소?이름=값&이름=값 --%>
  - GET 방식으로 정보를 보낼 때 한글 등은 반드시 인코딩해서 보낸다.<br>
</p>
<hr>

<!-- a 태그를 이용하여 GET방식으로 파라미터 전송 -->
<p>
	<!-- ex01_ok.jsp?name=%ED%99%8D%EA%B8%B8%EB%8F%99&age=20 -->
	<!-- 한글을 인코딩하지 않고 GET방식으로 전공하면 IE에서는 400에러가 발생한다. -->
	<a href="ex01_ok.jsp?name=홍길동&age=20">확인</a> |
	
	<!-- 자바를 이용하여 한글 인코딩 -->
	<a href="ex01_ok.jsp?name=<%=URLEncoder.encode("홍길동", "utf-8")%>&age=20">확인</a>
</p>
<hr>

<!-- 자바스크립트를 이용하여 GET방식으로 파라미터 전송 -->
<p>
	<button type="button" onclick="send();">확인</button>
</p>
<hr>

<!-- form 태그를 이용한 GET 방식 전송 : form 태그를 이용한 GET 방식 전송은 거의 사용하지 않는다. -->
<!-- form 태그를 이용하여 GET 방식으로 전송할 때 method를 생략하면 GET 방식으로 전송된다. -->
<form name="myForm" action="ex01_ok.jsp">
	<p> 이름 : <input type="text" name="name"></p>
	<p> 나이 : <input type="text" name="age"></p>
	<p>
		<button type="button" onclick="sendOk();">전송</button>
		<!-- type="button"은 전송이 되지 않음 -->
	</p>
</form>

</body>
</html>
<%@page import="java.net.URLDecoder"%>
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<%
	// request : 클라이언트가 보낸 요청 정보를 담고 있는 내장 객체
	
	// 클라이언트가 보낸 파라미터 받기
	// GET 방식으로 넘어온 인코딩된 데이터를 디코딩하지 않으면 WAS 따라 한글이 깨질 수 있다.
	String name= request.getParameter("name");
	// 자바에서 인코딩된 정보를 디코딩
	name = URLDecoder.decode(name, "utf-8");
	
	int age = Integer.parseInt(request.getParameter("age"));
	String state = age >= 19? "성인" : "미성년자";
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>GET 방식으로 전달받은 파라미터를 이용한 처리 결과</h3>

<p>
	<%=name %>님의 나이는 <%=age %>세 이므로 <%=state %>입니다.
</p>

</body>
</html>

 

- JavaScript의 location.href 속성을 이용한 파라미터 전송

lovation.href="URL?키1=값1&키2=값2";

- form태그를 이용한 전송

form 태그는 method 속성을 지정하지 않으면 기본으로 GET 방식으로 파라미터를 전송한다.

- GET 방식은 개발자가 직접 인코딩과 디코딩 작업을 해야한다.

 

 

POST 방식의 파라미터 전송

- 일반적으로 POST 방식으로 파라미터를 전송하기 위해서는 form 태그를 이용하여 전송한다.

- form 태그의 method 속성을 method="post"로 지정하면 POST 방식으로 파라미터를 전송한다.

- POST 방식에 의해 전달받은 파라미터 값을 디코딩 할 때 사용할 캐릭터 셋을 지정

request.setCharacterEncoding("utf-8"); 

더보기
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>파라미터 전송 - POST방식</h3>
<p>
  - POST 방식으로 파라미터를 전송하면 body에 정보를 실어서 보냄<br>
  - POST 방식은 용량에 제한이 없음<br>
  - POST 방식은 form 태그의 method="post"를 통해 전송됨<br>
  - form 태그의 method="post"에서 기본 enctype 설정은
  	enctype="application/x-www-form-urlencoded" 이다.<br>
  	enctype은 문자의 인코딩 방식을 지정하며, 
  	x-www-form-urlencoded는 주소 형식으로 데이터를 인코딩해서 정보를 보낸다.
</p>
<hr>

<form action="ex02_ok.jsp" method="post" >
	<p> 이름 : <input type="text" name="name"></p>
	<p> 나이 : <input type="text" name="age"></p>
	<p>
		<button type="submit">보내기</button>
	</p>
</form>

</body>
</html>
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<%
	// POST 방식으로 넘어온 파라미터의 인코딩 설정
	// POST 방식에서는 파라미터를 받기 전 반드시 아래처럼 문자 인코딩 파라미터를 설정해야 하며
	// 		설정하지 않는 경우에는 한글이 깨진다.
	request.setCharacterEncoding("utf-8"); // 위치가 바뀌면 안됨!
	
	String name= request.getParameter("name");
	int age = Integer.parseInt(request.getParameter("age"));
	String state = age >= 19? "성인" : "미성년자";
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>POST 방식으로 전달받은 파라미터를 이용한 처리 결과</h3>
<p>
	<%=name %>님의 나이는 <%=age %>세 이므로 <%=state %>입니다.
</p>


</body>
</html>

 

form 태그 안에 있는 submit 버튼의 종류

더보기
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>form 데이터 서버로 전송 - submit 버튼</h3>
<p>
  - form 태그 안에 있는 submit 버튼은 서버로 전송할 수 있는 기능이 있다.<br>
  <!-- [submit 버튼 종류] -->
  <!--  1. <button>확인</button> -->
  <!--  2. <button type="submit">확인</button> -->
  <!--  3. <input type="submit" value="확인"> -->
  <!--  4. <input type="image" src="이미지"> -->
  
  <!-- [input 태그의 required 속성] -->
  <!--  input 태그가 form 안에 있어야 하고 submit 버튼을 누를 때만 반응함 -->
</p>
<hr>

<form action="ex03_ok.jsp" method="post">
	<p>이름 : <input type="text" name="name" required="required"></p>
	<p>나이 : <input type="text" name="age" required="required"></p>
	<p>
		<button>확인</button> |
		<button type="submit">확인</button> |
		<input type="submit" value="확인"> |
		<input type="image" src="btn_submit.gif" style="vertical-align: bottom;"> | 
		<!-- inline 태그 안에서만 vertical-align 사용가능 -->
		<button type="button">일반버튼</button>
	</p>
	
</form>

</body>
</html>
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<%
	request.setCharacterEncoding("utf-8"); // 위치가 바뀌면 안됨!
	
	String name= request.getParameter("name");
	int age = Integer.parseInt(request.getParameter("age"));
	String state = age >= 19? "성인" : "미성년자";
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>처리 결과</h3>
<p>
	<%=name %>님의 나이는 <%=age %>세 이므로 <%=state %>입니다.
</p>


</body>
</html>

form 태그안의 submit 버튼을 이용해 서버로 데이터를 보내기 전에 form 태그의 onsubmit 속성을 이용해 유효성 검사하기

더보기
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">

<script type="text/javascript">
function check() {
	var f = document.myForm;

	if(! /^[가-힣]{2,5}$/.test(f.name.value) ) {
		alert("이름을 입력 하세요");
		f.name.focus();
		return false;
	}
	
	if(! /^(\d){1,3}$/.test(f.age.value) ) {
		alert("나이를 입력 하세요");
		f.age.focus();
		return false;
	}
	
	// 주의!!!
	// submit 버튼에서 f.submit(); 처럼 form의 submit() 함수를 호출하면 서버에 두 번 전송된다.
	
	return true;


}

</script>

</head>
<body>

<h3>form 데이터 서버로 전송 - submit 버튼 : 유효성 검사</h3>
<p>
  - form 태그 안의 submit 버튼을 클릭하면 submit 이벤트가 발생한다. <br>
  - submit 버튼을 사용하는 경우 유효성 검사는 submit 이벤트 핸들러에서 한다.<br>
  - submit 이벤트 핸들러에 false를 반환하면 서버로 전송되지 않는다.
</p>
<hr>

- 이름 한글 2~5자
- 나이는 한자 이상의 숫자

<form name="myForm" action="ex04_ok.jsp" method="post" onsubmit="return check();">
	<p>이름 : <input type="text" name="name"></p>
	<p>나이 : <input type="text" name="age"></p>
	<p>
		<button type="submit">확인</button>
		<button type="reset">다시 입력</button>
		<!-- reset 버튼은 form 태그 안에서만 동작한다. -->
	</p>
</form>

</body>
</html>
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<%
	request.setCharacterEncoding("utf-8"); // 위치가 바뀌면 안됨!
	
	String name= request.getParameter("name");
	int age = Integer.parseInt(request.getParameter("age"));
	String state = age >= 19? "성인" : "미성년자";
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>처리 결과</h3>
<p>
	<%=name %>님의 나이는 <%=age %>세 이므로 <%=state %>입니다.
</p>


</body>
</html>

 

form 태그안에 일반 버튼을 이용해 서버로 데이터를 보내기 전에 onclick으로 유효성 검사

더보기
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">

<script type="text/javascript">
function sendOk() {
	var f = document.myForm;

	if(! /^[가-힣]{2,5}$/.test(f.name.value) ) {
		alert("이름을 입력 하세요");
		f.name.focus();
		return;
	}
	
	if(! /^(\d){1,3}$/.test(f.age.value) ) {
		alert("나이를 입력 하세요");
		f.age.focus();
		return;
	}

	f.action = "ex05_ok.jsp"; //서버 주소
	f.submit(); // 일반 버튼 등에서 form의 내용을 서버로 전송

}

</script>

</head>
<body>

<h3>form 데이터 서버로 전송 - 일반 버튼 : 유효성 검사</h3>
<p>
  - form 태그 안의 내용을 일반 버튼을 이용하여 서버로 전송하기 위해서는 
    form 객체의 submit() 함수를 호출한다. <br>
  - submit() 함수를 이용하여 서버로 전송하는 경우 submit 이벤트는 발생되지 않는다.<br>
</p>
<hr>

<form name="myForm" method="post">
	<p>이름 : <input type="text" name="name"></p>
	<p>나이 : <input type="text" name="age"></p>
	<p>
		<button type="button" onclick="sendOk();">확인</button>
		<button type="reset">다시 입력</button>
		<!-- reset 버튼은 form 태그 안에서만 동작한다. -->
	</p>
</form>

</body>
</html>
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<%
	request.setCharacterEncoding("utf-8"); // 위치가 바뀌면 안됨!
	
	String name= request.getParameter("name");
	int age = Integer.parseInt(request.getParameter("age"));
	String state = age >= 19? "성인" : "미성년자";
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>처리 결과</h3>
<p>
	<%=name %>님의 나이는 <%=age %>세 이므로 <%=state %>입니다.
</p>


</body>
</html>
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<%
	int row = 10;
	int col = 10;
	int n = 0;
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
<style type="text/css">
* {
	margin: 0; padding: 0;
	box-sizing: border-box;
}

.layout {
	margin: 30px auto;
	width: <%=col*30%>px;
}

.table {
	width: 100%;
	border-spacing: 0;
	border-collapse: collapse;
}

.table td {
	text-align: center;
	padding: 3px; 
}
</style>

<script type="text/javascript">
function sendOk() {
	var f = document.frm;
	
	var cnt = 0;
	var arr = [];
	
	for(var i=0; i<f.chk.length; i++) {
		if(f.chk[i].checked) { // 이름이 동일한 것이 여러 개 있으므로 배열로 처리
			cnt++;
			arr.push(f.chk[i].value);
		}
	}
	
	if(cnt==0) {
		alert("선택 항목이 없습니다.");
		return;
	}
	
    alert('선택한 체크박스는 ' + arr.join() + ' 입니다.');
}
</script>

</head>
<body>

<div class="layout">
<form name="frm">
	<table class="table">
		<%for(int i=1; i<=row; i++) { %>
			<tr>
				<% for(int j=1; j<=col; j++) { %>
					<td>
						<input type="checkbox" name="chk" value="<%= (++n) %>">
					</td>
				<% } %>
			</tr>
		<% } %>
	</table>
	
	<table class="table">
		<tr>
			<td style="text-align: right;">
				<button type="button" onclick="sendOk()">확인</button>
			</td>
		</tr>
	</table>
</form>
</div>

</body>
</html>

JSP 주석

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<%
	// 2번째 줄 : 불필요한 공백 제거 
	// 스크립릿(java 코드 영역) - java 주석(자바코드 영역에서만 가능)
	int s = 0;
	for(int i = 1; i<=100; i++) {
		s += i;
	}

%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3> JSP 주석 </h3>

<!-- HTML 주석 : 클라이언트에게 전송됨 (네트워크 사용) -->
<%-- JSP 주석 : 클라이언트에게 전송되지 않음 --%>
<p>
	1에서 100까지 합은 <%=s%> 입니다.
</p>

</body>
</html>

표현식

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>표현식</h3>

<p>
  자바 코드의 결과를 클라이언트에게 전송하기 위해 사용한다.<br>
  표현식은 out.print(코드); 형식의 자바 코드로 변환 된다.<br>
  표현식은 서버측에서 실행되고 실행결과(문자열)을 클라이언트에게 전송한다.
</p>
<hr>

<p>
	합 : <%= 1+2+3+4+5 %>
</p>
<p>
	<%
		// 스크립 릿
		int n = 10;
		String result = n%2 == 0 ? "짝수" : "홀수";
	%>
	<%= n %>은 <%=result %> 입니다.
	
</p>

</body>
</html>

JSP 지시어(directive) 

page 지시어 - JSP 페이지의 설정 정보 지정

<!-- page의 contentType 속성 : 클라이언트에게 전송하는 문서의 타입 설정. 생략하면 인코딩은 ISO-8859_1로 설정 -->
<%@ page contentType="text/html; charset=UTF-8"%>

<!-- page의 import 속성 : 필요한 자바 클래스 import -->
<%@ page import="java.util.Calendar"%>

<!-- 불필요한 공백 제거 -->
<%@ page trimDirectiveWhitespaces="true"%>

<%
	Calendar cal = Calendar.getInstance();

	String s = String.format("%tF %tT", cal, cal);
%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>지시어(directive)</h3>

<p>
  page 지시어 : JSP 페이지의 설정 정보 지정<br>
</p>

<p>
	<%=s %>
</p>


</body>
</html>

page 지시어 buffer : 출력할 버퍼의 크기 지정 / autoFlish : 버퍼가 찬 경우 버퍼를 비울지의 여부를 지정

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page buffer="1kb" autoFlush="true" %>
<%@ page trimDirectiveWhitespaces="true"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>page 지시어(directive)</h3>

<p>
  page 지시어 : JSP 페이지의 설정 정보 지정<br>
  buffer : 출력할 버퍼의 크기 지정<br>
  autoFlush : 버퍼가 찬 경우 버퍼를 비울지의 여부를 지정(기본:true-버퍼를 비움) 
</p>

<!-- 
	buffer의 크기가 1kb이고 autoFlush="false" 환경에서 출력 내용이 4kb가 넘으므로 오류가 발생함.
	autoFlush="true"로 변경하면 에러가 없어짐
-->
<% for(int i=1; i<=1000; i++) { %>
	1234
<% } %>
</body>
</html>

page 지시어 errorPage 속성 : 에러가 발생할 경우 보여줄 페이지 지정

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page errorPage="error.jsp" %>
<%@ page trimDirectiveWhitespaces="true"%>

<%
	String s = "a";
	int n = Integer.parseInt(s); 
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>page 지시어(directive)</h3>
<p> errorPage 속성 : 에러가 발생할 경우 보여줄 페이지 지정</p>
<hr>

<p><%= n %></p>

</body>
</html>
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page isErrorPage="true" %> <!-- 에러가 발생할 때 보여지는 페이지임을 설정 -->
<%@ page trimDirectiveWhitespaces="true"%>
<%
	// 에러 페이지가 아닌 정상적인 페이지임을 설정
	response.setStatus(HttpServletResponse.SC_OK);
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>정보</h3>
<p>
	에러가 발생했습니다. 잠시 후 다시 실행 하세요.
</p>

</body>
</html>

include 지시어

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>include지시어</h3>

<p>
  JSP 페이지에 다른 페이지의 내용을 포함할 때 사용한다.<br>
  JSP 파일을 JAVA로 변환할 때 처리하며, 복사&amp;붙여넣기 개념과 유사하다.
</p>
<hr>

<%@ include file="ex07_inc.jsp" %>

<p>
  <%=name %> 홈페이지 입니다.
</p>

</body>
</html>
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<%
	String name = "이자바";
%>
<h3>환영합니다.</h3>

스크립릿, 표현식 예

(1) 방법

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>

<%
	int row = 10;
	int col = 7;
	int n = 0;
%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>스크립릿, 표현식 예</h3>

<table border="1" style="margin: 30px auto; width: <%=col*50%>px; border-collapse: collapse;">
<% for(int i=1; i<=row; i++) { %>
	<tr height="30px" align="center">
	<% for(int j=1; j<=col; j++) { %>
		<td><%= ++n %></td>
	<% } %>	
	</tr>
<% } %>
</table>

</body>
</html>
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>

<%
	int row = 10;
	int col = 7;
	int n = 0;
%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>스트립릿, 표현식 예</h3>
<p>
 out 객체 : JSP 내장 객체로 클라이언트에게 정보(문자열)를 전송하는 객체이다.
</p>
<hr>

<table border="1" style="margin: 30px auto; width: <%=col*50%>px; border-collapse: collapse;">
<%
	for(int i=1; i<=row; i++) {
		out.print("<tr height='30' align='center'>");
		for(int j=1; j <=col; j++) {
			out.print("<td>" +(++n)+"</td>");
		}
		out.print("</tr>");
	}
%>
</table>

</body>
</html>

구구단 짜보기

더보기
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
<style type="text/css">
p {
	margin: 0;
}
</style>
</head>
<body>

<h3>표현식, 스크립릿</h3>
<hr>

<h4>구구단 - 방법1</h4>
<% for(int dan=2; dan<=9; dan++) { %>
	<p>** <%=dan %>단 **</p>
	<%for(int n=1; n<=9; n++) { %>
		<p><%= dan %> * <%= n %> = <%= dan*n %></p>
	<% } %>
	<p>----------------</p>
<% } %>

<h4>구구단 - 방법2</h4>
<%
	for(int dan=2; dan<= 9; dan++) {
		out.print("<p>** " + dan + "단 **</p>");
		for(int n=1; n <=9; n++) {
			out.print("<p>" + dan +" * " + n +" = "+ (dan*n) +"</p>");
		}
		out.print("<p>-------------</p>");
	}
%>
</body>
</html>

 

(1) JSP 예제

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

<%
// 자바를 짜는 영역임
	Calendar now = Calendar.getInstance();
	String s = String.format("%tF %tA %tT", now, now, now);
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

<h3>JSP 첫 번째 - 예제</h3>

<p>
	지금 시간은 <span style="color: tomato;"> <%= s %> </span> 입니다.
</p>

</body>
</html>

 

(2) Servlet 예제

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

<h3>서블릿 예제 - 파라미터 전달 예</h3>

<p>
	<a href="/study2/test?name=Lee&age=19">확인</a>
</p>
<hr>

<form action="/study2/test" method="post">
	<p> 이름 : <input type="text" name="name"></p>
	<p> 나이 : <input type="text" name="age"></p>
	<p>
		<button type="submit">확인</button>
	</p>
</form>

</body>
</html>
package com.test;

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;

// web.xml 이 선택사항인 이유는 annotation을 이용할 수 있기 때문이다.
@WebServlet("/test") // 클라이언트가 주소줄에 test라고 요청하면, 의 의미이다.
public class TestServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// 클라이언트가 GET 방식으로 요청한 경우 실행
		// GET : 기본 요청방식으로 주소줄에 파라미터를 전달, 보안에 취약
		
		try {
			// 클라이언트가 보낸 파라미터를 받는다.
			String name = req.getParameter("name");
			int age = Integer.parseInt(req.getParameter("age"));
			
			// 처리
			String state = age >= 19 ? "성인" : "미성년자";

			// 처리 결과를 클라이언트에게 전송 한다.
			resp.setContentType("text/html; charset=utf-8");

			PrintWriter out = resp.getWriter();
			out.println("<html>");
			out.println("<head><title>servlet 예제</title></head>");
			out.println("<body>");
			out.println("<h3> GET방식으로 요청한 처리 결과 </h3>");
			out.println("<p>" + name + "님의 나이가 " + age + "이므로 <b>" + state + "</b>입니다.</p>");
			out.println("</body>");
			out.println("</html>");

		} catch (Exception e) {
			getServletContext().log("error!!", e);
		}
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// 클라이언트가 POST 방식으로 요청한 경우 실행
		// POST : <form method="post" action ... ></form> 을 통해서 요청
		// 		  body 부분에 정보를 보냄
		
		try {
			// 요청한 정보의 문자 인코딩 설정. 이 줄을 생략하면 한글이 깨짐.
			req.setCharacterEncoding("utf-8");
			
			// 클라이언트가 보낸 파라미터를 받는다.
			String name = req.getParameter("name");
			int age = Integer.parseInt(req.getParameter("age"));
			
			// 처리
			String state = age >= 19 ? "성인" : "미성년자";

			// 처리 결과를 클라이언트에게 전송 한다.
			resp.setContentType("text/html; charset=utf-8");

			PrintWriter out = resp.getWriter();
			out.println("<html>");
			out.println("<head><title>servlet 예제</title></head>");
			out.println("<body>");
			out.println("<h3> POST방식으로 요청한 처리 결과 </h3>");
			out.println("<p>" + name + "님의 나이가 " + age + "이므로 <b>" + state + "</b>입니다.</p>");
			out.println("</body>");
			out.println("</html>");

		} catch (Exception e) {
			getServletContext().log("error...", e);
		}
		
	}

}

 

서블릿 이란?

- 서버에서 웹 페이지 등을 동적으로 생성하거나 데이터 처리를 수행하기 위해 자바(Java)로 작성된 프로그램

- 자바 서블릿은 서버 측 기능을 확장시킨 자바 프로그램으로, 자바EE(JavaEE, Java Platform Enterprise Edition)의 한 기능이다.

- 서블릿은 javax.servlet.GenericServlet클래스를 상속받아 작성하거나, HTTP protocol 서비스를 지원하는 javax.servlet.http.HttpServlet 클래스를 상속받아 작성한다.

- 서블릿은 Servlet Container에 의해서 실행되고, 관리된다.

- 서블릿은 자바 코드 안에 HTML을 포함하고 있어서 그 효율성이 떨어진다. HTML 변경 시 서블릿을 재 컴파일해서 배포해야 한다.

 

Servlet Container

- HTTP 요청을 받아서 Servlet을 실행시키고, 그 결과를 사용자 브라우저에게 전달해주는 기능을 제공한다.

- Servlet을 실행하고 생명주기를 관리하는 역할을 한다.

- 멀티 스레딩을 지원하여 클라이언트의 다중 요청을 스레드를 이용하여 처리한다. 서블릿 컨테이너는 해당 서블릿의 요청이 들어오면 스레드를 생성해서 작업을 수행한다.

 

Servlet의 Life Cycle

- Servlet은 init(), service(), destroy()의 세 개의 메소드에 의한 생명주기를 갖는다.

- 클라이언트가 Servlet을 요청하는 경우 다음의 단계를 실행한다.

1) 해당 서블릿의 인스턴스가 존재하지 않는 경우

(1) Servlet 클래스를 로드하여 서블릿 클래스의 인스턴스를 생성한다.

(2) init() 메소드를 호출하여 서블릿 인스턴스를 초기화한다.

(3) 해당 서블릿의 인스턴스가 존재하는 경우에는 (1), (2)번의 과정은 실행하지 않는다.

2) request와 response 객체를 인수로 전달하여 service() 메소드를 호출, 클라이언트의 요청을 처리하여 처리 결과를 전송한다.

- service() 메소드는 클라이언트의 요청이 있을 때마다 반복적으로 호출하여 클라이언트 요청을 처리한다.

- 클라이언트가 서블릿을 요청하면 컨테이너는 스레드를 생성하여 병행적으로 service() 메소드를 호출된다.

- 서블릿을 javax.servlet.HttpServlet 클래스를 상속 받아 작성했다면 service() 메소드는 클라이언트의 요청방식에 따라 GET 방식이면 doGet()메소드를, POST 방식이면 doPost() 를 호출한다.

3) 서블릿을 제거해야 하는 경우 컨테이너는 서블릿의 destroy()메소드를 실행하고, 서블릿을 종료한다. 일반적으로 데이터베이스 연결 해제, 백그라운드 스레드 중지 등 사용한 자원을 종료한다.

웹 어플리케이션 ?

웹 브라우저의 요청에 대하여 처리해서 결과를 보여주는 프로그램을 의미한다.

 

웹 어플리케이션 구성요소

1) 웹 브라우저 : 사용자에게 화면(User Interface)을 제공한다.

2) 웹 서버 : HTTP를 통해 웹 브라우저와 같은 클라이언트에서 요청하는 HTML 문서나 CSS, JavaScript, 오브젝트(image 등) 등의 웹 페이지를 전송해주는 서비스 프로그램

3) WAS ( Web Application Server) : 인터넷 상에서 HTTP를 통해 사용자 컴퓨터나 장치에 애플리케이션을 수행해 주는 미들웨어(소프트웨어 엔진)로, Server 단에서 Application을 동작할 수 있도록 지원한다.

4) 데이터베이스 : 웹 어플리케이션이 필요로 하는 데이터를 저장한다.

 

웹 어플리케이션 종류

1) CGI(Common Gateway Interface) 

2) ASP (Active Server Page)와 ASP.NET

3) PHP (Hypertext Preprocessor)

4) Servlet

- 서버에서 웹 페이지 등을 동적으로 생성하거나 데이터 처리를 수행하기 위해 자바(Java)로 작성된 프로그램

- 자바 서블릿은 서버 측 기능을 확장시킨 자바 프로그램으로, 자바 EE(JavaEE, Java Platform Enterprise Edition)의 한 기능이다.

- 서블릿은 자바 코드 안에 HTML을 포함하고 있어서 그 효율성이 떨어진다.

5) JSP(Java Server Pages)

- JSP는 HTML내에 자바 코드를 삽입하여 웹 서버에서 동적으로 웹 페이지를 생성하여 웹 브라우저에 돌려주는 언어이다.

- JavaEE 스펙 중 일부로 웹 애플리케이션 서버에서 동작한다.

 

HTTP(HyperText Transfer Protocol)

1) 개요

- 인터넷에서 하이퍼텍스트(hypertext) 문서를 교환하기 위해 사용되는 통신규약.

- HTTP는 TCP/IP 위에서 작동하며, 서버/클라이언트 모델을 따른다. 클라이언트에서 요청(request)를 보내면 서버는 요청을 처리해서 응답(response)한다.

- HTTP는 connection less방식(stateless)이다. 클라이언트의 요청에 서버가 응답한 후 클라이언트와 연결을 끊는 구조로 network 속도가 느린 단점을 가지고 있다. 이를 개선하기 위해 HTTP 1.1 부터는 Keep Alive 기능을 지원한다. Keep Alive 기능은 일정한 시간(timeout)동안 접속을 유지하는 기능이다.

- 클라이언트가 서버에 접속하여 어떠한 요청을 하면, 서버는 세 자리 수로 된 응답 코드와 함께 응답한다.

- 응답코드는 응답헤더의 첫 번째 줄에 위치하여, 주요 응답 코드는 다음과 같다.

HTTP/1.1 200 : OK, HTTP/1.1 404 : Not Found, HTTP/1.1 500 : Internal error

- HTTP URL은 "http://"로 시작하며, 기본 포트번호는 80이다.

 

2) HTTP요청(request)과 응답(response)주요 구성 요소

(1) HTTP 요청(request) 주요 구성 요소

- HTTP 메소드

- 접근하고자 하는 URL

- 폼 파라미터

(2) HTTP 응답(response) 주요 구성 요소

- 상태 코드(요청 처리에 대한 성공 여부)

- 컨텐츠 타입(text/html, text/css, text/xml 등)

- 컨텐츠(HTML 소스, 이미지 등)

(3) HTTP 메소드

- HTTP 프로토콜을 사용하여 서버로 요청을 보내는 방법을 Method라 한다.

- 종류 

GET : 정보를 요청하기 위하여 사용한다. (SELECT)

POST : 클라이언트가 웹 서버에 데이터를 전달할 때 사용한다. (INSERT)

PUT : 정보를 업뎅트하기 위해서 사용한다. HTML 5는 지원하지 않음(UPDATE)

DELETE : 정보를 삭제하기 위해서 사용한다. HTML 5는 지원하지 않음(DELETE)

HEAD : (HTTP) 헤더 정보만 요청한다. 해당 자원이 존재하는지 혹은 서버에 문제가 없는지를 확인하기 위해서 사용한다.

OPTIONS : 웹 서버가 지원하는 메소드의 종류를 요청한다.

TRACE : 클라이언트의 요청을 그대로 반환한다. echo 서비스로 서버 상태를 확인하기 위한 목적으로 주로 사용한다.

- 보통 웹 서비스들은 GET과 POST만을 이용해서 개발한다.

 

HTTPS(HyperText Transfer Protocol over Secure Socket Layer)

- HTTP는 기본적으로 평문 데이터 전송을 원칙으로 하기 때문에 개인의 프라이버시가 오가는 서비스들(전자상거래, 전자메일, 사내문서)에 사용하기 힘들다.

- HTTP는 SSL 레이어 위에 HTTP를 통과 시키는 방식이다. 즉 평문의 HTTP 문서는 SSL 레이어를 통과하면서 암호화 돼서 목적지에 도착하고, 목적지에서는 SSL 레이어를 통과하면서 복호화돼서 웹 브라우저에 전달된다.

- SSL은 전자상거래에서의 데이터 보안을 위해서 개발한 통신 레이어다. SSL은 표현계층의 프로토콜로 응용 계층 아래에 있기 때문에, 어떤 응용 계층의 데이터라도 암호화해서 보낼 수 있다.

- HTTPS는 인증서를 이용해서, 접속 사이트를 신뢰할 수 있는지 평가할 수 있다.

- 일반적으로 HTPS는 HTTP에 비해서 느리다. 많은 양의 데이터를 처리할 경우 성능의 차이를 체감할 수 있다.

- HTTPS URL은 "https://"로 시작한다.

- 기본 포트번호는 443이다.

 

URL과 URI

URL(Uniform Resource Locator)

- 네트워크 상에서 자원이 어디 있는지를 알려주기 위한 규약이다.

- URL은 웹 사이트 주소뿐만 아니라 컴퓨터 네트워크상의 자원을 모두 나타낼 수 있으며, 해당 URL에 맞는 프로토콜을 이용하여 접속한다.

- URL은 인터넷 도메인 이름이나 IP주소, 이메일, 파일 전송과 같이 컴퓨터 네트워크 정보자원을 이용하는 모든 형태에 적용된다.

- 하위 개념으로 URL(Uniform Resource Locator), URN(Uniform Resource Name)이 있다.

 

웹 컨테이너(Web Container) ?

- JSP와 서블릿을 실행할 수 있는 소프트웨어를 웹 컨테이너(Web Container) 또는 서블릿 컨테이너(Servlet Container)라고 한다.

- 순수 서블릿을 처리하는 경우 서블릿 컨테이너라 부르는데, 서블릿 컨테이너를 포함한 JSP, HTTP 서버로서의 기능을 포함하기 때문에 웹 컨테이너라고 부르기도 한다.

- Apache Tomcat, IBM Web Sphere 어플리케이션 서버, Resin, 티맥스의 JEUS, 이클립스 재단의 jetty 등이 있다.

 

웹 컨테이너(Web Container)의 역할 및 특징

- 서블릿의 생명주기를 관리하고, URL과 특정 서블릿을 맵핑하며 URL 요청이 올바른 접근 권한을 갖도록 보장한다.

- 서블릿, JSP 등에 대한 요청을 다룬다.

- 서블릿 객체의 생성 및 초기화, 요청과 응답 객체 생성 및 관리 등의 작업을 수행한다.

- 웹 응용 프로그램의 보안, 병행성, 생명주기 관리 등의 서비스를 제공한다.

 

Apache Tomcat

- 아파치 소프트웨어 재단에서 개발한 서블릿 컨테이너만 있는 웹 애플리케이션 서버(WAS)

- 톰캣은 웹 서버와 연동하여 실행할 수 있는 자바 환경을 제공하여 자바 서버 페이지(JSP)와 자바 서블릿이 실행될 수 있는 환경을 제공한다.

 

+ Recent posts