게시판 URI 및 JSP 생각하기

 

1. URI 및 JSP
  1) 리스트
 uri : /cp/bbs/list.do
 jsp : /WEB-INF/views/bbs/list.jsp
 
  2) 글쓰기 폼
 uri : /cp/bbs/write.do
 jsp : /WEB-INF/views/bbs/write.jsp

  3) 글쓰기 완료
 uri : /cp/bbs/write_ok.do -> list.do 로 리다이렉트

  4) 글보기
 uri : /cp/bbs/article.do
 jsp : /WEB-INF/views/bbs/article.jsp
 
  5) 글수정 폼
 uri : /cp/bbs/update.do
 jsp : /WEB-INF/views/bbs/write.jsp  

  6) 글수정 완료
 uri : /cp/bbs/update_ok.do -> list.do 로 리다이렉트

  7) 글삭제
 uri : /cp/bbs/delete.do -> list.do 로 리다이렉트

 

2. 흐름도와 파라미터(클라이언트가 서버에 보내는 값)
  1) 리스트

- 리스트 --> 리스트 : 페이지번호클릭(페이지번호[, 검색컬럼, 검색값])
- 리스트 --> 리스트 : 검색(검색컬럼, 검색값)
- 리스트 --> 리스트 : 초기화(검색 해제)
- 리스트 --> 글쓰기폼 : 등록하기 버튼
- 리스트 --> 글보기 : 제목클릭(글번호, 페이지번호[, 검색컬럼, 검색값])

  2) 글쓰기폼
- 글쓰기폼 --> 등록하기 : 글저장 --> 리스트로 리다이렉트
                |
           (폼 데이터 : 제목, 작성자, 내용, 패스워드)
- 글쓰기폼 --> 등록취소 : 리스트로 가기

  3) 글보기
- 글보기 --> 리스트 : 리스트버튼(페이지번호[, 검색컬럼, 검색값])
- 글보기 --> 글보기 : 이전글/다음글(이전글/다음글번호, 페이지번호[, 검색컬럼, 검색값])
- 글보기 --> 수정폼 : 수정버튼(글번호, 페이지번호)
- 글보기 --> 글삭제 : 삭제버튼(페이지번호[, 검색컬럼, 검색값])

  4) 글수정폼
- 글수정폼 --> 수정완료 : 글수정버튼--> 리스트로 리다이렉트(글보기로 리다이렉트)
                |
         (폼 데이터 : 제목, 작성자, 내용, 패스워드, 글번호, 페이지번호) // 수정할게시글번호!!
- 글수정폼 --> 수정취소 : 리스트로 가기

  5) 글삭제 --> 리스트로 리다이렉트(페이지번호[, 검색컬럼, 검색값])

 

 

자유게시판으로 사용할 DB table

더보기

-- 게시판 테이블
CREATE TABLE bbs (
num NUMBER NOT NULL,
name VARCHAR2(30) NOT NULL,
pwd VARCHAR2(50) NOT NULL,
subject VARCHAR2(255) NOT NULL,
content VARCHAR2(4000) NOT NULL, -- 1300자 이상 저장을 위해서는 CLOB
ipAddr VARCHAR2(50) NOT NULL,
hitCount NUMBER DEFAULT 0,
reg_date DATE DEFAULT SYSDATE,
CONSTRAINT pk_bbs_num PRIMARY KEY(num)
);

-- 게시판 시퀀스
CREATE SEQUENCE bbs_seq
INCREMENT BY 1;
START WITH 1
NOMAXVALUE
NOCYCLE
NOCACHE;

 

페이징 처리에 사용하는 쿼리 Query

더보기

-- ORACLE :

 

아래 쿼리는 오라클에서 성능이 우수함
SELECT * FROM (
    SELECT ROWNUM rnum, tb.* FROM (
        SELECT num, name, subject, hitCount, 
            TO_CHAR(reg_date, 'YYYY-MM-DD') reg_date
        FROM bbs
        ORDER BY num DESC
    ) tb WHERE ROWNUM <= 끝
) WHERE rnum >= 시작;
-- 수정/삭제가 빈번히 일어나는 경우 index의 성능이 좋지 않음.

-- ORACLE 12C 이상 : 위 쿼리보다 성능이 좋지 않음
SELECT num, name, subject, hitCount,
    TO_CHAR(reg_date, 'YYYY-MM-DD') reg_date
FROM bbs
ORDER BY num DESC
OFFSET 30 ROWS FETCH FIRST 10 ROWS ONLY;
---------------------------------
-- MySQL
SELECT num, name, subject, hitCount,
    DATE_FORMAT(reg_date, '%Y-%m-%d') AS reg_date
FROM bbs
ORDER BY num DESC
LIMIT 건너뛸개수, 가져올개수;

 

페이징 처리 로직

 

Example

페이지당 게시글 10개

전체 데이터 개수 965개

-> 전체 페이지 개수는 97개

페이지당 게시글 10개

