= JSP = Java Server Pages Java의 특성을 물려받는다. => 플랫폼 독립적 + 보안↑ + 멀티스레드 (Servlet과 반대로) **HTML 문서에 Java 코드가 삽입되는 구조** -> HTML 코드는 웹브라우저로 그대로 전송 -> JSP 코드는 웹 컨테이너 쪽에서 실행되고 __결과만__ 웹 브라우저로 전송 (Servlet에 비해 밑줄 친 단계가 추가된 것.) * __**JSP 페이지** --(변환)-> **Servlet 클래스의 소스 코드**__ --(컴파일)-> **Servlet 클래스 파일** --(인스턴스화)-> **Servlet 객체** --(초기화)-> **Servlet** {{tag>Java Web}} = Servlet vs JSP = ^ ^ 장점 ^ 단점 ^ ^ Servlet |- HTML 문서에 소스코드가 공개되지 않는다. |- Java 코드안에 HTML이 작성된다.\\ =>디자인시 수정에도 코드 변경 필요!\\ - 설치과정이 복잡하다. | ^ JSP |- HTML 중심의 코드 구조로 수정이 쉽다.\\ - 설치과정이 쉽다. |- HTML 문서에서 소스 코드가 공개된다. | **그러나** **복잡한 로직**을 필요로 하는 경우 Servlet을 사용해서, JSP 페이지에 결과만 출력하는 구조가 적합하다! = Servlet = Java를 기반으로 하는 웹 어플리케이션 프로그래밍 기술 == 기본 규격 (작성시 지켜야 할 3가지 규칙) == # (**javax.servlet.http.HttpServlet** 를 상속받아) **javax.servlet.Servlet** 인터페이스를 구현해야 한다. # **doGet()**, **doPost()** 메소드의 선언 및 기능을 정의해야 한다. * Argument : (javax.servlet.http.httpServlet__Request__, javax.servlet.httpServlet__Response__) * Exception : java.io.IOException & javax.servlet.ServletException # 동적 HTML 문서를 생성하기 위해서는 doGet(), doPost()의 **두 번째 인자**를 이용해야 한다! 두번째 인자형 값에 getWriter() 메소드를 이용하면 PrinterWriter 객체가 반환되는 데, 이를 이용하여 print(), println(), printf()등의 메소드로 웹브라우저를 통해 HTML 문서에서 출력할 수 있다. == 알아두어야 할 점 == 웹 컨테이너가 Servlet을 운영하는 방법으로 * 웹 서버가 여러 웹 브라우저(User)로부터 **동시 접속**을 받을 수 있고, 여러 Servlet이 **동시 실행** 될 수 있다.\\ 그렇기 때문에 모든 웹 서버는 **Multi-Thread**로 작동한다! * (동시 요청이 왔을 때) 웹 컨테이너가 만드는 Servlet의 개수 * Multi-Thread Model : Thread 여러개로 하나의 Servlet으로 제어 * Single-Thread Model : Thread 하나로 여러개의 Servlet 제어 → 자원 낭비! 대규모 요청시 심각! **__2.4부터 폐용화.__** * 구현 방법 : javax.servlet.SingleThreadModel 구현. == web.xml 설정 방법 == * 에서 따로 package를 import 했으면 같이 적어줘야 한다! (패키지.클래스) * 에서 첫시작에서 "/"를 빼먹지 말자! * "URL패턴"은
태그의 "action" 속성에 지정되고, Servlet을 대표하는 URL로 자유롭게 지정할 수 있다. (나머지 URL은 웹 애플리케이션 디렉토리로써 정확히 적어줘야 한다.) NAME [PACKAGE.]SERVLET_NAME NAME /WEBAPPDIR/MyServlet = 기초 지식 = == 문법의 3종류 == * JSP에서 변환된 명령문들은 doGet(), doPost() 역할을 __동시__에 하는 **_jspService()** 안에 들어간다! === <% %> === * Scripting Elements를 아예 쓰지 않고, [[#Expression Language1 | Expression Language]][[#standard action | Ac]][[#JSTL | ti]][[#Custom Action | on]]만 사용하는 것을 권장. (Web Designer를 위해) ==== 스크립팅 요소 (Scripting Elements) ==== ^ Scriptlet ^ Expression ^ 선언부(Declaration) ^ | <% 명령문 %> | <%= 식(호출된 결과값) %> | <%! 변수 및 메소드 선언 %> | | <% int sum = 0; for(int i=0 ; i<10 ; i++) sum += i; %> | <%= Math.sqrt(sum) %> out.println(Math.sqrt(sum)); | <%! final static int LIMIT = 99999 %> ※ 인스턴스 변수 선언 주의!\\ 실행 중 변경안되도록 "final static" 붙이자! | <%@ page language="java" contentType="text/html" pageEncoding="UTF-8"%> Insert title here <% int a = 3; int b = 4; int total = add(a, b); %> <%! private int add(int a, int b) { return a+b; } %> <%=a %> + <%=b %> = <%=total %> ==== 지시자 (Directive) : <%@ %> ==== * 다른 문법들(Scripting Elements, Expression Language, Action)의 목적과 달리,\\ 웹 브라우저로부터의 요청을 처리하기 위해서가 아니라 **웹 컨테이너가 JSP 페이지를 Servlet 클래스로 변환할 때 __필요한 여러 정보들을 기술__**하기 위해 사용되는 문법 ===== page ===== * JSP 페이지 전체에 적용되는 정보를 기술 ^ Attribute ^ 용도 ^ 예시 ^ | contentType | JSP가 생성하는 문서 종류 및 인코딩 타입 | <%@page contentType="text/html; charset=euc-kr" %> | | import | Scripting Elements 안에서 사용할\\ Java 클래스&인터페이스의 import | <%@page import="java.util.*, java.io.*" %> | | buffer | 출력 Buffer 크기 | <%@page buffer="4kb" /* none */ %> | | autoFlush | 출력 버퍼가 모두 찼을 때의 동작 | <%@page autoFlush="false" %> | | isThreadSafe | Single-Thread로 동작 변경시 필요 | <%@page isThreadSafe="false" /* Single-Thread 동작 */ %> | | session | 세션 참여 여부 | <%@page session=“false” %> | | errorPage | Error 처리할 JSP 페이지 URL |[[#Exception 처리]] | | isErrorPage | Error 처리하는 JSP 페이지 여부 |:::| | isELIgnored | Expression Language 무시/처리 여부 | ===== include ====== * 다른 JSP/HTML 문서를 **현재 JSP 문서의 일부로 만들기 위해** 사용. * **file** 속성으로 **상대적 URL**를 이용한다. ... <%@include file="example.jsp" %> ... ===== taglib ====== * Action을 사용할 때, **Library가 필요할 때** 사용. <%@taglib prefix="c" uri="http://java.sun.com/jsp/js1/core" %> ==== 주석 ==== Servlet 클래스로 컴파일 과정에서 |< 21em 50% >| ^ JSP 주석(<%-- --%>) ^ HTML 주석()\\ Java 주석(// /* */) ^ | 제거된다. | 그대로 기록된다. | === Expression Language : ${ } === * [[#Expression Language1 | Expression Language]] === Action : XML Tag 형태 === * [[#Standard Action]] * [[#JSTL]] * [[#Custom Action]] == 내장 변수 (Implicit variable) == * 선언하지 않아도 사용할 수 있는 변수\\ ☞ **_jspServlet()**에 속하는 Parameter 변수와 Local 변수 ^ 변수명 ^ Type ^ 용도 ^ 예시 ^ | request |javax.servlet.http.\\ HttpServletRequest |doGet(), doPost() 첫 번째 Parameter | <%= request.setCharacterEncodeing("euc-kr"); %> <%= request.getParameter("NAME"); %> | | response |javax.servlet.http.\\ HttpServletResponse |doGet(), doPost() 두 번째 Parameter | <% response.sendRedirect("ex.jsp?RESULT="+msg+"&NUM=7") %> | | out |__javax.servlet.jsp.\\ JspWriter__\\ (PrintWriter 아님!) |웹 브라우저로 HTML 코드 출력 | <% out.println("
"); %> <% out.flush(); /* buffer 수동 비우기 */ %>
| | session |javax.servlet.http.\\ HttpSession |세션 관련 기능 |[[#Session 기술의 사용 방법]] | | application |javax.servlet.\\ ServletContext |JSP 문서가 속하는 Web App의 관련 기능 | <% String relPath = application.getContextPath(); String absPath = application.getRealpath("/RelativePath"); %> | | config |javax.servlet.\\ ServletConfig |JSP 문서의 구성 정보 가져오는 기능 | | pageContext |javax.servlet.jsp\\ PageContext |JSP 문서 범위 내에서 사용할 수 있는\\ 데이터저장 기능등 | | page |java.lang.\\ Object |JSP 문서로부터 생성된 Servlet | | exception |java.lang.\\ Throwble |Exception 객체 |[[#Exception 처리]] | == 다른 JSP 문서 호출하기 == * 가독성과 유지보수를 위해 JSP 문서를 여러 개로 나눴을 때 필요. === forward() === * 다른 JSP 문서를 호출할 때 사용. * 실행 흐름의 제어를 되돌려주지 않음.\\ ☞ 어떤 JSP 문서가 **할 일을 모두 마친** 후 다른 Web Resource(JSP, Servlet, %%HTML%%, ...)를 호출할 때 사용. * 호출하는 문서에 **HTML 코드 출력하면 Exception 발생!** <% RequestDispatcher dispatcher = request.getRequestDispatcher("ex.jsp"); //상대경로만 사용가능! 절대경로 불가능! //request.setAttribute("NAME", new Integer(7)); //String, Object dispatcher.forward(request, response); %> ==== forward() vs sendRedirect() ==== * **핵심** : 웹 브라우저를 거치는가? (= 같은 Servlet 객체를 공유하는가? 아니면 새로 생성하는가?) |<100% 20% 40% 40%>| ^ ^ forward() ^ sendRedirect() ^ ^ 호출 방식 | 웹 서버 쪽에서 **직접**\\ =>자원 절약+응답 시간↑ | URL을 웹 브라우저로 보내서 **간접적** | ^ 호출 경로 |__상대 경로**만**__! \\ = __같은 웹서버&디렉토리**만**__ 호출 가능.\\ => 회선을 거치지 않고 **직접** 데이터를 전달하기 때문에 **보안↑** |상대 경로, 절대 경로 \\ = 다른 웹 서버의 웹 자원 호출 가능.\\ => 새 URL 유도에 사용\\ => "새로 고침"시 중복 동작 방지에 사용. | ^ Data 전달 방식 | request 내장 변수를 통해 | URL 뒤에 붙여서 | ^ 전송 가능한 Data Type | Object | String | ^ 한글 Data URL 인코딩 여부 | 불필요 | 필요 | ^ Data 송수신 예 | //송신 request.setAttribute("Age", new Integer(11)); RequestDispatcher dispatcher = request.getRequestDispatcher("Result.jsp"); dispatcher.forward(request, response); //수신 Integer age = (Integer)request.getAttribute("Age"); | //송신 String str = URLEncoder.encode("안녕?", "EUC-KR"); response.sendRedirect("Test.jsp?STR=" + str + "&NUM=11") //수신 String str = reqeust.getParameter("STR"); String num = reqeust.getParameter("NUM"); | === include() === * 다른 웹 자원(JSP, Servlet, HTML, ...)를 호출하는 기능 * 호출된 웹 자원이 끝나고 나면 **실행 흐름의 제어가 본래의 웹 자원으로 돌아온다.**\\ ☞ 여러 웹 자원이 **공통으로 사용하는 코드**를 호출 할 때 사용. <% out.flush(); //출력 버퍼에서 JSP 코드 이전의 HTML 코드 제거. RequestDispatcher dispatcher = request.getRequestDispatcher("ex.jsp"); //상대경로만 사용가능! 절대경로 불가능! //request.setAttribute("NAME", new Integer(7)); //String, Object dispatcher.include(request, response); %> ==== include() vs include 지시자 ==== 포함된 Web component가 별도의 Servlet class를 생성하는가? |<15em 50%>| ^ include() ^ include 지시자 ^ | O | X((해당 코드를 호출하는 JSP 페이지의 Servlet class의 일부로 만든다.)) | = get vs post = 입력된 데이터가 URL에 |< 10em 50% >| ^ get ^ post ^ | 공개 | 비공개 | = Cookie vs Session = * 3개 이상의 화면으로 구성된 애플리케이션을 작성할 경우, 서로간의 __**데이터 송수신**__ 처리를 위해 필요. ^ ^ Cookie ^ Session ^ ^ 저장 위치 | Client | Server | ^ 저장 Type | String | Object | ^ 용량 제한 | 4KB, 한 Client(Domain) 당 20개 | 서버가 허용하는 한 용량, 개수 제한 없음 | ^ 단일 기록량 | 1 | 多 (☞ Hashtable 사용) | == 적절한 사용 시점? == * **Cookie** * 다른 언어나 Platform끼리 연동하여 Data 송수신을 할 경우 * **Session** * Data 크기가 큰 경우 * ☞ 용량이 큰 Cookie를 내보내면 Network 부하를 증가 시키게 되지만 \\ Session은 Servlet이 수행되는 Server의 Memory 공간에 Data가 저장되므로 \\ Client에서 Network 부하는 단지 Session ID 정도만 사용하게 됨. * 보안이 필요한 Data인 경우 * ☞ Server에 저장되므로 == 정의 == Web Component(JSP 페이지와 Servlet 클래스를 통칭)간의 __**데이터를 송수신**__이 가능케하는 기술. * **Cookie** : 전달할 Data를 __**Web Browser로 보냈다가**__ 웹 서버 쪽으로 되돌려 받는 방법. (Client) * Data 공유 범위 : 같은 웹 서버 내에 있는 모든 웹 컴포넌트들과 자바가 아닌 웹 애플리케이션 프로그램들 전체. * **Session** : 전달할 실제 Data를 __**Web Browser를 거치지 않고**__ **Session ID만 보내어** **웹 서버에 있는 데이터 영역**을 통해 데이터를 전달하는 방법. (Server)\\ ☞ Web Browser(Client)로 Session ID를 전송하는 기술은 **Cookie!** (웹 브라우저로 세션아이디를 보낼 때 **JSSESSIONID**란 이름의 쿠키 형태로 만들어 전송한다.)\\ ☞ Cookie에 비해 보안성 높음. * 여러 웹 컴포넌트들이 협력 작업을 시작해서 끝내기까지의 기간 * 보안상 중요한 데이터는 Session, 그렇지 않으면 Cookie 이용. * Session Data를 전송하기 위해 사용하는 기술도 Cookie! (☞ 둘 다 알아야 한다!) * Data 공유 범위 : 같은 웹 애플리케이션 디렉터리에 있는 웹 컴포넌트들 === 탄생 배경 - 왜 두 기술로 나뉘었는가? === WWW 등장 초창기에는 인프라 구축이 덜 되어 대규모의 동시 사용자를 위한 웹앱의 중간 데이터를 서버 쪽에 저장해 두는 것이 어려웠기 때문에 **Cookie** 기술이 먼저 개발되었다. (= Client측에서 처리) == Cookie 기술의 사용 방법 == === 입력 & 수정 === <%@page contentType="text/html; charset=euc-kr" %> //HTML 코드 명령문보다 앞에 오는 것이 바람직. (Buffer 때문) <% //두 Argument는 "String" Type! 수치값인 경우 String Data로 만들어야 한다! //쿠키명 같으면 "수정(Set)". response.addCookie(new Cookie("AGE", "20")); %> ... === 조회 === <%@page contentType="text/html; charset=EUC-KR" %> <% Cookie[] cookies = request.getCookies(); //배열! %> Age : <%= getCookieValue(cookies, "AGE") %> <%! private String getCookieValue(Cookie[] cookies, String name) { if(cookies == null) return null; for(Cookie cookie : cookies) { if(cookie.getName().equals(name)) { return cookie.getValue(); } } return null; } %> === 삭제 === <%@page contentType="text/html; charset=euc-kr" %> <% //초단위. 수명을 0로 하면 삭제된다. //음수면 아래 메서드를 호출하지 않았을 때와 마찬가지로 "웹 브라우저가 끝날 때" 쿠키 제거 Cookie cookie = new Cookie("Key", ""); //삭제할 쿠키이므로 Value는 아무렇게나 상관없음. cookie.setMaxAge(0); response.addCookie(cookie)' %> ... === 전송 범위 조정 === ==== 쿠키가 특정 경로명을 갖는 URL로만 전송되도록 만드는 방법 (전송 범위 좁히기) ==== * 웹 브라우저는 웹 서버로 URL을 보낼 때, 그 웹 서버에 속하는 모든 쿠키를 함께 보내는 것이 기본 동작이지만, 이런 전송 범위를 좁혀야 할 경우가 있을 때 사용. <%@page contentType="text/html; charset=euc-kr" %> <% Cookie cookie = new Cookie("Age", "20"); cookie.setPath("/local/"); //URL 경로명은 "반드시 /로 시작"해야하고, 마지막도 /로 끝내는 것을 권장. response.addCookie(cookie); %> ... ==== 쿠키가 여러 웹 서버로 전송되도록 만드는 방법 (전송 범위 넓히기) ==== * 웹 브라우저가 저장할 수 있는 쿠키의 수가 웹 서버별로 한정되어 있다. 남용시 데이터 손실되니 주의! <%@page contentType="text/html; charset=euc-kr" %> <% Cookie cookie = new Cookie("Age", "20"); cookie.setDomain(".site.co.kr"); //대표 도메인 설정. "."로 시작해야 한다! response.addCookie(cookie); %> ... == Session 기술의 사용 방법 == * Session의 적용 범위는 **같은** 웹 애플리케이션 **디렉토리** 내에 있는 **웹 컴포넌트(JSP, Servlet)**로 국한된다. (= 디렉토리별로 독립적, 같은 디렉토리 내 Java 웹 애플리케이션끼리만 공유 가능) === Servlet 클래스에서 세션 기술을 사용하는 방법 === HttpSession session = request.getSession(); //Session 시작/가져오기 session.setAttribute(String, Object); //데이터 저장 Object att = session.getAttribute(String); // 데이터 가져오기. 다른 타입은 Casting 필요. session.removeAttribute(String); // 데이터 삭제 session.invalidate(); //세션 끝내기 int timeout = session.getMaxInactiveInterval(); //타임아웃 기간 반환 session.setMaxInactiveInterval(-1); //타임아웃 기간 설정.(초단위), 음수값이면 무한대 === JSP 페이지에서 세션 기술을 사용하는 방법 === * Servlet 클래스로 변환될 때, **HttpSession session = request.getSession();**이 자동으로 추가되므로 session 변수를 그냥 이용하면 된다. * Session을 사용하지 않으려면 **<%@page session="false" %>**를 지정하면 된다. 그러나 Session을 끝내는 기능까지 하는 것이 아니므로 **반드시** invalidate()를 호출해야 한다. === URL 재작성 메커니즘의 사용 방법 === * __**Cookie**를 사용할 수 없는 웹 환경에서 사용.__ (예를 들어 정책에 따른 차단) * **"URL;jsessionid=SESSION_ID"** 형태를 이용하는 데, SESSION_ID를 얻기 위해서는 HttpSession의 getID()를 이용할 수 있지만 더 쉽게 doGet, doPost 메서드의 두 번째 Parameter **"response"**를 이용한다. * "response.encodeURL()"은 지능적으로 작동. * Parameter로 넘겨준 URL이 현재 웹 애플리케이션 디렉토리에 속하지 않을 경우, URL 재작성하지 않고 본래 URL 반환 * 웹 브라우저로부터 쿠키가 하나라도 있으면 쿠키를 사용할 수 있는 웹 환경이라고 판단하여 본래 URL 반환 * 상대적인 URL 경로 사용 가능. ("myHome/main.jsp") * 웹 서버 내 URL 경로 사용 가능. ("/root/myHome/main.jsp") <% /* 반환 결과는 URL;jsessionid=SESSION_ID */ String url1 = response.encodeURL("http://localhost:8080/myHome/main.jsp"); String url2 = response.encodeRedirectURL("http://localhost:8080/myHome/main.jsp"); //sendRedirect()의 URL 재작성 기법. Redirect시 세션 유지 %> = Exception 처리 = 일반적인 Java 프로그램의 try~catch를 이용하게 되면 HTML 코드와 섞여 난잡해진다. 이를 해결하기 위해 Exception 처리를 위한 웹 컴포넌트를 별도로 만들어 호출하면 된다. == 여러 페이지 만들어서 호출 == * try~catch + [[#forward()]] ☞ Servlet에서는 page 지시자를 이용할 수 없기 때문에 이를 이용. * page 지시자의 **errorPage**/**isErrorPage** Attribute **(☞ try~catch를 쓰지 않고 간결하게 처리 가능! (JSP만 가능))** <%@page contentType-"text/html; charset=euc-kr" errorPage="Error.jsp" %> <%@page contentType-"text/html; charset=euc-kr" isErrorPage="true" %> <%@ response.setStatus(200); %> //200이면 정상적인 실행 결과, 500이면 에러 발생 결과. 항상 의도한대로 작동시키기 위해 200 설정. <%= exception.getMessage() %> //isErrorPage 지시자를 이용하면 세부적인 Exception 메시지를 확인할 수 있다. == web.xml 파일에 여러 페이지 등록하기 == 웹 컴포넌트의 규모가 커질 경우 여러 페이지의 공통 Exception을 처리할 수 있으므로 효율적. * page 지시자의 errorPage 사용하지 않아야 한다. === Exception Type별 === * "HTTP 상태 코드별" 처리보다 높은 **우선권**을 갖는다. ... java.lang.NumberFormatException /Error.jsp ... //① doGet(), doPost() throws 선언 //② throws 할 수 있는 Exception이 한정되어 있기 때문에 SevletException으로 포장한다. /* 던질 수 있는 Exception 종류 * java.io.IOException, java.servlet.ServletException, java.lang.ArithmeticException, java.lang.NumberFormatException */ try {~} catch (java.sql.SQLExcption e) { throw new ServletException(e); } === HTTP 상태 코드별 === * 웹 컴포넌트의 실행과 상관없이, 웹 브라우저로부터 받은 **URL**에 해당하는 웹 자원이 **웹 서버에 없는 경우** 사용. ... 404 /Error.jsp ... = Servlet의 Life Cycle = == 똑같은 데이터, 로직, 결과를 갖는 코드를 한번만 실행하기 == === Servlet 클래스의 init(), destory() === * Init() Finabocci 수열 출력 import java.io.IOException; import java.io.PrintWriter; import java.math.BigInteger; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class Finabocci extends HttpServlet { private BigInteger[] arr; @Override public void init() throws ServletException { arr = new BigInteger[100]; arr[0] = new BigInteger("1"); arr[1] = new BigInteger("1"); for (int i = 2; i < arr.length ; i++) { arr[i] = arr[i - 2].add(arr[i - 1]); } } @Override /*public void init(ServletConfig config) throws ServletException { // 원리적으로 // Web container에서 Servlet을 초기화할 때 이 Method가 불리어진다. // 그런데 내부적으로 Parameter가 없는 init이 불러오기 때문에 // Parameter가 없는 init으로 초기화가 가능하다. // 주의점으로 이 메소드를 이용할 때는 반드시 부모 Class의 init을 호출해야 한다. // 혹시나 부모 클래스를 재정의한 경우가 있을 수 있으므로... super.init(config); }*/ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String str = request.getParameter("NUM"); int num = Integer.parseInt(str); if(num > 100) num = 100; response.setContentType("text/html; charset=UTF-8"); PrintWriter out = response.getWriter(); out.println(""); out.println("Fibonacci"); for(int i = 0; i < num ; i++) { out.println(arr[i] + " "); } out.println(""); out.println(""); } } finabocciServlet Finabocci 0 finabocciServlet /test * destroy() Log Writer Log Writer
import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.util.GregorianCalendar; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class LogWriter extends HttpServlet { private PrintWriter logFile; @Override public void init() throws ServletException { /* web.xml에 기재된 초기화 Parameter 이용 */ String fileName = getInitParameter("FILE_NAME"); try { logFile = new PrintWriter(new FileWriter(fileName, true)); } catch (IOException e) { throw new ServletException(e); } } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String message = request.getParameter("MESSAGE"); if(message == null) throw new NullPointerException("Message가 NULL이다!"); if(logFile != null) { GregorianCalendar now = new GregorianCalendar(); logFile.printf("%TF %TT - %s %n", now, now, message); } response.setContentType("text/html ; charset=UTF-8"); PrintWriter out = response.getWriter(); out.println(""); out.println("test"); out.println(""); out.println(message + "이 기록되었습니다."); out.println(""); out.println(""); } @Override public void destroy() { if(logFile != null) logFile.close(); } } logWriter-servlet LogWriter FILE_NAME C:\\log.txt 0 logWriter-servlet /logwriter === JSP 페이지의 jspInit(), jspDestroy() === ※ Servlet과의 차이점으로 선언부(<%! %>)에서는 **throws** 절을 사용할 수 없다. logWriter <%@page import="java.util.GregorianCalendar"%> <%@page import="java.io.*"%> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%! private PrintWriter logFile; public void jspInit() { /* web.xml에 기재된 초기화 Parameter 이용 */ String fileName = getInitParameter("FILE_NAME"); try { logFile = new PrintWriter(new FileWriter(fileName, true)); } catch (IOException e) { // throw 절 사용 불가! System.err.printf("%TT - %s 파일을 열 수 없습니다. %n", new GregorianCalendar(), fileName); } } %> logWriter <% GregorianCalendar now = new GregorianCalendar(); String date = String.format("현재 날짜: %TY년 %Tm월 %Te일", now, now, now); String time= String.format("현재 시각: %TI시 %TM분 %TS초", now, now, now); if(logFile != null) { logFile.println(date + " " + time); out.println(date + "
"); out.println(time + "
"); } else out.print("초기화 실패"); %> <%! public void jspDestroy() { if(logFile != null) logFile.close(); } %>
logWriter-jsp /logWriter.jsp FILE_NAME C:\\log2.txt 0 logWriter-jsp /logwriter == Servlet의 환경을 표현하는 ServletContext == === Servlet의 환경 정보를 가져오는 방법 === * Servlet import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ServerInfoServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ServletContext context = getServletContext(); String serverInfo = context.getServerInfo(); int majorVersion = context.getMajorVersion(); int minorVersion = context.getMinorVersion(); response.setContentType("text/html ; charset=euc-kr"); PrintWriter out = response.getWriter(); out.println(""); out.println("ServerInfo"); out.println(""); /* tomcat 버전과 Servlet 버전 출력*/ out.println(serverInfo + " // " + majorVersion + "." + minorVersion); out.println(""); out.println(""); } } * JSP * **applicaion** 내장 변수를 이용하여 더 간단히 작성 가능! <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> ServerInfo <%= application.getServerInfo() %> // <%= application.getMajorVersion() %> . <%= application.getMinorVersion() %> === 초기화 Parameter 가져오는 getInitParameter() === <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> ServerInfo <%= application.getInitParameter("PARAM_TEST") %> PARAM_TEST Hello, world! === Log 기록하는 Log() === * 실행되는 동안 [Tomcat]/logs 내에 **localhost.yyyy-mm-dd.log**에 기록됨. === 같은 Web application에 속하는 Web component끼리 Data를 주고 받는 방법 === ^application.setAttribute(String arg0, Object arg1) ^ ^application.getAttribute(String arg0) ^ ^application.removeAttribute(String arg0) ^ ==== setAttribute, getAttribute, removeAttribute 4Set 구분 ==== * 사용 범위가 좁은 Attribute 부터 순서 시작. ^ 호출할 때 사용하는 내장 변수 ^ Method 소속 ^ Data 전송 범위 ^ 용도 ^ 다루는 장 ^ | pageContext |javax.servlet.jsp.JspContext 클래스 |현재 JSP 페이지 내 |같은 JSP 페이지 안에 있는 Scripting 요소와 [[:expression_language1| Expression Language]] 간의 Data 교환 | [[#Expression Language | 7장]] | | request |javax.servlet.ServletRequest 인터페이스 |현재 웹 컴포넌트 및 forward(), include()를 통해 호출되는 또 다른 Web component |forward(), include()를 통해 호출되는 Web component로의 Data 전달 | [[#forward() | 3장]] | | session |javax.servlet.http.HttpSession |같은 세션에 속하는 모든 Web component |여러 화면으로 구성되는 Application에서 Web component간의 Data 전달 | [[#Session 기술의 사용 방법 | 4장]] | | application |javax.servlet.ServletContext 인터페이스 |같은 Web application에 속하는 모든 Web component |같은 Web application의 Directory에 속하는 Web component간의 Data 공유 | [[#같은 Web application에 속하는 Web component끼리 Data를 주고 받는 방법 | 6장]] | = Expression Language = * **간략한 표현**으로 식을 계산해서 그 **데이터 처리 결과를 출력**하는 목적으로 사용. * Logic 구현이 목적이 아니다! 오직 **출력**! ^ ${EXPRESSION} |EXPRESSION은 기본적으로 **"Attribute 이름"**이다.\\ 이외 산술연산자, 논리연산자 사용 및 정적 Method를 호출할 수 있다. | <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% int sum=0; for(int i=1 ; i<=10 ; i++) sum += i; request.setAttribute("SUM", sum); %> EL ${SUM}

${SUM * 2}
${SUM == 55}
== Expression 언어의 기초 문법 == === Attribute 이름 하나로만 구성된 EL 식 === ${ATTRIBUTE_NAME} * 만약 Attribute 이름이 같고, [[#setAttribute, getAttribute, removeAttribute 4Set 구분 | Method가 소속된 Package]]이 다른 경우??? * 사용 범위가 좁은 Attribute부터 해석된다! * [[#setAttribute, getAttribute, removeAttribute 4Set 구분 | page → request → session → application]] * 특정 소속의 Attribute를 선택하고 싶다면?? * **pageScope**, **requestScope**, **sessionScope**, **applicationScope** 내장 객체를 이용한다. \\ ${pageScope.SUM} ${requestScope.SUM} ${sessionScope.SUM} ${applicationScope.SUM} === Expression Language의 내장 객체 === ^ 내장 객체 이름 ^ 표현하는 데이터 ^ Type ^ ^pageScope |[[#setAttribute, getAttribute, removeAttribute 4Set 구분 |page Attribute 집합]] | Map | ^requestScope |[[#setAttribute, getAttribute, removeAttribute 4Set 구분 |request Attribute 집합]] | Map | ^sessionScope |[[#setAttribute, getAttribute, removeAttribute 4Set 구분 |session Attribute 집합]] | Map | ^applicationScope |[[#setAttribute, getAttribute, removeAttribute 4Set 구분 |application Attribute 집합]] | Map | ^param |Web browser로 입력된(
element를 통해 입력된) Data 집합\\ (paramValues는 같은 이름의 Data가 여러개일 때 사용. (checkbox or select)) | Map | ^paramValues |::: |::: | ^header |HTTP 요청 Message에 있는 HTTP Header의 집합\\ (headerValues는 같은 이름의 HTTP Header가 여러개일 때 사용) | Map | ^headerValues |::: |::: | ^Cookie |Web browser로부터 전송된 Cookie 집합 | Map | ^initParam |Web application의 초기화 Parameter 집합 | Map | ^pageContext |JSP Page의 환경 정보 집합\\ ([[https://tomcat.apache.org/tomcat-8.0-doc/jspapi/javax/servlet/jsp/PageContext.html | javax.servlet.jsp.PageContext]]) | PageContext | pageContext를 제외하고 모두 **Map** Type이기 때문에 - 단수 Data인 경우 - 내장객체.ATTRIBUTE_NAME - 내장객체.["ATTRIBUTE_NAME"] - 복수 Data인 경우 - 내장객체.ATTRIBUTE_NAME[INDEX] - 내장객체.["ATTRIBUTE_NAME"][INDEX] 두 가지 방법으로 사용 가능하다. (b 방법에서 큰 따옴표(") 대신 작은 따옴표(')로 사용 가능하다.)\\ **단, ATTRIBUTE_NAME이 __Java 식별자 명명 규칙을 따르지 않는 경우(첫 글자가 숫자이거나 영문자, 숫자, $/_ 이외 특수문자가 포함된 경우)__ b 방법을 사용해야 한다.** ==== 예제==== * param, paramValues input
이름

좋아하는 음식
초콜릿 국수 탕수육 스테이크

성별

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> result 성 : ${param.lastName}
이름 : ${param["firstName"]}
좋아하는 음식 : ${paramValues.food[0]} ${paramValues.food[1]} ${paramValues.food[2]} ${paramValues.food[3]}
성별 : ${paramValues["sex"][0]} ${paramValues["sex"][1]}
* cookie <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% Cookie c = new Cookie("job", "Developer"); response.addCookie(c); %> result value : ${cookie.job.value}
domain : ${cookie.job.domain}
path : ${cookie.job.path}
maxAge : ${cookie.job.maxAge}
* header, headerValues <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> ServerInfo ${header["User-Agent"]}
${headerValues.Accept[0]}
* initParam [[#초기화 Parameter 가져오는 getInitParameter()]] 그대로 인용. ... ${initParam.PARAM_TEST} ... * pageContext * [[https://tomcat.apache.org/tomcat-8.0-doc/jspapi/javax/servlet/jsp/PageContext.html#method_summary | API]]에서 **Parameter**가 없고, **get-**으로 시작하는 8개의 Method 중에서\\ get을 제거하고 첫자를 소문자로 변경하여 사용. * errorData * exception * page * request * response * servletConfig * servletContext * session <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% HttpSession s = request.getSession(); session.setAttribute("mySession", "Hello, world!"); %> ServerInfo ${pageContext.session.valueNames[0]}
${pageContext.request.requestURI}
== Expression Language의 연산자 == === 산술, 비교, 논리, 조건 연산자 === * IDE나 Editor에서 "<", ">", "%" 기호 판단을 제대로 못할 경우 사용 ^ div | / | ^ mod | % | ^ lt\\ (**l**ess **t**han) | < | ^ gt\\ (**g**reater **t**han) | > | ^ le\\ (**l**ess or **e**qual to) | <= | ^ ge\\ (**g**reater or **e**qual to) | >= | ^ eq\\ (**eq**ual to) | == | ^ ne\\ (**n**ot **e**qual to) | != | * 문자열에 사용할 경우 유니코드에 따른 사전식 비교가 된다. <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> ServerInfo ${"apple" lt "banana"} === Empty 연산자 === <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> ServerInfo ${empty param.ID ? "guest" : param.ID} === [], . 연산자 === 아래 4가지 항목을 가리킨다. * 배열의 Data * java.util.List의 Data * java.util.Map의 Data * [[https://ko.wikipedia.org/wiki/%EC%9E%90%EB%B0%94%EB%B9%88%EC%A6%88 | JavaBean]] Property((getter/setter Method를 통해 관리되는 data)) * 컴파일하여 [Web application]/WEB-INF/classes/[Package] 에 넣어야 한다. * **주의점!! JavaBean 작성시 default package는 비허용되므로 참조가 불가능하다!** <%@page import="java.util.HashMap"%> <%@page import="java.util.ArrayList"%> <%@page import="bean.PersonInfo"%> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% int[] arr = {11, 22, 33}; request.setAttribute("ARR", arr); ArrayList list = new ArrayList<>(); list.add("a"); list.add("b"); list.add("c"); request.setAttribute("LIST", list); HashMap map = new HashMap<>(); map.put("Jake", 21); map.put("Chris", 55); request.setAttribute("MAP", map); PersonInfo personInfo = new PersonInfo(); personInfo.setName("Luke"); personInfo.setAge(28); request.setAttribute("BEAN", personInfo); %> test ${ARR[0]} ${ARR[1]} ${ARR[2]}
${LIST[0]} ${LIST[1]} ${LIST[2]}
${MAP["Jake"]} ${MAP.Chris}
${BEAN["name"]} ${BEAN.age}
package bean; //JSP에서는 default package는 참조 불가 import java.io.Serializable; public class PersonInfo implements Serializable { private String name; private int age; public PersonInfo() { } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } == Expression Language로 정적 Method 호출 == - tld(tag library discriptor) 파일 생성 및 function 기술 - web.xml에 tld 파일 등록 - 호출하려는 jsp 파일에서 **taglib** 지시자 기술 package util; // default package는 불가! import java.text.SimpleDateFormat; import java.util.Date; public class MyMath { public static int sum(int start, int end) { int sum = 0; for(int i=start ; i<=end ; i++) { sum+=i; } return sum; } public static String now() { SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd hh:mm:ss"); return sdf.format(new Date()).toString(); } } tlib-version short-name sqrt java.lang.Math double sqrt(double) parseInt java.lang.Integer int parseInt(java.lang.String) total util.MyMath int sum(int, int) now util.MyMath java.util.String now() <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib uri="../../math-func.tld" prefix="m" %> test 제곱근 : ${m:sqrt(25)}
문자→숫자 : ${m:parseInt("123")}
사용자 정의 합 : ${m:total(1, 10)}
사용자 정의 현재 시간 : ${m:now()}
= Standard action = == JSP 페이지의 모듈화에 사용되는 Standard action == === === * [[#include1 | include()]] Method와 결과가 동일하다. <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> index

오늘의 메뉴

  • 짜장면
  • 짬뽕
  • 볶음밥

<%-- <%@include file="today.jsp" %> --%> <%-- <% out.flush(); RequestDispatcher dispatcher = request.getRequestDispatcher("today.jsp"); dispatcher.include(request, response); %> --%>
<%@page import="java.util.GregorianCalendar"%> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% GregorianCalendar now = new GregorianCalendar(); %> <%= String.format("%TF %TT", now, now) %> === === * [[#forward | forward()]]와 Method와 결과가 동일하다. <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> index <% int sum = 0; for(int i=1 ; i<=100 ; i++) sum+=i; request.setAttribute("RESULT", sum); %> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> result 합 : ${RESULT} == JavaBean 호출에 사용되는 Standard action == === 기초 사용 방법 === JavaBean은 [[#연산자 | [], . 연산자]] 사용. <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> index <%-- --%> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> result 이름 :
나이 :
=== Web browser로부터 입력된 Data를 JavaBean Property로 설정하는 방법 === input
이름 :
나이 :
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> result <%-- --%> 이름 :
나이 :
=== JavaBean의 다형성을 활용하는 방법 === * 상속받은 요소가 Interface 혹은 Abstract class인 경우 **type** attribute를 사용한다! package bean; //JSP에서는 default package는 참조 불가 import java.io.Serializable; abstract public class PersonInfo implements Serializable { private String name; private int age; public PersonInfo() { } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } package bean; public class EmployeeInfo extends PersonInfo { private long departmentNo; public long getDepartmentNo() { return departmentNo; } public void setDepartmentNo(long departmentNo) { this.departmentNo = departmentNo; } } <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> index <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> result 이름 :
나이 :
== 그 밖에 유용한 Standard action == === Script 요소를 대신하는 Standard action === [[#문법의 3종류 | 문법의 3종류]] 대신 사용 가능. <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> index <%-- <% %> --%> int num1 = 1; int num2 = 2; <%-- <%= %> --%> add(num1, num2) <%-- <%! %> --%> private int add(int a, int b) { return a + b; }
<%-- <%@ %> --%>
[[#jspinclude | today.jsp]] = JSTL = **J**SP **S**tandard **T**ag **L**ibrary * API docs * http://docs.oracle.com/javaee/5/jstl/1.1/docs/tlddocs/ * http://docs.oracle.com/javaee/5/tutorial/doc/bnake.html * Download * http://tomcat.apache.org/taglibs/standard/ * 1.1 : http://archive.apache.org/dist/jakarta/taglibs/standard/binaries/ * WEB-INF/lib 에 넣는다. (이클립스는 프로젝트 내, 아니면 tomcat 내) * 무엇을 할 수 있는가? * 간단한 프로그램 Logic 구사 (변수 선언, if/for 등의 간단한 Logic) * 다른 JSP Page 호출 * 날짜, 시간, 숫자 Format * JSP Page 하나를 가지고 여러 가지 언어의 Web page 생성 * Database의 입력, 수정, 삭제, 조회 * XML 문서의 처리 * 문자열 처리 함수 호출 ^ Library ^ 기능 ^ URI 식별자 ^ 접두어 ^ |core |변수 선언, 실행 흐름 제어, 다른 JSP page 제어 |http://java.sun.com/jsp/jstl/core | c | |formatting |숫자, 날짜, 시간 formatting 및 국제화, 다국어 지원 |http://java.sun.com/jsp/jstl/fmt | fmt | |database |입력/수정/삭제/조회 |http://java.sun.com/jsp/jstl/sql | sql | |xml |xml 처리 |http://java.sun.com/jsp/jstl/xml | x | |functions |문자열 처리 함수 제공 |http://java.sun.com/jsp/jstl/functions | fn | == Core library == <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> === === 변수 선언 및 초기화. * 초기화는 선택이 아닌 **필수** * 전달되는 Data는 **Attribute**이므로 Expression 사용 불가. ${num} <%= request.getAttribute("num") %> <%= num %> <% <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> result ${num1} * ${num2} = ${result} === === 특정 Attribute 삭제. === === <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> result num1이 크거나 같다!

${result}
num2가 크다!
${result}
=== === switch와 같은 역할. <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> result 0이다! 1이다! 0도 1도 아니다! === === <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <% String[] arr = {"돈까스", "짜장면", "콩국수"}; request.setAttribute("MENU", arr); %> result 야호
  • ${dish}
=== === for + StringTokenizer <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> result ${lyric}
=== === try 문. <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <% int num1 = Integer.parseInt(request.getParameter("NUM1")); int num2 = Integer.parseInt(request.getParameter("NUM2")); %> result <% int result = num1 / num2; %> <%= result %> ${e.message} === === [[#forward_vs_sendredirect | sendRedirect()]]와 동일.\\ 그렇기 때문에 JSP Page가 아닌 Web resource와 다른 Web server에 있는 Web resource 호출 가능. <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> result ${param.num1} * ${param.num2} = ${param.num1 * param.num2} === === 현재 JSP 페이지에 다른 Web resource를 포함시킴. * [[#jspinclude | ]]처럼 같은 Web server에 있는 JSP Page 포함 가능. * 다른 Web server에 있는 JSP Page 포함 가능. * JSP Page가 아닌 다른 종류의 Web resource 포함 가능. 사용법은 와 비슷. Data를 넘겨주는 형태도 동일. === === 구조적인 url을 위한 변수 선언. <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> result ${myUrl} === === Data 출력. 특이점으로 Tag로 해석될 가능성이 있는 특수문자(<, >, &, ', ")를 **Escape Sequence로 바꿔주는 기능**이 있어 기본적으로 그대로 출력됨. <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> result
== Formatting library == === === 날짜와 시간 format.\\ 주의사항으로 **Date 객체**를 EL식으로 넘겨줘야 한다! <%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@page import="java.util.Date"%> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> result











=== === 수치 format. <%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@page import="java.util.Date"%> <%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> result





=== === 지역 설정. <%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@page import="java.util.Date"%> <%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> result






=== , === 지역별 시간대 설정.\\ **TimeZone.getAvailableIDs()**으로 사용 가능한 **value** Attribute를 얻는다. * * Tag 안에만 영향을 미침. * * 이 Action 다음의 모든 코드에 영향을 미침. <%@page import="java.util.TimeZone"%> <%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@page import="java.util.Date"%> <%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> result
=== , === 다국어 지원. * 은 전체 영향, 는 Tag 안에만 영향. * properties 파일은 ASCII Code만 인식되므로, 특히 **한글** 포함일 경우 변환 과정 필요. * native2ascii [원본명] [출력파일명] * Eclipse 사용시 Properties Editor 사용. * **WEB-INF/classes** 에 넣는다. * Web browser의 언어 설정으로 영향을 받는다. * TITLE=About Us GREETING=Hi, {0}. You have visited this site {1} times! BODY=We are a dedicated software devlopment company. COMPANY_NAME=Duke Software Inc. TITLE=\ud68c\uc0ac \uc18c\uac1c GREETING={0}\ub2d8 \uc548\ub155\ud558\uc138\uc694. {1}\ubc88\uc9f8 \ubc29\ubb38\uc774\uc2dc\uad70\uc694! BODY=\ub2f9\uc0ac\ub294 \uc18c\ud504\ud2b8\uc6e8\uc5b4 \uac1c\ubc1c\uc744 \uc8fc\uc5c5\ubb34\ub85c \ud558\ub294 \ud68c\uc0ac\uc785\ub2c8\ub2e4. COMPANY_NAME=(\uc8fc) \ub4c0\ud06c \uc18c\ud504\ud2b8\uc6e8\uc5b4 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> ${ID} ${COUNT} ${title}

${title}


${greeting}

=== === POST Method로 전송된 한글 입력 Data를 받기 위해 필요. [[#Expression Language1 | Expression Language]]과 [[#standard action | Ac]][[#JSTL | ti]][[#Custom Action | on]]을 이용하면 코드 작업량을 줄일 수 있고, 가독성에서도 유리하므로 Web designer에게도 편리하기 때문에 [[#스크립팅 요소 (Scripting Elements) | Scripting Elements]]를 사용하지 않도록 권장된다. 그런데 이 때 발생하는 문제가 한글 인코딩(<% request.setCharacterEncoding("euc-kr") %>)을 사용해야 하는 경우와 충돌되는 데, 이런 경우에 사용한다. Log Writer
한글이름
<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> test 한글이름 : ${param.NAME} == Functions library == 주로 문자열 처리. String Class의 Method와 비슷한 기능 제공. * [[http://docs.oracle.com/javaee/5/jstl/1.1/docs/tlddocs/fn/tld-summary.html | API]] <%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> test ${fn:toUpperCase(str)}
${fn:split(str, " ")[1]}
${fn:escapeXml(str)}
= Custom action = Tag file과 Tag class의 선택 기준 * 소스 은닉 필요? * 복잡도? == Tag File을 이용해서 만드는 방법 == - [FILENAME].tag 작성 ([FILENAME]은 Custom action의 Tag 이름) - WEB-INF/[SUBDIRECORY] 에 넣는다. (예를 들어 /tags) - taglib 지시자 작성. ^ 지시자 이름 ^ 역할 ^ 비고 ^ | include |다른 Tag file 포함 | | | taglib |다른 Custom action의 Tag library 정보 기술 | | | tag |Web container가 Tag file을 compile 및 실행하기 위한 정보 기술 |tag file에서만 사용 가능. | | attribute |Custom action의 attribute 기술 |:::| | variable |Custom action의 변수 정보 기술 |:::| === 본체 내용을 갖지 않는 경우 === === Attribute를 갖는 경우 === === 동적 Attribute를 갖는 경우 === <%@tag body-content="empty" %> ----------------------------------
<%@tag body-content="empty" %> <%@attribute name="color" %> <%@attribute name="size" type="java.lang.Integer" required="true" %> <% for(int i=0 ; i
<%@tag import="java.util.Map"%> <%@tag body-content="empty" %> <%@tag dynamic-attributes="attrs" %> <% Map attrs = (Map)jspContext.getAttribute("attrs"); int size = Integer.parseInt(attrs.get("size")); for(int i=0 ; i
<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="u" tagdir="/WEB-INF/tags" %> test <%-- Error 발생! --%> === 본체 내용을 갖는 경우 === * body-content="scriptless" : scripting 요소 금지. (EL이나 Action은 인식됨.) * body-content="tagdependent" : Text 그대로 취급. (EL이나 Action은 인식되지 않음.) <%@tag body-content="scriptless" %>
<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="u" tagdir="/WEB-INF/tags" %> test hello, world! === 변수를 지원하는 Custom action === <%@tag body-content="empty" pageEncoding="UTF-8" %> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@attribute name="num1" type="java.lang.Integer" %> <%@attribute name="num2" type="java.lang.Integer" %> <%@attribute name="var" required="true" rtexprvalue="false" %> <%-- <%@variable name-given="result" variable-class="java.lang.Integer" scope="AT_END" %> --%> <%@variable name-from-attribute="var" alias="result" variable-class="java.lang.Integer" scope="AT_END" %> <% int sum = num1 + num2; %> <%@tag pageEncoding="UTF-8" %> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@attribute name="start" type="java.lang.Integer" %> <%@attribute name="end" type="java.lang.Integer" %> <%@attribute name="var" required="true" rtexprvalue="false" %> <%-- <%@variable name-given="result" variable-class="java.lang.Integer" scope="AT_END" %> --%> <%@variable name-from-attribute="var" alias="result" variable-class="java.lang.Integer" scope="NESTED" %> <% for(int i=start ; i<=end ; i++) { %> <% } %> <%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="u" tagdir="/WEB-INF/tags" %> test

a + b

<%-- 결과 : ${result} --%> 결과 : ${RESULT}

제곱

${num}의 제곱은? ${num * num}
== Tag Class를 이용해서 만드는 방법 == * JSP 1.2 : IterationTag, BodyTag Interface 구현. * [[#Custom action]] 안에 [[#스크립팅 요소 (Scripting Elements) | Script Elements]]를 사용할 수 있다. * JSP 2.0 : SimpleTag Interface 구현. * [[#Custom action]] 안에 [[#스크립팅 요소 (Scripting Elements) | Script Elements]]를 사용할 수 없다. * 매번 Method 내부를 작성하는 것이 비효율적. 모든 Method를 구현해놓은 Class => **SimpleTagSupport** === 본체 내용을 갖지 않는 경우 === package tool; import java.io.IOException; import javax.servlet.jsp.JspContext; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.tagext.SimpleTagSupport; public class StarLineTag extends SimpleTagSupport { @Override public void doTag() throws JspException, IOException { JspContext context = getJspContext(); JspWriter out = context.getOut(); out.println("***********************
"); } }
1.0 tool starLine tool.StarLineTag empty tools.tld /WEB-INF/tlds/tools.tld <%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="tool" uri="/WEB-INF/tlds/tools.tld" %> test === Attribute를 갖는 경우 === - setter를 생성한다. - tag 파일에 attribute를 기술한다. package tool; import java.io.IOException; import javax.servlet.jsp.JspContext; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.tagext.SimpleTagSupport; public class NewLineTag extends SimpleTagSupport { private int size; private String color; public void setSize(int size) { this.size = size; } public void setColor(String color) { this.color = color; } @Override public void doTag() throws JspException, IOException { JspContext context = getJspContext(); JspWriter out = context.getOut(); out.println(""); for(int i=0 ; i
"); } }
1.0 tool newLineTag tool.NewLineTag empty size java.lang.Integer color java.lang.String web.xml은 [[#기초 | Tag Class를 이용해서 만드는 방법#기초]]와 동일. <%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="tool" uri="/WEB-INF/tlds/tools.tld" %> test === 동적 Attribute를 갖는 경우 === package tool; import java.io.IOException; import java.util.HashMap; import java.util.Map; import javax.servlet.jsp.JspContext; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.tagext.DynamicAttributes; import javax.servlet.jsp.tagext.SimpleTagSupport; /* DynamicAttributes 구현 */ public class NewerLineTag extends SimpleTagSupport implements DynamicAttributes { private Map attrs = new HashMap<>(); @Override public void setDynamicAttribute(String uri, String localName, Object value) throws JspException { attrs.put(localName, value); } @Override public void doTag() throws JspException, IOException { String color = (String) attrs.get("color"); int size = Integer.parseInt((String) attrs.get("size")); JspContext context = getJspContext(); JspWriter out = context.getOut(); out.println(""); for(int i=0 ; i
"); } }
1.0 tool newerLine tool.NewerLineTag empty true <%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="tool" uri="/WEB-INF/tlds/tools.tld" %> test === 본체 내용을 갖는 경우 === body-content에 대한 이해는 [[#본체 내용을 갖는 경우 | Custom action#본체 내용을 갖는 경우]] 참조. package tool; import java.io.IOException; import javax.servlet.jsp.JspContext; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.tagext.JspFragment; import javax.servlet.jsp.tagext.SimpleTagSupport; public class BoxTag extends SimpleTagSupport { @Override public void doTag() throws JspException, IOException { JspContext context = getJspContext(); JspWriter out = context.getOut(); JspFragment body = getJspBody(); out.println("
"); body.invoke(out); out.println("
"); } }
1.0 tool box tool.BoxTag scriptless <%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="tool" uri="/WEB-INF/tlds/tools.tld" %> test hello, world! ==== 본체 내용 조작 ==== 문자열 두 개를 attribute로 받아 치환하는 Scenario. - 두 개의 setter를 추가한다. - StringWriter를 이용하여 출력 package tool; import java.io.IOException; import java.io.StringWriter; import javax.servlet.jsp.JspContext; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.tagext.JspFragment; import javax.servlet.jsp.tagext.SimpleTagSupport; public class ReplaceTag extends SimpleTagSupport { private String oldWord, newWord; public void setOldWord(String oldWord) { this.oldWord = oldWord; } public void setNewWord(String newWord) { this.newWord = newWord; } @Override public void doTag() throws JspException, IOException { JspContext context = getJspContext(); JspWriter out = context.getOut(); JspFragment body = getJspBody(); /* StringWriter : String 객체를 가상의 하드웨어 장치처럼 출력 */ StringWriter writer = new StringWriter(); body.invoke(writer); String newStr = writer.toString().replaceAll(oldWord, newWord); out.print(newStr); } } 1.0 tool replace tool.ReplaceTag scriptless oldWord java.lang.String newWord java.lang.String <%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="tool" uri="/WEB-INF/tlds/tools.tld" %> test 철수는 영희에게 인사를 하였습니다.
하지만 영희는 철수를 보지 못하고 지나쳤습니다.
=== 변수를 지원하는 Custom action === ==== 결과를 출력할 변수 이름이 고정된 경우 ==== package tool; import java.io.IOException; import javax.servlet.jsp.JspContext; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.SimpleTagSupport; public class SumTag extends SimpleTagSupport { private int num1, num2; public void setNum1(int num1) { this.num1 = num1; } public void setNum2(int num2) { this.num2 = num2; } @Override public void doTag() throws JspException, IOException { JspContext context = getJspContext(); context.setAttribute("result", num1 + num2); } } 1.0 tool sum tool.SumTag empty num1 java.lang.Integer true num2 java.lang.Integer true result java.lang.Integer AT_END <%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="tool" uri="/WEB-INF/tlds/tools.tld" %> test 합 : ${result} ==== 결과를 출력할 변수 이름을 유동적으로 직접 지정할 경우 ==== package tool; import java.io.IOException; import javax.servlet.jsp.JspContext; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.SimpleTagSupport; public class SumTag extends SimpleTagSupport { private int num1, num2; private String var; public void setNum1(int num1) { this.num1 = num1; } public void setNum2(int num2) { this.num2 = num2; } public void setVar(String var) { this.var = var; } @Override public void doTag() throws JspException, IOException { JspContext context = getJspContext(); context.setAttribute(var, num1 + num2); } } 1.0 tool sum tool.SumTag empty num1 java.lang.Integer true num2 java.lang.Integer true var java.lang.String true false var java.lang.Integer AT_END <%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="tool" uri="/WEB-INF/tlds/tools.tld" %> test 합 : ${xxx} === Child Custom Action === Custom action 안에 또 다른 Custom action을 포함하는 경우. ==== 기본 ==== package tool; import java.io.IOException; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.JspFragment; import javax.servlet.jsp.tagext.SimpleTagSupport; public class ListTag extends SimpleTagSupport { @Override public void doTag() throws JspException, IOException { JspFragment body = getJspBody(); // null을 넘겨주면 JSP 페이지와 동일한 출력 스트림을 통해 본체의 내용 출력. // 현재 의도는 포함된 자식 Custon action의 Tag Class를 알아서 호출 body.invoke(null); } } package tool; import java.io.IOException; import javax.servlet.jsp.JspContext; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.tagext.JspFragment; import javax.servlet.jsp.tagext.JspTag; import javax.servlet.jsp.tagext.SimpleTagSupport; public class ItemTag extends SimpleTagSupport { @Override public void doTag() throws JspException, IOException { JspTag parent = getParent(); if(parent == null || !(parent instanceof ListTag)) throw new JspException("The Parent is not ListTag"); JspContext context = getJspContext(); JspWriter out = context.getOut(); JspFragment body = getJspBody(); /* ~ [본체 내용]
*/ out.print("~ "); body.invoke(null); out.println("
"); } }
1.0 tool list tool.ListTag scriptless item tool.ItemTag scriptless <%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="tool" uri="/WEB-INF/tlds/tools.tld" %> test 사과 딸기 ==== 부모와 자식간의 정보를 주고 받는 경우 ==== package tool; import java.io.IOException; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.JspFragment; import javax.servlet.jsp.tagext.SimpleTagSupport; public class ListTag extends SimpleTagSupport { private char bullet; public char getBullet() { return bullet; } public void setBullet(char bullet) { this.bullet = bullet; } @Override public void doTag() throws JspException, IOException { JspFragment body = getJspBody(); // null을 넘겨주면 JSP 페이지와 동일한 출력 스트림을 통해 본체의 내용 출력. // 현재 의도는 포함된 자식 Custon action의 Tag Class를 알아서 호출 body.invoke(null); } } package tool; import java.io.IOException; import javax.servlet.jsp.JspContext; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.tagext.JspFragment; import javax.servlet.jsp.tagext.JspTag; import javax.servlet.jsp.tagext.SimpleTagSupport; public class ItemTag extends SimpleTagSupport { @Override public void doTag() throws JspException, IOException { JspTag parent = getParent(); if(parent == null || !(parent instanceof ListTag)) throw new JspException("The Parent is not ListTag"); JspContext context = getJspContext(); JspWriter out = context.getOut(); JspFragment body = getJspBody(); /* [bullet] [본체 내용]
*/ char bullet = ((ListTag) parent).getBullet(); out.print(bullet + " "); body.invoke(null); out.println("
"); } }
1.0 tool list tool.ListTag scriptless bullet java.lang.Charater true item tool.ItemTag scriptless <%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="tool" uri="/WEB-INF/tlds/tools.tld" %> test 사과 딸기 == Tag Library를 만드는 방법 == === Tag Class 이용 === - Directory 계층 구조 생성 - [ROOT]/META-INF[/...] : *class 제외 나머지 파일. (*.tld) - [ROOT]/[PACKAGE] : *.class - TLD 파일 수정. - 프로젝트에서 참조할 uri 추가. 1.0 tool /taglibs/tools.tld ... - JAR 생성 - jar cvf0 [FILENAME].jar * === Tag file 이용 === - Directory 계층 구조 생성 - [ROOT]/META-INF/tags[/...] : *class 제외 나머지 파일. (*.tld) - TLD 파일 생성. - 프로젝트에서 참조할 uri를 작성하고, tag-file을 기술한다. 주의점으로 path는 최상위 Directory 기준 작성이므로 /로 시작할 것!\\ 1.0 tool /taglibs/util.tld line /META-INF/tags/line.tag - [ROOT]/META-INF[/...] 에 저장. (단, tags 제외) - JAR 생성 - jar cvf0 [FILENAME].jar * = Filter & Wrapper = * Filter : Web component에 대해 **똑같은 사전작업이나 사후작업을 공통적으로 처리** (예. 먼저 로그인 여부 검사) * Wrapper : Web browser와 Web component간에 오가는 **데이터 변형** (예. 데이터 암호화, 일부 데이터 전달 방지) == Filter Class의 작성, 설치, 등록 == - Filter class를 컴파일하고 Web container에 설치. - javax.servlet.Filter의 Method를 구현한다. - Eclipse를 사용하지 않을 경우 **WEB-INF/classes/[PACKAGE]/**에 설치 - Filter class를 Web.xml에 등록 FILTER_NAME PACKAGE.CLASSNAME FILTER_NAME === 하나의 Web component를 등록할 때 === element에서 ****을 사용한다. (다수 등록 가능.)\\ 이 때, 특정한 Servlet Class나 JSP 페이지를 등록하려면 __**먼저 그 Setvlet Class나 JSP 페이지를 web.xml 파일에 서블릿으로 등록해야 한다.**__ * 참조 * [[#web.xml 설정 방법]] * [[#JSP 페이지의 jspInit(), jspDestroy()]] SERVLET_NAME [PACKAGE.]SERVLET_NAME SERVLET_NAME /WEBAPPDIR/MyServlet FILTER_NAME myfilter.SimpleFilter FILTER_NAME SERVLET_NAME === 다수의 Web component를 등록할 때 === element에서 ****을 사용한다. **의 본체 내용** ^ 본체 내용 ^ 기능 ^ | /* |같은 Web application Directory에 있는 **모든 Web component**를 가리키는 URL Pattern. | | *.jsp |같은 Web application Directory에 있는 **모든 JSP Page**를 가리키는 URL Pattern. | | /PATH[/...]/* |PATH(상대경로)에 있는 **모든 Web component**를 가리키는 URL Pattern.\\ 상대경로가 다르면 여러개 등록 가능.\\ 주의점으로 와일드카드(*)와 **파일 확장자**를 함께 쓰면 안된다! | == Wrapper Class의 작성, 설치, 등록 == === 요청 Wrapper Class를 작성하는 방법 === - HttpServletRequestWrapper 상속 - **request** Instance의 Method 재정의 - 예) getParameter(), getParameterValues(), getParameterMap() - Filter Class의 doFilter()에서 chain.doFilter() Method의 첫 번째 인자를 직접 작성한 Wrapper Instance로 대체 === 응답 Wrapper Class를 작성하는 방법 === - HttpServletResponseWrapper 상속 - **response** Instance의 Method 재정의 - 예) addCokie() - Filter Class의 doFilter()에서 chain.doFilter() Method의 두 번째 인자를 직접 작성한 Wrapper Instance로 대체 ==== 본체 내용 조작 ==== * PrintWriter Class의 출력 Method를 재정의한다? * => print, println, printf, ... 너무 많다! 또한 Parameter Type도 여러 종류! * => **StringWriter** Class를 사용! (전체 내용을 버퍼에 담아 한꺼번에 출력) * [[#본체 내용 조작|참조]] = Database 사용하기 = == Database Connection Pool == Database에 대한 몇 개의 Connection을 미리 맺어놓은 후에\\ 그것을 한데 모아놓고\\ Web applcation들이 필요할 때마다 가져가서 사용한 후\\ 반환할수 있도록 만들어놓은 장소 * [[https://commons.apache.org/proper/commons-dbcp/download_dbcp.cgi | DBCP]] * [[http://commons.apache.org/proper/commons-collections/download_collections.cgi | Pool]] * [[http://commons.apache.org/proper/commons-collections/download_collections.cgi | Collections]] * 설치 경로 * 일반 : [TOMCAT]/lib * Eclipse : [APP]/WEB-INF/lib === Database Connection Pool을 생성하고 등록하는 Program의 작성 방법 === ==== 생성 ==== <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@page import="org.apache.commons.dbcp.*"%> <%@page import="org.apache.commons.pool.impl.GenericObjectPool"%> <%! private final static String DB_URL = "jdbc:mysql://localhost:3306/webdb"; private final static String DB_USER = "root"; private final static String DB_PASSWORD = "root"; private final static String DB_POOL_NAME = "/webdb_pool"; %> <% // Connection Pool 및 DB Connection 생성, 작동 GenericObjectPool objPool = new GenericObjectPool(); DriverManagerConnectionFactory connFactory = new DriverManagerConnectionFactory(DB_URL, DB_USER, DB_PASSWORD); /* 3번째 : PreparedStatement Pooling 기능 4번째 : DB 연결 검사 SELECT 문 5번째 : Read Only 여부 6번째 : Auto-commit 여부 */ new PoolableConnectionFactory(connFactory, objPool, null, null, false, true); // Web Container에 등록 PoolingDriver driver = new PoolingDriver(); /* XML을 이용해서 생성하는 DBCP은 이름 앞에 자동으로 "/"가 붙기 때문에 일관성을 위해 "/"로 시작하는 것이 좋다! */ driver.registerPool(DB_POOL_NAME, objPool); %> DBCP 생성 DBCP 생성 및 등록 성공!
Pool name : <%=DB_POOL_NAME %>
==== 연결 및 해제 ==== <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" errorPage="DBError.jsp"%> <%@page import="java.sql.*"%> <%! private final static String DB_POOL_NAME = "/webdb_pool"; %> Test DBCP <% Class.forName("org.apache.commons.dbcp.PoolingDriver"); Class.forName("com.mysql.jdbc.Driver"); Connection conn = DriverManager.getConnection("jdbc:apache:commons:dbcp:" + DB_POOL_NAME); if(conn == null) { out.println("연결 실패"); return; } out.println("연결 취득 완료
"); conn.close(); out.println("연결 반환 완료
"); %>
==== 조회 ==== 1. 자동 DBCP 생성 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@page import="org.apache.commons.dbcp.*"%> <%@page import="org.apache.commons.pool.impl.GenericObjectPool"%> <%! private final static String DB_URL = "jdbc:mysql://localhost:3306/webdb"; private final static String DB_USER = "root"; private final static String DB_PASSWORD = "root"; private final static String DB_POOL_NAME = "/webdb_pool"; public void jspInit() { GenericObjectPool objPool = new GenericObjectPool(); DriverManagerConnectionFactory connFactory = new DriverManagerConnectionFactory(DB_URL, DB_USER, DB_PASSWORD); new PoolableConnectionFactory(connFactory, objPool, null, null, false, true); PoolingDriver driver = new PoolingDriver(); driver.registerPool(DB_POOL_NAME, objPool); } %> auto-create-db-pool-jsp /AutoCreateDBPool.jsp 1 2. 연결 및 조회 <%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" errorPage="DBError.jsp"%> <%@page import="java.sql.*"%> <%@page import="java.io.UnsupportedEncodingException"%> <%! private final static String DB_POOL_NAME = "/webdb_pool"; %> <% String code = request.getParameter("code"); Connection conn = null; Statement stmt = null; try { Class.forName("org.apache.commons.dbcp.PoolingDriver"); Class.forName("com.mysql.jdbc.Driver"); conn = DriverManager.getConnection("jdbc:apache:commons:dbcp:" + DB_POOL_NAME); if(conn == null) throw new Exception("연결 불가!"); stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM goodsinfo WHERE code = '" + code + "';"); if(rs.next()) { String title = rs.getString("title"); String writer = rs.getString("writer"); String price = rs.getString("price"); request.setAttribute("CODE", code); /* request.setAttribute("TITLE", toUnicode(title)); request.setAttribute("WRITER", toUnicode(writer)); */ request.setAttribute("TITLE", title); request.setAttribute("WRITER", writer); request.setAttribute("PRICE", new Integer(price)); } } finally { try { stmt.close(); } catch (Exception e) { } try { conn.close(); } catch (Exception e) { } } RequestDispatcher dispatcher = request.getRequestDispatcher("GoodsInfoViewer.jsp"); dispatcher.forward(request, response); %> <%! private String toUnicode(String str) { try { byte[] b = str.getBytes("ISO-8859-1"); return new String(b); } catch (UnsupportedEncodingException e) { System.err.println(e.getMessage()); return null; } } %> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> 상품 정보 ${CODE}
${TITLE}
${WRITER}
${PRICE}
=== JOCL File을 이용한 Database Connection Pool 생성 방법 === **J**ava **O**bject **C**onfiguration **L**anguage DBCP 생성에 필요한 객체 정보를 "[FILENAME].jocl"이란 XML 문서에 기술하여 사용. **이 때, DBCP명은 자동으로 [FILENAME]이 된다!** 1. jocl 작성 2. Library 설치 JDBC, DBCP, POOL, Collections를 WEB-INF/lib 에 복사. 3. 프로그램 작성 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" errorPage="DBError.jsp"%> <%@page import="java.sql.*"%> <%@page import="org.apache.commons.dbcp.PoolingDriver"%> <%! private final static String DB_POOL_NAME = "/wdbpool"; %> Test DBCP <% Class.forName("org.apache.commons.dbcp.PoolingDriver"); Class.forName("com.mysql.jdbc.Driver"); Connection conn = DriverManager.getConnection("jdbc:apache:commons:dbcp:" + DB_POOL_NAME); if(conn == null) { out.println("연결 실패"); return; } out.println("연결 취득 완료

"); out.println("현재 작동중인 DBCP
"); PoolingDriver driver = (PoolingDriver) DriverManager.getDriver("jdbc:apache:commons:dbcp:"); String[] names = driver.getPoolNames(); for(String name : names) out.println(name + "
"); out.println("
"); conn.close(); out.println("연결 반환 완료
"); %>