Java

[펌] JSTL Primer 정리

야이니 2008. 7. 2. 11:04

아래 내용을 정리 (2002년. JSP1.2 기준으로 작성된 글)
 
이 시리즈 기사에서는 EL과 core, fmt, xml, sql 태그 라이브러리에 대해 설명하고 있다.
마지막의 xml, sql 라이브러리는 MVC모델에서 Model측(business logic)의 기능에 가까우므로 제대로 된 대형 프로젝트에서는 사용하지 않도록 해야 겠다.
 
 
JSTL을 사용하는 이유는 JSP파일에서 모든 자바코드를 제거하는데 있다.
이는 자바코드 부분을 JSTL태그로 대체하여 유지보수를 용이하게 함에 있다.
 
 
 
 
[Expression Language(EL)]
 
JSTL의 EL 예제: ${...}
<c:out value="Hong Gildong"/> <1-- 정적 텍스트로 처리 -->
<c:out value="${user.firstName}"/> <!-- EL -->
<c:out value="Hello ${user.firstName} ${user.lastName}"/> <!-- 결합된 EL -->
Identifier: user
Accessor  : firstName, lastName:
Literal   : "Hello"
 
 

Identifier를 찾는 순서 (위의 예에서 user에 해당하는 부분)
    내장객체(EL Implicit Object)
Category Identifier Description
JSP pageContext The PageContext instance corresponding to the processing of the current page
Scopes pageScope A Map associating the names and values of page-scoped attributes
requestScope A Map associating the names and values of request-scoped attributes
sessionScope A Map associating the names and values of session-scoped attributes
applicationScope A Map associating the names and values of application-scoped attributes
Request parameters param A Map storing the primary values of the request parameters by name
paramValues A Map storing all values of the request parameters as String arrays
Request headers header A Map storing the primary values of the request headers by name
headerValues A Map storing all values of the request headers as String arrays
Cookies cookie A Map storing the cookies accompanying the request by name
Initialization parameters initParam A Map storing the context initialization parameters of the Web application by name
 
    범위변수(Scoped variables)
        내부적으로 pageContext의 findAttribute() 메소드를 사용하여 해당 ID를 검색
        page
        request
        session
        application

 
Accessors
객체의 속성(property)를 가져올 때는 dot(.)을 사용
   
    ${user.name} : 자바빈즈의 규칙을 따르므로 getFirstName()메소드가 제공되어야 함.
    ${user.addresss.city}
   
배열이나 컬렉션의 원소를 가져올 때는 []를 사용
   
    ${urls[3]}         : 배열, 순서화된 컬렉션(java.util.List와 같은)
    ${commands["dir"]} : java.util.Map
    ${url[3].protocol}

.과 []는 서로 interchangeable함.
   
    ${user["firstName"]} : user객체의 firstName속성값. 즉, ${user.firstName}의 결과와 동일
    ${commands.dir}      : commands맵의 dir키값. 즉, ${commands["dir"]}의 결과와 동일
   
 
연산자(Operators)
 
The EL operators
Category Operators
Arithmetic +, -, *, / (or div), % (or mod)
Relational == (or eq), != (or ne), < (or lt), > (or gt), <= (or le), >= (or ge)
Logical && (or and), || (or or), ! (or not)
Validation empty
 
${ item.price * (1 + taxRate[user.address.zipcode]) }
${ (x >= min) && (x <= max) }
${empty input} : null값, 컬렉션이나 배열의 원소가 없을때, String 길이가 0
 
연산자 우선순위
[], .
()
unary -, not, !, empty
*, /, div, %, mod
+, binary -
() <, >, <=, >=, lt, gt, le, ge
==, !=, eq, ne
&&, and
||, or
 
 
 
사용 예제)
page범위변수 user에 대해 값을 set/get하는 예제
 
[User.java]
package beans;

public class User {
    private String firstName;
    private String lastName;
   
    public String getFirstName() {
        return firstName;
    }
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
    public String getLastName() {
        return lastName;
    }
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
}
 
[index.jsp]
<html>
<body>
<c:out value="Hong Gildong"/><br/>

<jsp:useBean id="user" class="beans.User" scope="page"></jsp:useBean>
<jsp:setProperty name="user" property="firstName" value="Hong"/>
<jsp:setProperty name="user" property="lastName" value="Gildong"/>

<c:out value="${user.firstName}"/><br/>
<c:out value="Hello ${user.firstName} ${user.lastName}"/><br/>

</body>
</html>
 
[WEB-INF/web.xml]
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
   
    <display-name>DynamicWeb</display-name>
   
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
   
    <jsp-config>
        <jsp-property-group>
            <url-pattern>*.jsp</url-pattern>
            <el-ignored>false</el-ignored>
            <page-encoding>euc-kr</page-encoding>
            <scripting-invalid>false</scripting-invalid>
            <include-prelude>/header.jsp</include-prelude>
        </jsp-property-group>
    </jsp-config>  
   