전체 데이터 개수 960개

-> 전체 페이지 개수는 96개

 

즉, (전체 데이터 개수 / 페이지당 게시글) 에서 소수점이하가 없으면 ( 나머지가 없으면) 몫만큼의 개수가 전체페이지 개수이고, 그렇지 않을경우는 +1을 해줘야 한다.

 

전체데이터개수/페이지당게시글 + (전체데이터개수%페이지당게시글== 0 ? 0 : 1);

// 자바에서 int는 정수형만 취급하므로 나누었을 때 소수가 표현되지 않음.

 

1페이지에는 1~10까지의 자료가 나온다.

2페이지는 11~20

3페이지는 21~30

:

n페이지 1+(n-1*10)~n*10 

 

package com.util;

public class MyUtil {
	/**
	 * 전체 페이지수 구하기
	 * @param rows			한화면에 출력할 목록 수
	 * @param dataCount		총 데이터 수
	 * @return				전체 페이지 수
	 */
	public int pageCount(int rows, int dataCount) {
		if(dataCount <= 0) {
			return 0;
		}
		
		return dataCount / rows +(dataCount % rows > 0 ? 1 : 0);
	}
	
	/**
	 * 페이징 처리(GET 방식)
	 * @param current_page	현재 표시되는 페이지 번호
	 * @param total_page	전체 페이지 수
	 * @param list_url		링크를 설정할 주소
	 * @return				페이지 처리 결과
	 */
	public String paging(int current_page, int total_page, String list_url) {
		StringBuilder sb = new StringBuilder();
		
		int numPerBlock = 10;
		int currentPageSetup;
		int n, page;
		
		if(current_page < 1 || total_page < 1) {
			return "";
		} // 데이터가 없으면 설정할 필요가 없음
		
		if(list_url.indexOf("?") != -1) {
			list_url += "&";
		} else {
			list_url += "?";
		}
		
		// currentPageSetup : 표시할 첫 페이지-1
		currentPageSetup = (current_page / numPerBlock) * numPerBlock;
		if(current_page % numPerBlock == 0) {
			currentPageSetup = currentPageSetup - numPerBlock;
		}
		
		sb.append("<div class='paginate'>");
		
		// 처음페이지, 이전(10페이지 전)
		n = current_page - numPerBlock;
		if(total_page > numPerBlock && currentPageSetup > 0) {
			sb.append("<a href='"+list_url+"page=1'>처음</a>");
			sb.append("<a href='"+list_url+"page="+n+"'>이전</a>");
		}
		
		// 페이징 처리
		page = currentPageSetup + 1;
		while(page <= total_page && page <= (currentPageSetup+numPerBlock)) {
			if(page == current_page) {
				sb.append("<span>"+page+"</span>");
			} else {
				sb.append("<a href='"+list_url+"page="+page+"'>"+page+"</a>");				
			}
			page++;
		}
		
		// 다음(10페이지 후), 마지막페이지
		n = current_page + numPerBlock;
		if(n > total_page) n = total_page;
		if(total_page - currentPageSetup > numPerBlock) {
			sb.append("<a href='"+list_url+"page="+n+"'>다음</a>");
			sb.append("<a href='"+list_url+"page="+total_page+"'>끝</a>");
		}
		
		sb.append("</div>");
		
		return sb.toString();
	}
	
}

 

 

테스트

더보기
<%@page import="com.util.MyUtil"%>
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ page trimDirectiveWhitespaces="true"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%
	request.setCharacterEncoding("utf-8");

	// 파라미터로 넘어온 페이지번호(JSP에서 page는 예약어로 변수명으로 사용 불가)
	String pageNum = request.getParameter("page");
	int current_page = 1;
	if(pageNum != null) {
		current_page = Integer.parseInt(pageNum);
	}
	
	MyUtil util = new MyUtil();
	
	int dataCount = 965;
	int rows = 10;
	int total_page = util.pageCount(rows, dataCount);
	if(current_page > total_page) {
		current_page = total_page;
	}
	
	String listUrl = "list.jsp";
	String paging = util.paging(current_page, total_page, listUrl);
	
%>
<!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;
}

body {
	font-size: 14px;
	font-family: 맑은 고딕, 나눔고딕, 돋움, sans-serif;
}

.paginate {
	text-align: center;
	font-size: 14px;
}

.paginate a {
	border: 1px solid #ccc;
	color: #000;
	font-weight: 600;
	text-decoration: none;
	padding: 3px 7px;
	margin-left: 3px;
	vertical-align: middle;
}

.paginate a:hover, .paginate a:active {
	color: #6771ff;
}

.paginate span {
	border: 1px solid #e28d8d;
	color: #cb3536;
	font-weight: 600;
	padding: 3px 7px;
	margin-left: 3px;
	vertical-align: middle;
}

.paginate :first-child {
	margin-left: 0;
}

.container {
	width: 700px;
	margin: 30px auto;
}

