Java Server Pages
Java의 특성을 물려받는다. ⇒ 플랫폼 독립적 + 보안↑ + 멀티스레드
(Servlet과 반대로) HTML 문서에 Java 코드가 삽입되는 구조
→ HTML 코드는 웹브라우저로 그대로 전송
→ JSP 코드는 웹 컨테이너 쪽에서 실행되고 결과만 웹 브라우저로 전송 (Servlet에 비해 밑줄 친 단계가 추가된 것.)
장점 | 단점 | |
---|---|---|
Servlet | - HTML 문서에 소스코드가 공개되지 않는다. | - Java 코드안에 HTML이 작성된다. ⇒디자인시 수정에도 코드 변경 필요! - 설치과정이 복잡하다. |
JSP | - HTML 중심의 코드 구조로 수정이 쉽다. - 설치과정이 쉽다. | - HTML 문서에서 소스 코드가 공개된다. |
그러나 복잡한 로직을 필요로 하는 경우 Servlet을 사용해서, JSP 페이지에 결과만 출력하는 구조가 적합하다!
Java를 기반으로 하는 웹 어플리케이션 프로그래밍 기술
웹 컨테이너가 Servlet을 운영하는 방법으로
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" version="3.0"> <servlet> <servlet-name>NAME</servlet-name> <!-- 4, 8번줄 같아야 한다. --> <servlet-class>[PACKAGE.]SERVLET_NAME</servlet-class> <!-- 생성한 Servlet 이름 (Package 포함!) --> </servlet> <servlet-mapping> <servlet-name>NAME</servlet-name> <!-- 4, 8번줄 같아야 한다. --> <url-pattern>/WEBAPPDIR/MyServlet</url-pattern> <!-- /웹 애플리케이션 디렉토리/"URL패턴" --> </servlet-mapping> </web-app>
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"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=EUC-KR"> <title>Insert title here</title> </head> <body> <% int a = 3; int b = 4; int total = add(a, b); %> <%! private int add(int a, int b) { return a+b; } %> <%=a %> + <%=b %> = <%=total %> </body> </html>
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 무시/처리 여부 |
... <body> <%@include file="example.jsp" %> </body> ...
<%@taglib prefix="c" uri="http://java.sun.com/jsp/js1/core" %>
Servlet 클래스로 컴파일 과정에서
JSP 주석(<%-- --%>) | HTML 주석() Java 주석(// /* */) |
---|---|
제거된다. | 그대로 기록된다. |
변수명 | 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("<br>"); %> <% 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 처리 |
<% RequestDispatcher dispatcher = request.getRequestDispatcher("ex.jsp"); //상대경로만 사용가능! 절대경로 불가능! //request.setAttribute("NAME", new Integer(7)); //String, Object dispatcher.forward(request, response); %>
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"); |
<% out.flush(); //출력 버퍼에서 JSP 코드 이전의 HTML 코드 제거. RequestDispatcher dispatcher = request.getRequestDispatcher("ex.jsp"); //상대경로만 사용가능! 절대경로 불가능! //request.setAttribute("NAME", new Integer(7)); //String, Object dispatcher.include(request, response); %>
포함된 Web component가 별도의 Servlet class를 생성하는가?
include() | include 지시자 |
---|---|
O | X1) |
입력된 데이터가 URL에
get | post |
---|---|
공개 | 비공개 |
Cookie | Session | |
---|---|---|
저장 위치 | Client | Server |
저장 Type | String | Object |
용량 제한 | 4KB, 한 Client(Domain) 당 20개 | 서버가 허용하는 한 용량, 개수 제한 없음 |
단일 기록량 | 1 | 多 (☞ Hashtable 사용) |
Web Component(JSP 페이지와 Servlet 클래스를 통칭)간의 데이터를 송수신이 가능케하는 기술.
WWW 등장 초창기에는 인프라 구축이 덜 되어 대규모의 동시 사용자를 위한 웹앱의 중간 데이터를 서버 쪽에 저장해 두는 것이 어려웠기 때문에 Cookie 기술이 먼저 개발되었다. (= Client측에서 처리)
<%@page contentType="text/html; charset=euc-kr" %> //HTML 코드 명령문보다 앞에 오는 것이 바람직. (Buffer 때문) <% //두 Argument는 "String" Type! 수치값인 경우 String Data로 만들어야 한다! //쿠키명 같으면 "수정(Set)". response.addCookie(new Cookie("AGE", "20")); %> <html> ... </html>
<%@page contentType="text/html; charset=EUC-KR" %> <% Cookie[] cookies = request.getCookies(); //배열! %> <html> <head><title></title></head> <body> Age : <%= getCookieValue(cookies, "AGE") %> </body> </html> <%! 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)' %> <html> ... </html>
<%@page contentType="text/html; charset=euc-kr" %> <% Cookie cookie = new Cookie("Age", "20"); cookie.setPath("/local/"); //URL 경로명은 "반드시 /로 시작"해야하고, 마지막도 /로 끝내는 것을 권장. response.addCookie(cookie); %> <html> ... </html>
<%@page contentType="text/html; charset=euc-kr" %> <% Cookie cookie = new Cookie("Age", "20"); cookie.setDomain(".site.co.kr"); //대표 도메인 설정. "."로 시작해야 한다! response.addCookie(cookie); %> <html> ... </html>
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); //타임아웃 기간 설정.(초단위), 음수값이면 무한대
<% /* 반환 결과는 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시 세션 유지 %>
일반적인 Java 프로그램의 try~catch를 이용하게 되면 HTML 코드와 섞여 난잡해진다. 이를 해결하기 위해 Exception 처리를 위한 웹 컴포넌트를 별도로 만들어 호출하면 된다.
<%@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 설정. <html> <body> <%= exception.getMessage() %> //isErrorPage 지시자를 이용하면 세부적인 Exception 메시지를 확인할 수 있다. </body> </html>
웹 컴포넌트의 규모가 커질 경우 여러 페이지의 공통 Exception을 처리할 수 있으므로 효율적.
<web-app ... > ... <error-page> <exception-type>java.lang.NumberFormatException</exception-type> <!-- Type --> <location>/Error.jsp</location> <!-- Exception 처리 페이지 경로명 --> </error-page> ... </web-app>
//① 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); }
<web-app ... > ... <error-page> <error-code>404</error-code> <!-- HTTP 상태 코드. 404는 웹 자원이 없을 때, 500은 웹 컴포넌트 안의 Exception 발생 상태 코드 --> <location>/Error.jsp</location> <!-- Exception 처리 페이지 경로명 --> </error-page> ... </web-app>
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("<html>"); out.println("<head><title>Fibonacci</title></head"); out.println("<body>"); for(int i = 0; i < num ; i++) { out.println(arr[i] + " "); } out.println("</body>"); out.println("</html>"); } }
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" version="3.0"> <servlet> <servlet-name>finabocciServlet</servlet-name> <servlet-class>Finabocci</servlet-class> <!-- 매번 Servlet을 실행할 때마다 대기시간이 길어질 수 있다. 해결방법은?? --> <!-- Web Container가 시작될 때 초기화한다. --> <!-- 내부 정수값은 우선순위. 작을수록 높음. --> <load-on-startup>0</load-on-startup> </servlet> <servlet-mapping> <servlet-name>finabocciServlet</servlet-name> <url-pattern>/test</url-pattern> </servlet-mapping> </web-app>
Log Writer
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Log Writer</title> </head> <body> <form action="logwriter"> <input type="text" name="MESSAGE"> <input type="submit" value="확인"> </form> </body> </html>
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("<html>"); out.println("<head><title>test</title></head>"); out.println("<body>"); out.println(message + "이 기록되었습니다."); out.println("</body>"); out.println("</html>"); } @Override public void destroy() { if(logFile != null) logFile.close(); } }
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" version="3.0"> <servlet> <servlet-name>logWriter-servlet</servlet-name> <servlet-class>LogWriter</servlet-class> <!-- 소스 코드를 건들지 않고 Path 변경 --> <!-- 초기화 Parameter --> <init-param> <param-name>FILE_NAME</param-name> <param-value>C:\\log.txt</param-value> </init-param> <load-on-startup>0</load-on-startup> </servlet> <servlet-mapping> <servlet-name>logWriter-servlet</servlet-name> <url-pattern>/logwriter</url-pattern> </servlet-mapping> </web-app>
※ 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); } } %> <!DOCTYPE html> <html> <head> <title>logWriter</title> </head> <body> <% 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 + "<br>"); out.println(time + "<br>"); } else out.print("초기화 실패"); %> </body> </html> <%! public void jspDestroy() { if(logFile != null) logFile.close(); } %>
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <servlet> <servlet-name>logWriter-jsp</servlet-name> <!-- Servlet 설정과 비교했을 때 아래 부분만 다름 --> <jsp-file>/logWriter.jsp</jsp-file> <!-- 소스 코드를 건들지 않고 Path 변경 --> <!-- 초기화 Parameter --> <init-param> <param-name>FILE_NAME</param-name> <param-value>C:\\log2.txt</param-value> </init-param> <load-on-startup>0</load-on-startup> </servlet> <servlet-mapping> <servlet-name>logWriter-jsp</servlet-name> <url-pattern>/logwriter</url-pattern> </servlet-mapping> </web-app>
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("<html>"); out.println("<head><title>ServerInfo</title></head>"); out.println("<body>"); /* tomcat 버전과 Servlet 버전 출력*/ out.println(serverInfo + " // " + majorVersion + "." + minorVersion); out.println("</body>"); out.println("</html>"); } }
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <title>ServerInfo</title> </head> <body> <%= application.getServerInfo() %> // <%= application.getMajorVersion() %> . <%= application.getMinorVersion() %> </body> </html>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <title>ServerInfo</title> </head> <body> <!-- 결과적으로 Hello, world! 출력 --> <%= application.getInitParameter("PARAM_TEST") %> </body> </html>
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <!-- Web application 전체 속하는 초기화 Parameter --> <context-param> <param-name>PARAM_TEST</param-name> <param-value>Hello, world!</param-value> </context-param> </web-app>
application.setAttribute(String arg0, Object arg1) |
---|
application.getAttribute(String arg0) |
application.removeAttribute(String arg0) |
호출할 때 사용하는 내장 변수 | Method 소속 | Data 전송 범위 | 용도 | 다루는 장 |
---|---|---|---|---|
pageContext | javax.servlet.jsp.JspContext 클래스 | 현재 JSP 페이지 내 | 같은 JSP 페이지 안에 있는 Scripting 요소와 Expression Language 간의 Data 교환 | 7장 |
request | javax.servlet.ServletRequest 인터페이스 | 현재 웹 컴포넌트 및 forward(), include()를 통해 호출되는 또 다른 Web component | forward(), include()를 통해 호출되는 Web component로의 Data 전달 | 3장 |
session | javax.servlet.http.HttpSession | 같은 세션에 속하는 모든 Web component | 여러 화면으로 구성되는 Application에서 Web component간의 Data 전달 | 4장 |
application | javax.servlet.ServletContext 인터페이스 | 같은 Web application에 속하는 모든 Web component | 같은 Web application의 Directory에 속하는 Web component간의 Data 공유 | 6장 |
${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); %> <!DOCTYPE html> <html> <head> <title>EL</title> </head> <body> <!-- <%= request.getAttribute("SUM") %> 동일. --> ${SUM} <br><br> <!-- 산술연산자 및 논리연산자 사용이 가능 --> ${SUM * 2} <br> ${SUM == 55} <!-- 정적 Method 호출은 하단 참조 --> </body> </html>
${ATTRIBUTE_NAME}
${pageScope.SUM} ${requestScope.SUM} ${sessionScope.SUM} ${applicationScope.SUM}
내장 객체 이름 | 표현하는 데이터 | Type |
---|---|---|
pageScope | page Attribute 집합 | Map |
requestScope | request Attribute 집합 | Map |
sessionScope | session Attribute 집합 | Map |
applicationScope | application Attribute 집합 | Map |
param | Web browser로 입력된(<form> 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의 환경 정보 집합 ( javax.servlet.jsp.PageContext) | PageContext |
pageContext를 제외하고 모두 Map Type이기 때문에
두 가지 방법으로 사용 가능하다. (b 방법에서 큰 따옴표(“) 대신 작은 따옴표(')로 사용 가능하다.)
단, ATTRIBUTE_NAME이 Java 식별자 명명 규칙을 따르지 않는 경우(첫 글자가 숫자이거나 영문자, 숫자, $/_ 이외 특수문자가 포함된 경우) b 방법을 사용해야 한다.
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>input</title> </head> <body> <form action="result.jsp"> 성 <input type="text" name="lastName"> <br> 이름 <input type="text" name="firstName"> <br><br> 좋아하는 음식 <br> <input type="checkbox" name="food" value="초콜릿"> 초콜릿 <input type="checkbox" name="food" value="국수"> 국수 <input type="checkbox" name="food" value="탕수육"> 탕수육 <input type="checkbox" name="food" value="스테이크"> 스테이크 <br><br> 성별 <select name="sex"> <option>남</option> <option>여</option> </select> <br><br> <input type="reset" value="취소"> <input type="submit" value="확인"> </form> </body> </html>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <title>result</title> </head> <body> <!-- 하나일 경우 아래 두 가지 방식으로 표현 가능. (" 대신 ' 사용 가능.) --> 성 : ${param.lastName} <br> 이름 : ${param["firstName"]} <br> <!-- 여러개일 경우 아래 두 가지 방식으로 표현 가능. (" 대신 ' 사용 가능.) --> 좋아하는 음식 : ${paramValues.food[0]} ${paramValues.food[1]} ${paramValues.food[2]} ${paramValues.food[3]} <br> 성별 : ${paramValues["sex"][0]} ${paramValues["sex"][1]} </body> </html>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% Cookie c = new Cookie("job", "Developer"); response.addCookie(c); %> <!DOCTYPE html> <html> <head> <title>result</title> </head> <body> value : ${cookie.job.value} <br> domain : ${cookie.job.domain} <br> path : ${cookie.job.path} <br> maxAge : ${cookie.job.maxAge} <br> </body> </html>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <title>ServerInfo</title> </head> <body> <!-- Firefox일 경우 --> <!-- Mozilla/5.0 (Windows NT 6.1; Win64; x64; Trident/7.0; rv:11.0) like Gecko --> ${header["User-Agent"]}<br> <!-- application/x-ms-application, image/jpeg, application/xaml+xml, image/gif, image/pjpeg, application/x-ms-xbap, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */* --> ${headerValues.Accept[0]} </body> </html>
초기화 Parameter 가져오는 getInitParameter() 그대로 인용.
... <!-- 결과적으로 Hello, world! 출력 --> ${initParam.PARAM_TEST} ...
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% HttpSession s = request.getSession(); session.setAttribute("mySession", "Hello, world!"); %> <!DOCTYPE html> <html> <head> <title>ServerInfo</title> </head> <body> <!-- mySession --> ${pageContext.session.valueNames[0]}<br> <!-- /Example/result.jsp --> ${pageContext.request.requestURI} </body> </html>
div | / |
---|---|
mod | % |
lt (less than) | < |
gt (greater than) | > |
le (less or equal to) | <= |
ge (greater or equal to) | >= |
eq (equal to) | == |
ne (not equal to) | != |
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <title>ServerInfo</title> </head> <body> <!-- true --> ${"apple" lt "banana"} </body> </html>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <title>ServerInfo</title> </head> <body> <!-- Data의 존재 여부 확인 --> ${empty param.ID ? "guest" : param.ID} </body> </html>
아래 4가지 항목을 가리킨다.
<%@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<String> list = new ArrayList<>(); list.add("a"); list.add("b"); list.add("c"); request.setAttribute("LIST", list); HashMap<String, Integer> 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); %> <!DOCTYPE html> <html> <head> <title>test</title> </head> <body> <!-- 배열의 Data 출력 --> ${ARR[0]} ${ARR[1]} ${ARR[2]}<br> <!-- List의 Data 출력 --> ${LIST[0]} ${LIST[1]} ${LIST[2]}<br> <!-- Map의 Data 출력 (두 가지 방식 사용 가능) --> ${MAP["Jake"]} ${MAP.Chris}<br> <!-- JavaBeans Property의 Data 출력 (두 가지 방식 사용 가능) --> <!-- 원론적으로는 해당 class를 컴파일하여 [Web application]/WEB-INF/classes/[Package] 에 넣어야 한다. --> <!-- default package는 불가!!! --> <!-- 그러나 Eclipse를 사용할 경우 Java Resources/src에 class 생성하면 자동으로 컴파일이 되어 바로 참조 가능. (이미 설정되어 있음.) --> ${BEAN["name"]} ${BEAN.age}<br> </body> </html>
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; } }
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(); } }
<?xml version="1.0" encoding="UTF-8"?> <taglib xmlns="http://java.sun.com/xml/ns/j2ee" version="2.1"> <!-- 아래 두 element는 반드시 작성! --> <tlib-version>tlib-version</tlib-version> <short-name>short-name</short-name> <function> <name>sqrt</name> <function-class>java.lang.Math</function-class> <function-signature>double sqrt(double)</function-signature> </function> <function> <name>parseInt</name> <function-class>java.lang.Integer</function-class> <!-- Full package 명을 기입해야 한다! --> <function-signature>int parseInt(java.lang.String)</function-signature> </function> <!-- 사용자 정의 함수 --> <function> <name>total</name> <function-class>util.MyMath</function-class> <function-signature>int sum(int, int)</function-signature> </function> <function> <name>now</name> <function-class>util.MyMath</function-class> <function-signature>java.util.String now()</function-signature> </function> </taglib>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib uri="../../math-func.tld" prefix="m" %> <!DOCTYPE html> <html> <head> <title>test</title> </head> <body> 제곱근 : ${m:sqrt(25)} <br> 문자→숫자 : ${m:parseInt("123")} <br> 사용자 정의 합 : ${m:total(1, 10)} <br> 사용자 정의 현재 시간 : ${m:now()} <br> </body> </html>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>index</title> </head> <body> <h1>오늘의 메뉴</h1> <ul> <li>짜장면</li> <li>짬뽕</li> <li>볶음밥</li> </ul> <br> <!-- 별도의 class 파일을 생성하지 않음. 현재 JSP 파일의 Servlet class에서 코드가 포함됨. --> <%-- <%@include file="today.jsp" %> --%> <!-- 별도의 class 파일을 생성함. --> <%-- <% out.flush(); RequestDispatcher dispatcher = request.getRequestDispatcher("today.jsp"); dispatcher.include(request, response); %> --%> <!-- 별도의 class 파일을 생성함. --> <!-- 즉, include() 메소드와 동일. --> <jsp:include page="today.jsp" /> </body> </html>
<%@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) %>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>index</title> </head> <body> <% int sum = 0; for(int i=1 ; i<=100 ; i++) sum+=i; request.setAttribute("RESULT", sum); %> <jsp:forward page="result.jsp" /> </body> </html>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>result</title> </head> <body> 합 : ${RESULT} </body> </html>
JavaBean은 [], . 연산자 사용.
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>index</title> </head> <body> <!-- id : 변수이름 --> <!-- JavaBean 객체의 기본 생존 범위는 JSP "page" 안 --> <!-- forward를 이용해 Data를 공유하려면 최소 "request" 설정 --> <!-- page < request < session < application --> <jsp:useBean id="info" class="bean.PersonInfo" scope="request" /> <jsp:setProperty property="name" value="Luke" name="info" /> <jsp:setProperty property="age" value="28" name="info" /> <!-- 위와 같이 연달아 action이 나오는 경우 아래 방법으로도 사용 가능. --> <%-- <jsp:useBean id="info" class="bean.PersonInfo" scope="request"> <jsp:setProperty property="name" value="Luke" name="info" /> <jsp:setProperty property="age" value="28" name="info" /> </jsp:useBean> --%> <jsp:forward page="result.jsp" /> </body> </html>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>result</title> </head> <body> <jsp:useBean id="info" class="bean.PersonInfo" scope="request" /> 이름 : <jsp:getProperty property="name" name="info"/> <br> 나이 : <jsp:getProperty property="age" name="info"/> </body> </html>
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>input</title> </head> <body> <form action="result.jsp"> 이름 : <input type="text" name="name"> <br> 나이 : <input type="text" name="age"> <br> <input type="submit" value="확인"> </form> </body> </html>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>result</title> </head> <body> <jsp:useBean id="info" class="bean.PersonInfo" /> <!-- value="${PARAM.NAME}"과 param="NAME" 결과 동일. --> <!-- 당연한 얘기지만 value와 param 혼용 불가. --> <%-- <jsp:setProperty property="name" name="info" param="name" /> <jsp:setProperty property="age" name="info" param="age" /> --%> <!-- Property 이름과 입력 데이터의 이름이 동일(대소문자 구분)하다면 아래 방식으로 사용 가능. --> <jsp:setProperty property="*" name="info" /> 이름 : <jsp:getProperty property="name" name="info"/> <br> 나이 : <jsp:getProperty property="age" name="info"/> </body> </html>
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"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>index</title> </head> <body> <jsp:useBean id="info" class="bean.EmployeeInfo" scope="request"> <jsp:setProperty property="name" name="info" value="Luke" /> <jsp:setProperty property="age" name="info" value="28" /> </jsp:useBean> <jsp:forward page="result.jsp" /> </body> </html>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>result</title> </head> <body> <!-- 만약, 상속받은 요소가 추상 클래스거나 인터페이스인 경우 "type" attribute를 사용한다! --> <jsp:useBean id="info" type="bean.PersonInfo" scope="request" /> 이름 : <jsp:getProperty property="name" name="info"/> <br> 나이 : <jsp:getProperty property="age" name="info"/> </body> </html>
문법의 3종류 대신 사용 가능.
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>index</title> </head> <body> <%-- <% %> --%> <jsp:scriptlet> int num1 = 1; int num2 = 2; </jsp:scriptlet> <%-- <%= %> --%> <jsp:expression>add(num1, num2)</jsp:expression> <%-- <%! %> --%> <jsp:declaration> private int add(int a, int b) { return a + b; } </jsp:declaration> <br> <%-- <%@ %> --%> <jsp:directive.include file="today.jsp" /> </body> </html>
JSP Standard Tag Library
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 |
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
변수 선언 및 초기화.
<!-- 전달되는 Data의 Attribute 이름이 "num"일 때, --> <!-- 사용가능 --> ${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" %> <c:set var="num1" value="7" scope="request" /> <c:set var="num2" value="9" scope="request" /> <c:set var="result" value="${num1*num2}" scope="request" /> <jsp:forward page="result.jsp" />
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>result</title> </head> <body> ${num1} * ${num2} = ${result} <!-- attribute 형태이므로 Expression 사용 불가 --> </body> </html>
특정 Attribute 삭제.
<!-- scope를 지정하지 않으면 --> <!-- "num"이라는 이름의 Attribute를 --> <!-- 모든 영역(page, request, session, application)에서 삭제. --> <c:remove var="num" scope="request" />
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <c:set var="num1" value="1" scope="request" /> <c:set var="num2" value="9" scope="request" /> <jsp:forward page="result.jsp" />
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>result</title> </head> <body> <!-- "test" attribute 빼먹지 말자! --> <!-- "test" 안에는 EL식! --> <c:if test="${num1 >= num2}" var="result"> num1이 크거나 같다! <br> <br> ${result} </c:if> <c:if test="${num1 < num2}" var="result"> num2가 크다! <br> ${result} </c:if> </body> </html>
switch와 같은 역할.
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <c:set var="num1" value="99" scope="request" /> <jsp:forward page="result.jsp" />
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>result</title> </head> <body> <c:choose> <c:when test="${num == 0}"> <!-- switch의 case --> 0이다! </c:when> <c:when test="${num == 1}"> 1이다! </c:when> <c:otherwise> <!-- switch의 default --> 0도 1도 아니다! </c:otherwise> </c:choose> </body> </html>
<%@ 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); %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>result</title> </head> <body> <!-- 1부터 10까지, 2간격식. --> <c:forEach var="cnt" begin="1" end="10" step="2"> <font size=${cnt}>야호</font> <br> </c:forEach> <!-- Iterator --> <ul> <c:forEach var="dish" items="${MENU}"> <li>${dish}</li> </c:forEach> </ul> </body> </html>
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" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>result</title> </head> <body> <c:set var="str" value="동해물과 백두산이/마르고^닳도록" /> <c:forTokens var="lyric" items="${str}" delims=" /^"> ${lyric} <br> </c:forTokens> </body> </html>
try 문.
<!-- http://localhost:8080/Example2/result.jsp?NUM1=10&NUM2=0 --> <%@ 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")); %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>result</title> </head> <body> <!-- "catch" block에 해당하는 code는 별도 작성 필요. --> <c:catch var="e"> <% int result = num1 / num2; %> <%= result %> </c:catch> <c:if test="${e != null}"> ${e.message} </c:if> </body> </html>
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" %> <c:redirect url="result.jsp"> <c:param name="num1" value="7" /> <c:param name="num2" value="11" /> </c:redirect>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>result</title> </head> <body> <!-- attribute가 아닌 parameter! --> ${param.num1} * ${param.num2} = ${param.num1 * param.num2} </body> </html>
현재 JSP 페이지에 다른 Web resource를 포함시킴.
사용법은 <c:redirect>와 비슷. 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" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>result</title> </head> <body> <!-- /Example2/result.jsp?NUM1=999&NUM2=111 --> <c:url var="myUrl" value="/result.jsp"> <c:param name="NUM1" value="999" /> <c:param name="NUM2" value="111" /> </c:url> ${myUrl} </body> </html> </html>
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" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>result</title> </head> <body> <!-- Tag를 해석하지 않고 그대로 출력 --> <c:out value="<h1>Test</h1>" /> <br> <!-- Tag를 해석한다. --> <c:out value="<h1>Test</h1>" escapeXml="false" /> <!-- 출력 Data가 없는 경우, default 출력 --> <c:out value="${param.NAME}" default="Hello!" /> </body> </html>
날짜와 시간 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" %> <c:set var="date" value="<%= new Date() %>" /> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>result</title> </head> <body> <!-- 2016. 6. 29 --> <fmt:formatDate value="${date}" /> <br> <!-- 오후 11:49:09 --> <fmt:formatDate value="${date}" type="time" /> <br> <!-- 2016. 6. 29 오후 11:49:09 --> <fmt:formatDate value="${date}" type="both" /> <br><br> <!-- 16. 6. 30 오전 12:00 --> <fmt:formatDate value="${date}" type="both" dateStyle="short" timeStyle="short" /> <br> <!-- 2016. 6. 30 오전 12:00:28 --> <fmt:formatDate value="${date}" type="both" dateStyle="medium" timeStyle="medium" /> <br> <!-- 2016년 6월 30일 (목) 오전 12시 00분 28초 --> <fmt:formatDate value="${date}" type="both" dateStyle="long" timeStyle="long" /> <br> <!-- 2016년 6월 29일 수요일 오후 3:00:28 --> <fmt:formatDate value="${date}" type="both" dateStyle="full" timeZone="full" /> <br> <br><br> <!-- 2016/06/30 (목) --> <fmt:formatDate value="${date}" type="date" pattern="yyyy/MM/dd (E)" /> <br> <!-- (오전) 12:09:23 --> <fmt:formatDate value="${date}" type="time" pattern="(a) hh:mm:ss" /> <br> </body> </html>
수치 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" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>result</title> </head> <body> <!-- 1,234,500 --> <fmt:formatNumber value="1234500" groupingUsed="true" /> <br> <!-- 3.14 --> <fmt:formatNumber value="<%= Math.PI %>" pattern="#.##" /> <br> <!-- 10.50 --> <fmt:formatNumber value="10.5" pattern="#.00#" /> <br><br> <!-- 120% --> <fmt:formatNumber value="1.2" type="percent" /> <br> <!-- ₩123,000 --> <fmt:formatNumber value="123000" type="currency" /> <br> <!-- $123,000 --> <fmt:formatNumber value="123000" type="currency" currencySymbol="$" /> </body> </html>
지역 설정.
<%@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" %> <c:set var="date" value="<%=new Date()%>" /> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>result</title> </head> <body> <fmt:setLocale value="ko_kr"/> <!-- ₩1,000,000 2016년 6월 30일 목요일 오후 12시 28분 45초 KST --> <fmt:formatNumber value="1000000" type="currency" /> <br> <fmt:formatDate value="${date}" type="both" dateStyle="full" timeStyle="full" /> <br><br> <fmt:setLocale value="en_us"/> <!-- $1,000,000.00 Thursday, June 30, 2016 12:28:45 PM KST --> <fmt:formatNumber value="1000000" type="currency" /> <br> <fmt:formatDate value="${date}" type="both" dateStyle="full" timeStyle="full" /> <br><br> <fmt:setLocale value="ja_jp"/> <!-- ¥1,000,000 2016年6月30日 12時28分45秒 KST --> <fmt:formatNumber value="1000000" type="currency" /> <br> <fmt:formatDate value="${date}" type="both" dateStyle="full" timeStyle="full" /> </body> </html>
지역별 시간대 설정.
TimeZone.getAvailableIDs()으로 사용 가능한 value Attribute를 얻는다.
<%@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" %> <c:set var="date" value="<%=new Date()%>" /> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>result</title> </head> <body> <!-- 2016년 6월 30일 목요일 오전 9:57:48 --> <fmt:setTimeZone value="Europe/Berlin"/> <fmt:formatDate value="${date}" type="both" dateStyle="full" /> <br> <!-- 2016년 6월 30일 목요일 오전 2:57:48 --> <fmt:timeZone value="America/Lima"> <fmt:formatDate value="${date}" type="both" dateStyle="full" /> </fmt:timeZone> </body> </html>
다국어 지원.
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=회사 소개 GREETING={0}님 안녕하세요. {1}번째 방문이시군요! BODY=당사는 소프트웨어 개발을 주업무로 하는 회사입니다. COMPANY_NAME=(주) 듀크 소프트웨어 --> 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" %> <c:set var="ID" value="Jake" scope="request" /> <c:set var="COUNT" value="3" scope="request" /> <jsp:forward page="result.jsp" />
<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> <fmt:setBundle basename="intro"/> <!-- 변수로 저장하여 사용할 수도 있다! --> <fmt:message var="title" key="TITLE" /> <!-- Parameter를 받아 처리할 수도 있다. --> <fmt:message var="greeting" key="GREETING" > <fmt:param>${ID}</fmt:param> <fmt:param>${COUNT}</fmt:param> </fmt:message> <!-- 회사 소개 당사는 소프트웨어 개발을 주업무로 하는 회사입니다. Jake님 안녕하세요. 3번째 방문이시군요! (주) 듀크 소프트웨어 --> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>${title}</title> </head> <body> <h1>${title}</h1> <fmt:message key="BODY" /> <br> <!-- parameter 받아 출력 --> ${greeting} <br> <br> <fmt:message key="COMPANY_NAME" /> </body> </html>
POST Method로 전송된 한글 입력 Data를 받기 위해 필요.
Expression Language과 Ac ti on을 이용하면 코드 작업량을 줄일 수 있고, 가독성에서도 유리하므로 Web designer에게도 편리하기 때문에 Scripting Elements를 사용하지 않도록 권장된다.
그런데 이 때 발생하는 문제가 한글 인코딩(<% request.setCharacterEncoding("euc-kr") %>)을 사용해야 하는 경우와 충돌되는 데, 이런 경우에 사용한다.
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Log Writer</title> </head> <body> <form action="result.jsp" method="POST" > 한글이름 <input type="text" name="NAME"> <br> <input type="submit" value="확인"> </form> </body> </html>
<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> <fmt:requestEncoding value="UTF-8" /> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>test</title> </head> <body> 한글이름 : ${param.NAME} </body> </html>
주로 문자열 처리. String Class의 Method와 비슷한 기능 제공.
<%@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" %> <c:set var="str" value="<h1>hello, world!</h1>" /> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>test</title> </head> <body> <!-- <h1> Tag가 적용된 "HELLO, WORLD!" --> ${fn:toUpperCase(str)} <br> <!-- world! --> ${fn:split(str, " ")[1]} <br> <!-- <h1>hello, world!</h1> --> ${fn:escapeXml(str)} </body> </html>
Tag file과 Tag class의 선택 기준
지시자 이름 | 역할 | 비고 |
---|---|---|
include | 다른 Tag file 포함 | |
taglib | 다른 Custom action의 Tag library 정보 기술 | |
tag | Web container가 Tag file을 compile 및 실행하기 위한 정보 기술 | tag file에서만 사용 가능. |
attribute | Custom action의 attribute 기술 | |
variable | Custom action의 변수 정보 기술 |
<!-- 아래 지시자와 attribute를 지정하면 body(본체)를 가질 수 없도록 제한함. --> <%@tag body-content="empty" %> ----------------------------------<br>
<%@tag body-content="empty" %> <%@attribute name="color" %> <!-- 기본적으로 attribute value는 String이므로 변환 필요 --> <!-- required="true"는 attribute 기술 강제 요구 --> <%@attribute name="size" type="java.lang.Integer" required="true" %> <font color=${color} > <% for(int i=0 ; i<size ; i++) out.print("-"); %> </font><br>
<%@tag import="java.util.Map"%> <%@tag body-content="empty" %> <%@tag dynamic-attributes="attrs" %> <font color=${attrs.color} > <% Map<String, String> attrs = (Map<String, String>)jspContext.getAttribute("attrs"); int size = Integer.parseInt(attrs.get("size")); for(int i=0 ; i<size ; i++) out.print("-"); %> </font><br>
<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="u" tagdir="/WEB-INF/tags" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>test</title> </head> <body> <!-- ---------------------------------- --> <u:line /> <%-- <u:line>Error 발생!</u:line> --%> <!-- attribute value를 갖는 Custom tag --> <!-- 적색의 "-" 25개 --> <u:line_att color="red" size="25" /> <!-- dynamic attribute value를 갖는 Custom tag --> <!-- attribute가 존재하는 지, 값이 유효한 지 확인하지 않음. 문법적 유연성 제공. --> <u:line_datt color="blue" size="100" style="bold" /> </body> </html>
<%@tag body-content="scriptless" %> <table border="1" cellpadding="20"> <tr> <td> <!-- 본체 내용 출력. (tag file에서만 사용할 수 있다!) --> <jsp:doBody /> </td> </tr> </table>
<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="u" tagdir="/WEB-INF/tags" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>test</title> </head> <body> <!-- <table> tag가 적용된 text 출력 --> <u:box>hello, world!</u:box> </body> </html>
<%@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" %> <!-- rtexprvalue="false" : Attribute value로 Scripting Elements나 EL 사용 금지 --> <%@attribute name="var" required="true" rtexprvalue="false" %> <!-- scope="NESTED" : default. 본체 내부에서만 변수 사용 가능. scope="AT_BEGIN" : default. 시작 Tag 다음 위치부터 변수 사용 가능. scope="NESTED" : default. 끝 Tag 다음 위치부터 변수 사용 가능. --> <%-- <%@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; %> <c:set var="result" value="<%=sum %>" />
<%@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" %> <!-- rtexprvalue="false" : Attribute value로 Scripting Elements나 EL 사용 금지 --> <%@attribute name="var" required="true" rtexprvalue="false" %> <!-- scope="NESTED" : default. 본체 내부에서만 변수 사용 가능. scope="AT_BEGIN" : default. 시작 Tag 다음 위치부터 변수 사용 가능. scope="NESTED" : default. 끝 Tag 다음 위치부터 변수 사용 가능. --> <%-- <%@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++) { %> <c:set var="result" value="<%= i %>" /> <jsp:doBody/> <% } %>
<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="u" tagdir="/WEB-INF/tags" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>test</title> </head> <body> <!-- Custom action의 body(본체) 밖에서 변수를 사용할 경우 --> <!-- 어떤 attribute를 넘겨주면 return값을 출력할 경우. --> <h1>a + b</h1> <!-- name-given을 사용할 경우 --> <%-- <u:sum num1="1" num2="10" /> 결과 : ${result} --%> <u:sum var="RESULT" num1="1" num2="10" /> 결과 : ${RESULT} <!-- Custom action의 body(본체) 안에서 변수를 사용할 경우 --> <h1>제곱</h1> <u:square var="num" start="5" end="10"> ${num}의 제곱은? ${num * num} <br> </u:square> </body> </html>
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("***********************<br>"); } }
<?xml version="1.0" encoding="UTF-8"?> <taglib xmlns="http://java.sun.com/xml/ns/j2ee" version="2.1"> <tlib-version>1.0</tlib-version> <short-name>tool</short-name> <tag> <name>starLine</name> <tag-class>tool.StarLineTag</tag-class> <body-content>empty</body-content> </tag> </taglib>
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <jsp-config> <taglib> <taglib-uri>tools.tld</taglib-uri> <taglib-location>/WEB-INF/tlds/tools.tld</taglib-location> </taglib> </jsp-config> </web-app>
<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="tool" uri="/WEB-INF/tlds/tools.tld" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>test</title> </head> <body> <tool:starLine /> </body> </html>
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("<font color=" + color + ">"); for(int i=0 ; i<size ; i++) out.print("*"); out.println("</font><br>"); } }
<?xml version="1.0" encoding="UTF-8"?> <taglib xmlns="http://java.sun.com/xml/ns/j2ee" version="2.1"> <tlib-version>1.0</tlib-version> <short-name>tool</short-name> <tag> <name>newLineTag</name> <tag-class>tool.NewLineTag</tag-class> <body-content>empty</body-content> <attribute> <name>size</name> <type>java.lang.Integer</type> </attribute> <attribute> <name>color</name> <type>java.lang.String</type> </attribute> </tag> </taglib>
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" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>test</title> </head> <body> <tool:newLineTag color="red" size="10" /> </body> </html>
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<String, Object> 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("<font color=" + color + ">"); for(int i=0 ; i<size ; i++) out.print("*"); out.println("</font><br>"); } }
<?xml version="1.0" encoding="UTF-8"?> <taglib xmlns="http://java.sun.com/xml/ns/j2ee" version="2.1"> <tlib-version>1.0</tlib-version> <short-name>tool</short-name> <tag> <name>newerLine</name> <tag-class>tool.NewerLineTag</tag-class> <body-content>empty</body-content> <dynamic-attributes>true</dynamic-attributes> </tag> </taglib>
<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="tool" uri="/WEB-INF/tlds/tools.tld" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>test</title> </head> <body> <!-- background, height 는 존재하지 않지만 Exception 발생하지 않음. --> <tool:newerLine color="red" size="10" background="black" height="10" /> </body> </html>
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("<table border=1 cellpadding=20><tr><td>"); body.invoke(out); out.println("</td></tr></table>"); } }
<?xml version="1.0" encoding="UTF-8"?> <taglib xmlns="http://java.sun.com/xml/ns/j2ee" version="2.1"> <tlib-version>1.0</tlib-version> <short-name>tool</short-name> <tag> <name>box</name> <tag-class>tool.BoxTag</tag-class> <body-content>scriptless</body-content> </tag> </taglib>
<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="tool" uri="/WEB-INF/tlds/tools.tld" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>test</title> </head> <body> <!-- table로 둘러 쌓인 hello, world! 출력 --> <tool:box>hello, world!</tool:box> </body> </html>
문자열 두 개를 attribute로 받아 치환하는 Scenario.
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); } }
<?xml version="1.0" encoding="UTF-8"?> <taglib xmlns="http://java.sun.com/xml/ns/j2ee" version="2.1"> <tlib-version>1.0</tlib-version> <short-name>tool</short-name> <tag> <name>replace</name> <tag-class>tool.ReplaceTag</tag-class> <body-content>scriptless</body-content> <attribute> <name>oldWord</name> <type>java.lang.String</type> </attribute> <attribute> <name>newWord</name> <type>java.lang.String</type> </attribute> </tag> </taglib>
<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="tool" uri="/WEB-INF/tlds/tools.tld" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>test</title> </head> <body> <!-- 철수가 민기로 치환 --> <tool:replace oldWord="철수" newWord="민기" > 철수는 영희에게 인사를 하였습니다.<br> 하지만 영희는 철수를 보지 못하고 지나쳤습니다.<br> </tool:replace> </body> </html>
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); } }
<?xml version="1.0" encoding="UTF-8"?> <taglib xmlns="http://java.sun.com/xml/ns/j2ee" version="2.1"> <tlib-version>1.0</tlib-version> <short-name>tool</short-name> <tag> <name>sum</name> <tag-class>tool.SumTag</tag-class> <body-content>empty</body-content> <attribute> <name>num1</name> <type>java.lang.Integer</type> <!-- RTimeEXPressionVALUE : Expression이나 EL식 포함 가능 여부 --> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <name>num2</name> <type>java.lang.Integer</type> <!-- RTimeEXPressionVALUE : Expression이나 EL식 포함 가능 여부 --> <rtexprvalue>true</rtexprvalue> </attribute> <variable> <name-given>result</name-given> <variable-class>java.lang.Integer</variable-class> <scope>AT_END</scope> </variable> </tag> </taglib>
<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="tool" uri="/WEB-INF/tlds/tools.tld" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>test</title> </head> <body> <!-- http://localhost:8080/Example2/result.jsp?NUM1=17&NUM2=33 --> <tool:sum num1="${param.NUM1}" num2="${param.NUM2}" /> 합 : ${result} </body> </html>
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); } }
<?xml version="1.0" encoding="UTF-8"?> <taglib xmlns="http://java.sun.com/xml/ns/j2ee" version="2.1"> <tlib-version>1.0</tlib-version> <short-name>tool</short-name> <tag> <name>sum</name> <tag-class>tool.SumTag</tag-class> <body-content>empty</body-content> <attribute> <name>num1</name> <type>java.lang.Integer</type> <!-- RTimeEXPressionVALUE : Expression이나 EL식 포함 가능 여부 --> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <name>num2</name> <type>java.lang.Integer</type> <!-- RTimeEXPressionVALUE : Expression이나 EL식 포함 가능 여부 --> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <name>var</name> <type>java.lang.String</type> <!-- 필수 기재 --> <required>true</required> <!-- RTimeEXPressionVALUE : Expression이나 EL식 포함 가능 여부 --> <rtexprvalue>false</rtexprvalue> </attribute> <variable> <name-from-attribute>var</name-from-attribute> <variable-class>java.lang.Integer</variable-class> <scope>AT_END</scope> </variable> </tag> </taglib>
<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="tool" uri="/WEB-INF/tlds/tools.tld" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>test</title> </head> <body> <!-- http://localhost:8080/Example2/result.jsp?NUM1=17&NUM2=33 --> <!-- var를 xxx라는 이름의 Attribute로 지정 --> <tool:sum var="xxx" num1="${param.NUM1}" num2="${param.NUM2}" /> 합 : ${xxx} </body> </html>
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(); /* ~ [본체 내용]<br> */ out.print("~ "); body.invoke(null); out.println("<br>"); } }
<?xml version="1.0" encoding="UTF-8"?> <taglib xmlns="http://java.sun.com/xml/ns/j2ee" version="2.1"> <tlib-version>1.0</tlib-version> <short-name>tool</short-name> <tag> <name>list</name> <tag-class>tool.ListTag</tag-class> <body-content>scriptless</body-content> </tag> <tag> <name>item</name> <tag-class>tool.ItemTag</tag-class> <body-content>scriptless</body-content> </tag> </taglib>
<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="tool" uri="/WEB-INF/tlds/tools.tld" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>test</title> </head> <body> <!-- ~ [본체 내용]<br> --> <tool:list> <tool:item>사과</tool:item> <tool:item>배</tool:item> <tool:item>딸기</tool:item> </tool:list> </body> </html>
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] [본체 내용]<br> */ char bullet = ((ListTag) parent).getBullet(); out.print(bullet + " "); body.invoke(null); out.println("<br>"); } }
<?xml version="1.0" encoding="UTF-8"?> <taglib xmlns="http://java.sun.com/xml/ns/j2ee" version="2.1"> <tlib-version>1.0</tlib-version> <short-name>tool</short-name> <tag> <name>list</name> <tag-class>tool.ListTag</tag-class> <body-content>scriptless</body-content> <attribute> <name>bullet</name> <type>java.lang.Charater</type> <required>true</required> </attribute> </tag> <tag> <name>item</name> <tag-class>tool.ItemTag</tag-class> <body-content>scriptless</body-content> </tag> </taglib>
<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="tool" uri="/WEB-INF/tlds/tools.tld" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>test</title> </head> <body> <!-- ★ [본체 내용]<br> --> <tool:list bullet="★"> <tool:item>사과</tool:item> <tool:item>배</tool:item> <tool:item>딸기</tool:item> </tool:list> </body> </html>
<?xml version="1.0" encoding="UTF-8"?> <taglib xmlns="http://java.sun.com/xml/ns/j2ee" version="2.1"> <tlib-version>1.0</tlib-version> <short-name>tool</short-name> <uri>/taglibs/tools.tld</uri> <tag> ... </tag> </taglib>
<?xml version="1.0" encoding="UTF-8"?> <taglib xmlns="http://java.sun.com/xml/ns/j2ee" version="2.1"> <tlib-version>1.0</tlib-version> <short-name>tool</short-name> <uri>/taglibs/util.tld</uri> <tag-file> <name>line</name> <path>/META-INF/tags/line.tag</path> </tag-file> </taglib>
new PoolableConnectionFactory(connFactory, objPool, null, null, false, true);
// Web Container에 등록 PoolingDriver driver = new PoolingDriver(); /* XML을 이용해서 생성하는 DBCP은 이름 앞에 자동으로 "/"가 붙기 때문에 일관성을 위해 "/"로 시작하는 것이 좋다! */ driver.registerPool(DB_POOL_NAME, objPool);
%>
<!DOCTYPE html><head>
<meta charset="UTF-8">
<title>DBCP 생성</title>
</head>
<body>
DBCP 생성 및 등록 성공!<br>
Pool name : <%=DB_POOL_NAME %>
</body>
</sxh>
<%@ 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"; %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Test DBCP</title> </head> <body> <% 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("연결 취득 완료<br>"); conn.close(); out.println("연결 반환 완료<br>"); %> </body> </html>
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); } %>
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <servlet> <servlet-name>auto-create-db-pool-jsp</servlet-name> <jsp-file>/AutoCreateDBPool.jsp</jsp-file> <load-on-startup>1</load-on-startup> </servlet> </web-app>
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"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>상품 정보</title> </head> <body> ${CODE} <br> ${TITLE} <br> ${WRITER} <br> ${PRICE} </body> </html>
Java Object Configuration Language
DBCP 생성에 필요한 객체 정보를 “[FILENAME].jocl”이란 XML 문서에 기술하여 사용. 이 때, DBCP명은 자동으로 [FILENAME]이 된다!
1. jocl 작성
<object class="org.apache.commons.dbcp.PoolableConnectionFactory" xmlns="http://apache.org/xml/xmlns/jakarta/commons/jocl"> <object class="org.apache.commons.dbcp.DriverManagerConnectionFactory"> <string value="jdbc:mysql://localhost:3306/webdb" /> <string value="root" /> <string value="root" /> </object> <object class="org.apache.commons.pool.impl.GenericObjectPool" /> <object class="org.apache.commons.pool.KeyedObjectPoolFactory" null="true" /> <string null="true" /> <boolean vlaue="false" /> <boolean value="true" /> </object>
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"; %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Test DBCP</title> </head> <body> <% 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("연결 취득 완료<br><br>"); out.println("현재 작동중인 DBCP<br>"); PoolingDriver driver = (PoolingDriver) DriverManager.getDriver("jdbc:apache:commons:dbcp:"); String[] names = driver.getPoolNames(); for(String name : names) out.println(name + "<br>"); out.println("<br>"); conn.close(); out.println("연결 반환 완료<br>"); %> </body> </html>