</web-app>
 
[header.jsp]
<%@ page contentType="text/html;charset=EUC-KR" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %>
<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
 
 
 
 
[core 태그 라이브러리의 주요 태그들]
 
범위변수의 생성/초기화(set)
<c:set var="name" scope="page" value="Hong Gildong"/>
<c:out value="${name}"/><br/><br/>
<c:remove var="name" scope="page"/>
 
<c:set var="timezone" scope="session" value="CST"/>
<c:set var="squre" value="${param['x'] * param['x']}"/>

<c:set var="timezone" scope="session" value="CST"/>
이것은 아래와 같이 해도 동일하다.
<c:set var="timezone" scope="session">CST</c:set>
 

출력(out)
Syntax for the <c:out> action
<c:out value="expression" default="expression" escapeXml="boolean"/>
 
default:
 value가 null이거나 빈 문자열일 경우 대신 출력됨.
 사용자가 로그인하면 사용자명을, 로그인 전이면 Guest를 출력한다면 아래와 같이 할 수 있다.
 
 Hello <c:out value="${user.username}" default=="Guest"/>!
 
 
* <c:set>과 <c:out>의 조합
디폴트값으로 변수를 초기화할 때는 아래와 같은 방식을 사용할 수 있다.
timezone변수가 존재하지 않으면 쿠키가 생성될 때 같이 값이 설정된다.
 
<c:set var="timezone" scope="session">
 <c:out value="${cookie['tzPref'].value}" default="CST"/>
</c:set>
 
 
 
마지막으로 jsp스크립트를 사용한 아래의 예를 jstl EL코드로 변경한 예를 보였다.
 
JSP코드
<% if(user.getRole() == "member") { %>
    <p>Welcome, member!</p>
<% } else { %>
    <p>Welcome, guest!</p>
<% } %>

JSTL EL코드
<c:choose>
    <c:when test="${user.role == 'member'}">
        <p>Welcome, member!</p>
    </c:when>
    <c:otherwise>
        <p>Welcome, guest!</p>
    </c:otherwise>
</c:choose>
 
 
 
 
반복문(forEach, forTokens)
 
Syntax for numerical iteration through the <c:forEach> action

<c:forEach var="name" varStatus="name"
begin="expression" end="expression" step="expression">
body content
</c:forEach>
 

<c:forEach var="name" items="expression" varStatus="name"
begin="expression" end="expression" step="expression">
body content
</c:forEach>
 
Syntax for iterating through a string's tokens with the <c:forTokens> action

<c:forTokens var="name" items="expression"
delims="expression" varStatus="name"
begin="expression" end="expression" step="expression">
body content
</c:forTokens>
 
Collections supported by the items attribute of the <c:forEach> tag
Value for items Resulting item values
java.util.Collection Elements from call to iterator()
java.util.Map Instances of java.util.Map.Entry
java.util.Iterator Iterator elements
java.util.Enumeration Enumeration elements
Array of Object instances Array elements
Array of primitive values Wrapped array elements
Comma-delimited String Substrings
javax.servlet.jsp.jstl.sql.Result Rows from an SQL query
 
Properties of the LoopTagStatus object
Property Getter Description
current getCurrent() The item (from the collection) for the current round of iteration
index getIndex() The zero-based index for the current round of iteration
count getCount() The one-based count for the current round of iteration
first isFirst() Flag indicating whether the current round is the first pass through the iteration
last isLast() Flag indicating whether the current round is the last pass through the iteration
begin getBegin() The value of the begin attribute
end getEnd() The value of the end attribute
step getStep() The value of the step attribute
 
 
* 10사이의 짝수의 제곱을 구함
<c:forEach var="x" begin="0" end="10" step="2">
    <c:out value="${x} * ${x} = ${x*x}"/><br/>
</c:forEach>
 
* TP헤더를 출력(Map컬렉션)
<c:forEach var="x" items="${header}" varStatus="status">
    <c:out value="${status.count}. "/>
    <c:out value="${x}"/><br/>
</c:forEach>
 
* 콤마가 delimeter인 문자열 출력
<c:set var="fruits" value="banana,apple,tomato,melon"/>
<c:forEach var="x" items="${fruits}" varStatus="status">
    <c:out value="${x}"/><br/>
</c:forEach>
 
* delimiter가 콤마가 아니라면 forTokens를 사용
<c:set var="fruits" value="banana|apple|tomato|melon"/>
<c:forTokens var="x" items="${fruits}" varStatus="status" delims="|">
    <c:out value="${x}"/><br/>
</c:forTokens>
 
 
 
 
 
조건문(if, choose)
 