</style>


</head>
<body>

<div class="container">
	<h3>페이징 처리 테스트</h3>
	
	<div style="padding-top: 10px;">
		<%= paging %>
	</div>
</div>


</body>
</html>

${pageContext.request.contextPath} 를 이용해서 cp의 이름을 가져온 후, 

원하는 주소창의 주소로 

여기서는 form 태그 안에 <%=cp>/insa/write.do 넣어준다. 그러면 서블릿을 통해 이 주소와 같으면 알아서 서버에서 클라이언트로 forward해준다.

 

서블릿에서 @WebServlet 이라는 annotation을 통해서 주소와 서블릿을 매핑시켜 /insa/* 라고 주면 주소창에 insa 밑에 뭐라고 주든(뭐든지) 이 서블릿 안으로 들어온다. GET방식이든 POST방식이든 process라는 메소드를 실행하고, 그 안에서 주소창에 준 주소에 따라서 jsp를 실행한다. 

 

더보기

insa.jsp

<%@ 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>

<form action="<%=cp%>/insa/write_ok.do" method="post">
	<p> 이름 : <input type="text" name="name" required="required"> </p>
	<p> 생년월일 : <input type="date" name="birth" required="required"> </p>
	<p> 전화번호 : <input type="text" name="phone" required="required"> </p>
	<p> 기본급 : <input type="text" name="salary" required="required" pattern="\d+"> </p>
	<p> 수당 : <input type="text" name="bonus" required="required" pattern="\d+"> </p>
	<p>
		<button type="submit">등록하기</button> <%-- required가 먹으려면 button=submit 사용 --%>
		<button type="reset">다시입력</button>
	</p>
</form>

</body>
</html>

 

result.jsp

<%@ 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> 이름 : ${name}</p>
<p> 이름 : <%=request.getAttribute("name") %></p>
<p> 생년월일 : ${birth}</p>
<p> 전화번호 : ${phone}</p>
<p> 기본급 : ${salary}</p>
<p> 수당 : ${bonus}</p>
<p> 세금 : ${tax}</p>
<p> 실수령액 : ${pay}</p>
<p> 나이 : ${age}</p>
<p> 띠 : ${tti}</p>
</body>
</html>

EL을 이용해서 표현식보다 더 쉽게 attribute를 받아서 쓸 수 있다.

 

 

insaServlet

package ch02.insa;

import java.io.IOException;
import java.text.NumberFormat;

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;

import com.util.DateUtil;

// insa 밑에 뭐가 오든 InsaServlet으로 와라. 서블릿이 우선순위가 높음
// 들어올 때는 GET 방식으로 들어옴
@WebServlet("/insa/*") // 주소와 서블릿 매핑
public class InsaServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		process(req, resp);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		process(req, resp);
	}
	
	protected void process(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		req.setCharacterEncoding("utf-8");
		
		String uri = req.getRequestURI();
		
		if(uri.indexOf("write.do") != -1) {
			// 입력 폼 출력
			writeForm(req, resp);
		} else if(uri.indexOf("write_ok.do") != -1) {
			// 전송 받은 파라미터를 이용하여 연산
			writeSubmit(req, resp);
		}
	}
	
	protected void forward(HttpServletRequest req, HttpServletResponse resp, String path) throws ServletException, IOException {
		RequestDispatcher rd = req.getRequestDispatcher(path);
		rd.forward(req, resp);
	}

	protected void writeForm(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// 입력 폼 출력
		forward(req, resp, "/WEB-INF/views/insa/insa.jsp");
	}
	
	protected void writeSubmit(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// 클라이언트가 보낸 파라미터 정보
		
		String name = req.getParameter("name");
		String birth = req.getParameter("birth");
		String phone = req.getParameter("phone");
		int salary = Integer.parseInt(req.getParameter("salary")); 
		int bonus = Integer.parseInt(req.getParameter("bonus")); 
		
		DateUtil util = new DateUtil();
		int age = util.toAge(birth);
		String t = util.toTti(Integer.parseInt(birth.substring(0,4)));
		
		int total = salary+bonus;
		int tax = 0;
		if(total>=3000000)
			tax = (int)(total*0.03);
		else if(total>=2000000)
			tax = (int)(total*0.02);
		int pay = total-tax;
		
		NumberFormat nf = NumberFormat.getCurrencyInstance();
		
		// JSP에 보낼 속성
		
		req.setAttribute("name", name);
		req.setAttribute("birth", birth);
		req.setAttribute("phone", phone);
		req.setAttribute("age", age);
		req.setAttribute("tti", t);
		
		req.setAttribute("salary", nf.format(salary) );
		req.setAttribute("bonus", nf.format(bonus) );
		req.setAttribute("tax", nf.format(tax) );
		req.setAttribute("pay", nf.format(pay) );
		
		forward(req, resp, "/WEB-INF/views/insa/result.jsp");
	}


	
}

 

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>

 

+ Recent posts