Syntax for the <c:if> conditional action

<c:if test="expression" var="name" scope="scope">
body content
</c:if>
 
Syntax for the <c:choose> action

<c:choose>
<c:when test="expression">
body content
</c:when>
...
<c:otherwise>
body content
</c:otherwise>
</c:choose>
 
<c:forEach var="x" items="${header}" varStatus="status">
    <c:if test="${status.first}">
        <c:out value="[HTTP Header]"/><br/>
    </c:if>
    <c:out value="${status.count}. "/>
    <c:out value="${x}"/><br/>
</c:forEach>

<c:choose>
    <c:when test="${pageContext.request.scheme eq 'http'}">
        This is an insecure Web session.
    </c:when>
    <c:when test="${pageContext.request.scheme eq 'https'}">
        This is an secure Web session.
    </c:when>
    <c:otherwise>
        You are using an unrecognized Web protocol. How did this happen?
    </c:otherwise>
</c:choose>
 
 
 
 
 
예외 처리(catch)
JSP페이지내에서 예외를 처리할 때.
태그내 'body content'에서 발생한 예외는 JSP에러 메카니즘에서 무시되고 var에 저장된다.
 
Syntax for the <c:catch> action

<c:catch var="name">
body content
</c:catch>
 
 
 
 
 
 
URL처리(url)
Syntax for the <c:url> action

<c:url value="expression" context="expression"
var="name" scope="scope">
<c:param name="expression" value="expression"/>
...
</c:url>

<a href="<c:url value='/content/sitemap.jsp'/>">View Sitemap</a>
<c:url value="/content/search.jsp">
    <c:param name="keyword" value="${searchTerm}}"/>
    <c:param name="month" value="02/2003"/>
</c:url>

var이 지정되면 화면에 출력하지 않고 이 변수에 내용이 저장됨

<c:url var="myURL" value="/content/search.jsp">
    <c:param name="keyword" value="${searchTerm}}"/>
    <c:param name="month" value="02/2003"/>
</c:url>
<c:out value="${myURL}"/>
 
 
 
 
 
 
컨텐트를 임포트(import)
 
Syntax for the <c:import> action

<c:import url="expression" context="expression"
charEncoding="expression" var="name" scope="scope">
<c:param name="expression" value="expression"/>
...
</c:import>
 
include directive : jsp페이지가 컴파일될때 포함됨
<jsp:include>     : jsp페이지가 호출될 포함됨
<c:import>        : jsp페이지가 호출될 포함됨. <jsp:include>의 확장판으로 외부의 리소스까지 include할 수 있다.
 

<c:catch var="exception">
    <pre>
        <c:import url="ftp://ftp.sayclub.co.kr/pub/Linux/fedora/linux/core/5/i386/os/README"/>
    </pre>
</c:catch>
<c:if test="${not empty exception}">
    Sorry, the remote content is not currently available.
</c:if>

var이 지정되면 화면에 출력하지 않고 이 변수에 내용이 저장됨
<c:import var="readme" url="ftp://ftp.sayclub.co.kr/pub/Linux/fedora/linux/core/5/i386/os/README"/>
<c:if test="${not empty readme}">
    <pre><c:out value="${readme}"/></pre>
</c:if>
   
 
 
 
 
요청을 리다이렉트(redirect)
javax.servlet.http.HttpServletResponse의 sendRedirect()메소드와 동일
 
Syntax for the <c:import> action

<c:import url="expression" context="expression"
charEncoding="expression" var="name" scope="scope">
<c:param name="expression" value="expression"/>
...
</c:import>

<c:catch var="exception">
    <c:import url="ftp://ftp.example.com/package/README"/>
</c:catch>
<c:if test="${not empty exception}">
    <c:redirect url="/errors/remote.jsp"/>
</c:if>

* forward, redirect의 차이
forward는 서버측에서 처리되고, redirect는 브라우저에서 처림됨
redirect는 유저의 브라우저에 변경된 주소가 표시되지만, forward는 표지되지 않는다.
forward가 좀 더 유용해 보이지만, 현재의 서블릿 컨텍스트내에서만 포워딩이 가능하다는 제한이 있다.
 
 
 
 
 
 
 
 
 
[fmt 태그 라이브러리의 주요 태그들]
 
Localization context tags(setLocale, setTimeZone, timeZone)
데이터 지역화(Localization)에 영향을 주는 요소: locale, timezone
데스크탑 자바 애플리케이션은 VM이 OS를 통해 디폴트 locale, timezone을 파악하지만,
서버측 자바 애플리케이션은 서버보다는 클라이언트측 정보에 의존해야 하므로 다음과 같은 순서로 locale,timezone을 결정한다.

1. JSP 설정변수
   
<fmt:setLocale value="expression" scope="scope" variant="expression"/>
 
    value: 로케일명 or java.util.Locale
        로케일명: ISO 언어코드+국가코드로 구성(국가코드는 옵션)
        언어코드 목록: ISO 639 specification (http://www.loc.gov/standards/iso639-2/englangn.html)
        국가코드 목록: ISO 3166 specification (http://userpage.chemie.fu-berlin.de/diverse/doc/ISO_3166.html)
        ex) ko_KR, en_US, fr_CA, ko, en, fr, ...
    scope: page, request, session, application
    variant: MAC, WIN,..
   
   
<fmt:setTimeZone value="expression" var="name" scope="scope"/>

    value: 타임존명 or java.util.TimeZone
    var: 인스턴스화된 timezone값이 var에 저장되고, 현재의 타임존은 변화 없음
   
    사용가능한 타임존명 파악
        String[] ids = java.util.TimeZone.getAvailableIDs();
        for(String id : ids)
            System.out.println(id);
   
    현재의 타임존 파악
    System.out.println(java.util.TimeZone.getDefault());
    // sun.util.calendar.ZoneInfo[id="Asia/Seoul",offset=32400000,dstSavings=0,useDaylight=false,transitions=14,lastRule=null]
   
<fmt:timeZone value="expression">
body content
</fmt:timeZone>

    setTimeZone과 같으나, body content내에서만 유효함. 
   
   
   
    예) default locale, timezone의 지정
    <fmt:setLocale value="ko_KR: scope="session"/>
    <fmt:setTimezone value="Asia/Seoul" scope="session"/>
   
 
2. HTTP프로토콜의 Accept-Language헤더값으로 locale 파악 (timezone 정보는 파악이 불가능)
accept-language=ko
accept-language=en,ko;q=0.5
* 이는 javax.servlet.ServletRequest클래스의 getLocale(), getLocales()를 통해서 자동으로 파악됨.

3. VM default locale (JSP컨테이너가 위치한 OS에서 파악)
 

 
 
 
Date tags(formatDate, parseDate)
 
<fmt:formatDate value="expression"
timeZone="expression"
type="field" dateStyle="style"
timeStyle="style"
pattern="expression"
var="name" scope="scope"/>
type: time, date, both
dateStyle, timeStyle: default, short, medium, long, full
pattern: dateStyle,timeStyle 대신 사용자가 지정
        java.text.SimpleDateFormat에 따른 패턴으로 지정. 예) MM/dd/yyyy
 
[User.java]
package beans;
import java.util.*;
public class User {
    private Date birth = new Date();
   
    public Date getBirth() {
        return birth;
    }
    ....
}
 
[index.html]
<jsp:useBean id="user" class="beans.User" scope="page"/>
<c:out value="${user.birth}"/><br/>
<fmt:formatDate value="${user.birth}"/><br/>
<fmt:formatDate value="${user.birth}" type="both"/><br/>
<fmt:formatDate value="${user.birth}" type="both" dateStyle="full" timeStyle="full" /><br/>
<fmt:formatDate value="${user.birth}" pattern="yyyy/MM/dd hh:mm:ss" /><br/>
 
결과:
Sun Aug 20 21:16:01 KST 2006
2006. 8. 20
2006. 8. 20 오후 9:16:01
2006년 8월 20일 일요일 오후 9시 16분 01초 KST
2006/08/20 09:16:01
 

<fmt:parseDate value="expression"
type="field" dateStyle="style" timeStyle="style"
pattern="expression"
timeZone="expression" parseLocale="expression"
var="name" scope="scope"/>

<fmt:parseDate
type="field" dateStyle="style" timeStyle="style"
pattern="expression"
timeZone="expression" parseLocale="expression"
var="name" scope="scope">
body content
</fmt:parseDate>
주어진 문자열을 java.util.Date형으로 변환.
사용할 이유 없음. 차라리 서블릿에서 처리하는 것이 적합
 
<c:set var="koDateString">06. 4. 1 오후 7:03</c:set>
<fmt:parseDate value="${koDateString}" parseLocale="ko_KR"
    type="both" dateStyle="short" timeStyle="short"
    var="koDate"/>
<c:set var="usDateString">4/1/06 7:03 PM</c:set>
<fmt:parseDate value="${usDateString}" parseLocale="en_US"
    type="both" dateStyle="short" timeStyle="short"
    var="usDate"/>
<c:set var="gbDateString">4/1/06 19:03</c:set>
<fmt:parseDate value="${gbDateString}" parseLocale="en_GB"
    type="both" dateStyle="short" timeStyle="short"
    var="gbDate"/>

<table border="1">
<tr>
    <th>Locale</th>
    <th>input</th>
    <th>output</th>
</tr>
<tr>
    <td>Korea Korean(ko_KR)</td>
    <td><c:out value="${koDateString}"/></td>
    <td><c:out value="${koDate}"/></td>
</tr>
<tr>
    <td>U.S. English(en_US)</td>
    <td><c:out value="${usDateString}"/></td>
    <td><c:out value="${usDate}"/></td>
</tr>
<tr>
    <td>British English(en_GB)</td>
    <td><c:out value="${gbDateString}"/></td>
    <td><c:out value="${gbDate}"/></td>
</tr>
 
결과:
Locale input output
Korea Korean(ko_KR) 06. 4. 1 오후 7:03 Sat Apr 01 19:03:00 KST 2006
U.S. English(en_US) 4/1/06 7:03 PM Sat Apr 01 19:03:00 KST 2006
British English(en_GB) 4/1/06 19:03 Wed Jan 04 19:03:00 KST 2006
 
 
 
Number tags(formatNumber, parseNumber)
숫자라는 차이외엔 formatDate, parseDate와 유사
 
<fmt:formatNumber value="expression"
type="type" pattern="expression"
currencyCode="expression" currencySymbol="expression"
maxIntegerDigits="expression" minIntegerDigits="expression"
maxFractionDigits="expression" minFractionDigits="expression"
groupingUsed="expression"
var="name" scope="scope"/>

type: number, currency, percentage
currentCode: type이 currency일때 유효. 통화기호를 ISO통화코드에서 정의한 코드로 지정
             통화코드 목록: ISO 4217 specification (http://www.xe.com/iso4217.htm)
             * 한국: KRW Korea (South), Won
currentSymbol: type이 currency일때 유효. 통화기호를 사용자가 지정
maxIntegerDigits,minIntegerDigits,maxFractionDigits,minFractionDigits: 정소, 소수 부분 자리수 지정
groupingUsed: boolean값. 자리수 표시 토글(default: true)

 
화폐 단위 예제
<fmt:setLocale value="ko_KR"/>
<fmt:formatNumber value="200000" type="currency"/>
 
결과:
₩200,000
 
 
 
<fmt:parseNumber value="expression"
type="type" pattern="expression"
parseLocale="expression"
integerOnly="expression"
var="name" scope="scope"/>

<fmt:parseNumber
type="type" pattern="expression"
parseLocale="expression"
integerOnly="expression"
var="name" scope="scope">
body content
</fmt:parseNumber>
주어진 문자열을 java.util.Number형으로 변환.
사용할 이유 없음. 차라리 서블릿에서 처리하는 것이 적합
 
 
 
 
 
Message tags(setBundle, bundle, message, param)
로케일과 연관된 리소스 번들에서 문자열 메시지를 가져옴
 
<fmt:setBundle basename="expression"
var="name" scope="scope"/>

<fmt:bundle basename="expression"
prefix="expression">
body content
</fmt:bundle>

<fmt:message key="expression" bundle="expression"
var="name" scope="scope"/>

<fmt:message key="expression" bundle="expression"
var="name" scope="scope">
<fmt:param value="expression"/>
...
</fmt:message>

setBundle이나 bundle(일시적으로 사용시)로 리소스 번들파일을 지정한 뒤,
message태그를 사용하여 메시지를 표시하거나 변수에 저장한다.
 
[a.txt]
test.Greeting.greeting=안녕하세요 {0}씨, JSTL 블로그에 오신걸 환영합니다.

[WEB-INFclassesGreeting_en.properties]
test.Greeting.greeting=Hello {0}, and welcome to the JSTL Blog.

[WEB-INFclassesGreeting_ko.properties] - a.txt에 대해 native2ascii를 수행한 결과
test.Greeting.greeting=uc548ub155ud558uc138uc694 {0}uc528, JSTL ube14ub85cuadf8uc5d0 uc624uc2e0uac78 ud658uc601ud569ub2c8ub2e4.
 
[index.jsp]
<fmt:bundle basename="Greeting">
<fmt:message key="test.Greeting.greeting">
<fmt:param value="홍길동"/>
</fmt:message>
</fmt:bundle>
[index.jsp] - prefix를 사용한 예제(출력은 위의 예제와 동일)
<fmt:bundle basename="Greeting" prefix="test.Greeting.">
<fmt:message key="greeting">
<fmt:param value="홍길동"/>
</fmt:message>
</fmt:bundle>
 
결과:
안녕하세요 홍길동씨, JSTL 블로그에 오신걸 환영합니다.
 
[index.jsp] - 영어로 출력 테스트
<fmt:setLocale value="en_US"/>
<fmt:bundle basename="Greeting" prefix="test.Greeting.">
<fmt:message key="greeting">
<fmt:param value="Hong Gildong"/>
</fmt:message>
</fmt:bundle>
 
결과:
Hello Hong Gildong, and welcome to the JSTL Blog.
 
 
 
[xml 태그 라이브러리의 주요 태그들] - parse, transform

<x:parse xml="expression" var="name" scope="scope"
filter="expression" systemId="expression"/>


<x:parse var="name" scope="scope"
filter="expression" systemId="expression">
body content
</x:parse>


<x:parse xml="expression" varDom="name" scopeDom="scope"
filter="expression" systemId="expression"/>


<x:parse varDom="name" scopeDom="scope"
filter="expression" systemId="expression">
body content
</x:parse>

Interaction of the <x:parse> and <c:import> actions

<c:import var="rssFeed" url="http://slashdot.org/slashdot.rdf"/>
<x:parse var="rss" xml="${rssFeed}"/>
 
 


<x:transform xml="expression" xslt="expression"
var="name" scope="scope"
xmlSystemId="expression" xsltSystemId="expression">
<x:param name="expression" value="expression"/>
...
</x:transform>


<x:transform xslt="expression"
var="name" scope="scope"
xmlSystemId="expression" xsltSystemId="expression">
body content
<x:param name="expression" value="expression"/>
...
</x:transform>

Syntax variations for the <x:transform> action when using the result attribute to supply a javax.xml.transform.Result instance

<x:transform xml="expression" xslt="expression"
result="expression"
xmlSystemId="expression" xsltSystemId="expression">
<x:param name="expression" value="expression"/>
...
</x:transform>

<x:transform xslt="expression"
result="expression"
xmlSystemId="expression" xsltSystemId="expression">
body content
<x:param name="expression" value="expression"/>
...
</x:transform>

core라이브러리의 태그와 유사한 태그들
<x:set>
<x:if>
<x:choose>, <x:when>, <x:otherwise>
<x:forEach>
 

[index.jsp]
<c:import var="rssFeed" url="http://slashdot.org/slashdot.rdf"/>
<c:import var="rssToHtml" url="/WEB-INF/xslt/rss2html.xsl"/>
<x:transform xml="${rssFeed}" xslt="${rssToHtml}"/>
 
[WEB-INF/xslt/rss2html.xsl]
<?xml version="1.0"?>
<xsl:stylesheet
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
  <a>
    <xsl:attribute name="href">
      <xsl:value-of select="//*[name()='channel']/*[name()='link']"/>
    </xsl:attribute>
    <xsl:value-of select="//*[name()='channel']/*[name()='title']"/>
  </a>
  <ul>
    <xsl:for-each select="//*[name()='item']">
      <li>
        <a>
          <xsl:attribute name="href">
            <xsl:value-of select="./*[name()='link']"/>
          </xsl:attribute>
          <xsl:value-of select="./*[name()='title']"/>
        </a>
      </li>
    </xsl:for-each>
  </ul>
</xsl:template>
</xsl:stylesheet>
 
결과:


<x:out>의 select에는 XPath표현식을 사용하면 된다고 했지만, 실제 테스트해보니
제대로 되지 않음. 파악하는데 시간낭비될 것 같아 다음에 알아볼 것임.
 
<x:out>테스트
<c:import var="rssFeed" url="http://slashdot.org/slashdot.rdf"/>
<x:parse var="rss" xml="${rssFeed}"/>
<x:out select="$rss//*[name()='channel']/*[name()='title'][1]" escapeXml="false"/>

위의 xls를 이용한 것과 동일한 결과를 출력한다는 코드
<c:import var="rssFeed" url="http://slashdot.org/slashdot.rdf"/>
<x:parse var="rss" xml="${rssFeed}"/>
<a href="<x:out select="$rss//*[name()='channel']/*[name()='link'][1]"/>"
  ><x:out select="$rss//*[name()='channel']/*[name()='title'][1]" escapeXml="false"/></a>
<ul>
<x:forEach select="$rss//*[name()='item']">
  <li> <a href="<x:out select="./*[name()='link']"/>"
        ><x:out select="./*[name()='title']" escapeXml="false"/></a>
</x:forEach>
</ul>
 
 
 
 
[sql 태그 라이브러리의 주요 태그들] setDataSource, query, update, transaction
Datasources - 데이터베이스 연결

<sql:setDataSource dataSource="expression"
var="name" scope="scope"/>

<sql:setDataSource url="expression" driver="expression"
user="expression" password="expression"
var="name" scope="scope"/>

dataSource: JNDI명
url: JDBC URL

위 2가지 형태중 아무거나 사용할 수 있으나, 막코딩(hard-coding)나 테스트 용도가 아니라면 대개 1번째 형태를 사용할 것이다.
하지만, 사실 위의 형태보다는 web.xml에 디폴트를 지정하는 것이 보다 일반적일 것이다. 아래와 같다.
 
Using a JNDI name to set JSTL's default datasource in the web.xml deployment descriptor

<context-param>
<param-name>javax.servlet.jsp.jstl.sql.dataSource</param-name>
<param-value>jdbc/blog</param-value>
</context-param>

 
 
SQL문에 따라, 데이터 변경이 필요하면 update태그를, 단순 조회용이면 query태그를 사용하면 된다.
 

<sql:query sql="expression" dataSource="expression"
var="name" scope="scope"
maxRows="expression" startRow="expression"/>

<sql:query sql="expression" dataSource="expression"
var="name" scope="scope"
maxRows="expression" startRow="expression">
<sql:param value="expression"/>
...
</sql:query>

<sql:query dataSource="expression"
var="name" scope="scope"
maxRows="expression" startRow="expression">
SQL statement
<sql:param value="expression"/>
...
</sql:query>
maxRows: 반환되는 행의 최대 개수
startRows: 처음에서 skip될 행 개수

쿼리의 실행결과(var에 저장됨)는 javax.servlet.jsp.jstl.sql.Result 인터페이스의 인스턴스로 범위변수(scoped variable)에 저장된다.
 
Properties defined by the javax.servlet.jsp.jstl.sql.Result interface
Property Description
rows An array of SortedMap objects, each of which maps column names to a single row in the result set
rowsByIndex An array of arrays, each corresponding to a single row in the result set
columnNames An array of strings naming the columns in the result set, in the same order as used for the rowsByIndex property
rowCount The total number of rows in the query result
limitedByMaxRows True if the query was limited by the value of the maxRows attribute
 
Using <sql:query> to query a database, and using <c:forEach> to iterate through the result set

<sql:setDataSource var="dataSrc" 
    url="jdbc:oracle:thin:@localhost:1521:ORCL" driver="oracle.jdbc.OracleDriver"
    user="scott" password="tiger"/>
<sql:query var="queryResults" dataSource="${dataSrc}">
    select * from emp where rownum < ?
    <sql:param value="${6}"/>
</sql:query>
<table border="1">
<tr>
    <th>EMPNO</th>
    <th>ENAME</th>
    <th>JOB</th>
    <th>MGR</th>
    <th>HIREDATE</th>
    <th>SAL</th>
    <th>COMM</th>
    <th>DEPTNO</th>
</tr>
<c:forEach var="row" items="${queryResults.rows}">
<tr>
    <td><c:out value="${row.empno}"/></td>
    <td><c:out value="${row.ename}"/></td>
    <td><c:out value="${row.job}"/></td>
    <td><c:out value="${row.mgr}"/></td>
    <td><c:out value="${row.hiredate}"/></td>
    <td><c:out value="${row.sal}"/></td>
    <td><c:out value="${row.comm}"/></td>
    <td><c:out value="${row.deptno}"/></td>
</tr>
</c:forEach>

결과:
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
7369 SMITH CLERK 7902 1980-12-17 800 20
7499 ALLEN SALESMAN 7698 1981-02-20 1600 300 30
7521 WARD SALESMAN 7698 1981-02-22 1250 500 30
7566 JONES MANAGER 7839 1981-04-02 2975 20
7654 MARTIN SALESMAN 7698 1981-09-28 1250 1400 30
 
패러미터가 날짜/시간의 값을 가진다면, param태그 대신 datePram태그를 사용한다.

<sql:dateParam value="expression" type="type"/>
value: java.util.Date
type: date | time | timestamp

<sql:update sql="expression" dataSource="expression"
var="name" scope="scope"/>

<sql:update sql="expression" dataSource="expression"
var="name" scope="scope">
<sql:param value="expression"/>
...
</sql:update>

<sql:update dataSource="expression"
var="name" scope="scope">
SQL statement
<sql:param value="expression"/>
...
</sql:update>

var이 지정되면, java.lang.Integer형으로 저장되며, 갱신된 행의 개수를 나타낸다.
 
 
 

<sql:transaction dataSource="expression" isolation="isolationLevel">
<sql:query .../> or  <sql:update .../>
...
dataSource: 지정하지 않으면, JSTL 디폴트 데이터소스를 사용
isolation: read_committed, read_uncommitted, repeatable_read, serializable
transaction내에 내포된 query, update태그는 transaction태그의 데이터소스를 사용하므로, dataSources속성값은 의미가 없다.
 
Using <sql:transaction> to combine database updates into a transaction

<html>
<body>
<sql:setDataSource var="dataSrc" 
    url="jdbc:oracle:thin:@localhost:1521:ORCL" driver="oracle.jdbc.OracleDriver"
    user="scott" password="tiger"/>
<sql:transaction dataSource="${dataSrc}">
    <sql:update sql="insert into dept(deptno, dname, loc) values(?,?,?)">
        <sql:param value="50"/>
        <sql:param value="DEVS"/>
        <sql:param value="SEOUL"/>
    </sql:update>
    <sql:update sql="update dept set LOC=? where deptno=?">
        <sql:param value="BUSAN"/>
        <sql:param value="50"/>
    </sql:update>
</sql:transaction>
</body>
</html>

 
위와 같이 데이터소스를 명시적으로 지정하기 보다는 디폴트 데이터소스를 사용하는 것이 보다 일반적일 것이다.
그러면 JSP페이지에서는 데이터소스를 명시적으로 지정할 필요없이 query나 update태그를 바로 사용할 수 있다.
 
[WEB-INF/web.xml]
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
    xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
   
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
   
    <jsp-config>
        <jsp-property-group>
            <url-pattern>*.jsp</url-pattern>
            <el-ignored>false</el-ignored>
            <page-encoding>euc-kr</page-encoding>
            <scripting-invalid>false</scripting-invalid>
            <include-prelude>/header.jsp</include-prelude>
        </jsp-property-group>
    </jsp-config>
   
    <context-param>
        <param-name>javax.servlet.jsp.jstl.sql.dataSource</param-name>
        <param-value>jdbc/OracleDB</param-value>
    </context-param>
</web-app>

[META-INF/context.xml] - 톰캣 JNDI 설정
<?xml version="1.0" encoding="euc-kr" ?>
<Context>
    <Resource
        name="jdbc/OracleDB" auth="Container" type="javax.sql.DataSource"
        username="scott" password="tiger"
        driverClassName="oracle.jdbc.OracleDriver"
        url="jdbc:oracle:thin:@localhost:1521:ORCL"/>
</Context>

[index.html]
<html>
<body>
<sql:transaction>
    <sql:update sql="insert into dept(deptno, dname, loc) values(?,?,?)">
        <sql:param value="50"/>
        <sql:param value="DEVS"/>
        <sql:param value="SEOUL"/>
    </sql:update>
    <sql:update sql="update dept set LOC=? where deptno=?">
        <sql:param value="BUSAN"/>
        <sql:param value="50"/>
    </sql:update>
</sql:transaction>
</body>
</html>
 
 
[functions 태그 라이브러리의 주요 태그들]
[index.jsp]
<html>
<body>
<c:set var="name" value="Welcome to 한국  "/>
<c:set var="name" value="${fn:trim(name)}"/><br/>
<c:out value="name: ${name}"/><br/><br/>
<c:out value="length(name): ${fn:length(name)}"/><br/>
<c:out value="toUpperCase(name): ${fn:toUpperCase(name)}"/><br/>
<c:out value="toLowerCase(name): ${fn:toLowerCase(name)}"/><br/>
<c:out value="substring(name,3,7): ${fn:substring(name,3,7)}"/><br/>
<c:out value="substringBefore(name,'come'): ${fn:substringBefore(name, 'come')}"/><br/>
<c:out value="substringAfter(name,'Welcome'): ${fn:substringAfter(name, 'Welcome')}"/><br/>
<c:out value="replace(name, '한국', 'Korea'): ${fn:replace(name, '한국', 'Korea')}"/><br/>
<c:out value="indexOf(name, 'to'): ${fn:indexOf(name,'to')}"/><br/>
<c:out value="contains(name, 'welcome'): ${fn:contains(name, 'welcome')}"/><br/>
<c:out value="containsIgnoreCase(name, 'welcome'): ${fn:containsIgnoreCase(name, 'welcome')}"/><br/>
<c:out value="startsWith(name, 'Welcome'): ${fn:startsWith(name, 'Welcome')}"/><br/>
<c:out value="endsWith(name, '한국'): ${fn:endsWith(name, '한국')}"/><br/>
<c:remove var="name"/>
 
<c:out value="---------------------------------"/><br/>
<c:set var="fruits" value="사과,배,참외,수박,복숭아"/>
<c:set var="fruits_arr" value="${fn:split(fruits,',')}"/>
<c:forEach var="x" items="${fruits_arr}">
    <c:out value="${x}"/><br/>
</c:forEach>
<c:out value="${fn:join(fruits_arr, ',')}"/><br/>
</body>
</html>
 
결과:

name: Welcome to 한국

length(name): 13
toUpperCase(name): WELCOME TO 한국
toLowerCase(name): welcome to 한국
substring(name,3,7): come
substringBefore(name,'come'): Wel
substringAfter(name,'Welcome'): to 한국
replace(name, '한국', 'Korea'): Welcome to Korea
indexOf(name, 'to'): 8
contains(name, 'welcome'): false
containsIgnoreCase(name, 'welcome'): true
startsWith(name, 'Welcome'): true
endsWith(name, '한국'): true
---------------------------------
사과

참외
수박
복숭아
사과,배,참외,수박,복숭아

출처] http://blog.empas.com/phpaspjsp/15273431