[jsp] jstl 설명

프로그래밍/Web 2010. 1. 8. 14:00 Posted by galad
출처: http://greatbeat.tistory.com/tag/JSTL

1           JSTL 개요

1.1          JSTL 이란

커스텀태그를 공부하면서 jsp페이지에서 자바코드를 추출하는데 탁월한 성능을 발휘하는 모습을 보았다. 허나 이것을 만든다고 생각하면, 아직도 좀 아찔한 감이 남아있다. 개발시간은 촉박한데, 로직 부분을 빼낸다고, tld 만들고, 태그핸들러 만들고, 컴파일하고, 잘 동작하는지 테스트해보고 하려면 사실 시간이 더 많이 소요되기 때문에 망설여지는 것이 사실이다.

하지만 커스텀태그 소개하면서 계속 얘기했던 것은 자주 쓰이는 커스텀태그들을 표준으로 정해서 모아놓은 것이 있으니까, 이것들만 잘 찾아서 쓰면 된다고 얘기했다. 정말 알짜들만 모아놓았다. 최정예 커스텀태그들을 모아서 이름을 붙여준 것이 JSP Stadard Tag Library 이고, 줄여서 JSTL 이라고 부른다. JCP(http://www.jcp.org )에서 표준을 제정했다. JSR-52 에서 각계의 전문가들이 심사 후에 알짜들을 모아놓은 것이다.

 

1.2          JSTL 현황

집필하는 현재 JSTL JSP2.0 스펙에 포함되었다. 따라서 JSP2.0 의 표준을 제일 먼저 구현해서 참고를 삼는 톰캣5.0 이 정식으로 발표된다면, 별다른 설치를 하지 않고 바로 JSTL을 사용할 수 있게 된다. (이미 발표된 톰캣5.0 알파버전에는 JSTL의 기능은 빠져 있다. EL 과 심플 커스텀태그와 태그파일의 기능은 들어가 있고, JSTL JSF는 빠져있다.)

JSTL EL 을 이용해서 객체의 접근을 쉽게 할 수 있다. jsp 에서 객체의 접근은 먼저 선언부터 되어야 되지만, EL에서는 별다른 선언없이도 객체를 받아서 처리할 수 있게 되었다. 이에 관해서는 후에 예제를 통해서 살펴보겠다.

JSTL 에 관련된 최신 정보는 sun jstl 홈페이지 http://java.sun.com/products/jsp/jstl 와 자카르타 프로젝트의 taglibs http://jakarta.apache.org/taglibs 를 통해서 얻을 수 있다.

 

1.3          JSTL 처리영역

JSTL은 태생이 커스텀태그이기 때문에 jsp와 밀접하게 관계가 있다. application, session, request, response, pageContext 등의 내장객체에 쉽게 접근하며, 그 외에도 파라메터, 헤더, 쿠키 등을 복잡한 코드를 사용하지않고, 쉽게 직관적으로 사용할 수 있다. 또한 기본적인 연산이나 객체의 비교 등을 .equals() 메소드 등을 이용하는 대신 == 와 같이 쉽게 구현했으며, 조건, 반복, 이동에 대한 태그를 지원하기 때문에 태그만으로도 반복 기능을 구현할 수 있다.

JSTL 의 처리영역은 크게 4가지로 나누어진다. core, format, xml, sql 로 기능이 구분되고, 각각의 기능은 이름이 말해 주듯, 기본기능, 형식화, xml처리, sql처리를 담당한다.

기능

prefix

기본URI

기본기능

c

http://java.sun.com/jstl/core

XML 처리

x

http://java.sun.com/jstl/xml

i18n & 형식화

fmt

http://java.sun.com/jstl/fmt

데이터베이스 작업

sql

http://java.sun.com/jstl/sql

 

2           JSTL 설치

2.1          JSTL 다운로드

JSTL JSP2.0 표준 스펙에 포함이 되었지만 아직 이 스펙을 지원하는 제품이 나오지 않은 상태이기 때문에 기존의 톰캣4에서 사용할 수 있게 설치하는 법을 알아보려고 한다.

이 책의 논외가 되겠지만 sun에서 나온 JWSDP(Java Web Services Developer Pack)에는 톰캣4.1.2 JSTL v1.0.3 이 기본으로 들어있기 때문에 이것만 설치하면 쉽게 JSTL을 사용할 수 있다. 이에 관한 사용법은 다음 주소를 참고하기 바란다. http://java.sun.com/webservices/docs/1.1/tutorial/doc/index.html 

jstl의 기본 설명도 충실하게 잘 나와있고, 웹서비스에 관련된 좋은 안내서이기에 꼭 읽어보기 바란다.

JSTL은 현재 자카르타의 taglibs 서브 프로젝트에서 받아올 수 있다.  http://jakarta.apache.org/taglibs 에 접속하고, Downloads 링크를 클릭한다. Release 버전과 Nightly Build 버전이 있는데, 정식 릴리스 버전은 현재 1.0.3 까지 나와있다.

http://www.apache.org/dist/jakarta/taglibs/standard/ 에 가면 바이너리 빌드를 받아 볼 수 있다. jakarta-taglibs-standard-current.zip 를 다운로드 받아서 적당한 위치에 압축을 푼다.

 

2.2          JSTL 예제 설치

jakarta-taglibs 디렉토리 아래 standard 에서 standard-examples.war 파일을 jstl.war 파일로 이름을 바꾼 뒤에 Tomcat 4 가 설치된 디렉토리의 webapps 디렉토리에 복사한다.

server.xml <Host> unpackWARs="true" 로 설정되어 있다면, jstl 이라는 디렉토리가 자동으로 생기면서 jstl.war 의 압축이 풀린 뒤에 브라우저에서 http://localhost:포트/jstl 로 예제 웹 어플리케이션을 실행해 볼 수 있다.

 

2.3          JSTL add-on 설치

기존의 컨텍스트에서 JSTL을 사용하기 위해서는 웹 어플리케이션의 WEB-INF/lib 디렉토리에 필요한 라이브러리를 복사하면 된다. JSTL 의 주된 라이브러리 파일은 jstl.jar, standard.jar 이고, xml에서 지원되는 기능을 사용하기 위해서 jaxen-full.jar, saxpath.jar,  jaxp-api.jar 파일 등이 필요하다. 이 파일들을 웹어플리케이션의 WEB-INF/lib 에 복사하고, 컨텍스트를 리로드한다. 구체적인 파일들의 명세는 다음과 같다.

이름

설명

파일

JSTL 1.0 API 클래스

jstl 1.0 API 클래스

jstl.jar

JSTL 1.0 구현 클래스

JSTL 구현

standard.jar

Jaxen 1.0

Xpath 엔진

jaxen-full.jar

Saxpath 1.0

Xpath 파싱에 필요 sax 방식

saxpath.jar

Jdbc 2.0 선택 패키지

JDBC 구현 클래스
j2se1.4,
톰캣4 기본포함

jdbc2_0-stdext.jar

Jaxp 1.2 구현

jaxp 1.2 호환 파서 필요

jaxp-api.jar
dom.jar
sax.jar
xercesImpl.jar

Xalan

아파치 xslt 변환기

xalan.jar

만일 톰캣4 ROOT 컨텍스트에 설치를 한 경우에는 webapps/ROOT/WEB-INF/ 아래에 lib 디렉토리를 만들고 jstl 의 필요한 JAR 파일들을 복사해 놓으면 된다.

 

2.4          JSTL tld 파일

tld파일이 없거나, web.xml 파일에 8개의 tld 파일을 등록하지 않아도 표준태그는 사용할 수 있도록 되어 있다.

4가지의 JSTL 태그마다 EL 기반과 RT 기반의 태그로 나눠진다. 태그핸들러의 종류는 똑같지만 차이가 있다면 value 값으로 EL 을 사용하느냐 아니면 스크립트의 표현식을 허용하느냐의 차이다. 이에 관해서는 후에 살펴보겠다.

서버에 따라서 필요한 경우가 있으므로 간략히 방법을 설명하면, jakarta-taglibs standard 디렉토리에 있는 tld 디렉토리의 8개의 tld 파일을 웹 어플리케이션의 WEB-INF/ 아래에 적당한 위치에 복사한 뒤에 이 파일들의 위치를 web.xml 에 등록한다.

 

3           표현언어 EL (Expression Language)

EL은 다양한 위치에 있는 데이터에 접근하기 위한 언어이다. 문법체계가 직관적으로 아주 쉽다. jsp 에서는 모든 변수의 생성과 선언을 반드시 표시를 해주어야 되지만 EL은 그 과정 없이 바로 접근이 가능하다.

 

3.1          EL 표시형식

EL임을 표시하는 형식은 ${} 이다. 이 안에 들어있는 것은 EL 로 처리된다. 내장객체의 접근이 가능하고, 산술연산과 비교연산이 가능하다.

자바스크립트와 비슷한 방법으로 객체 내부의 자원에 접근이 가능하다. dot(.) bracket([]) 모두를 이용해서 접근할 수 있으며, 예를 들면

${header.cookie} ${header['cookie']} 는 같은 결과 값을 얻을 수 있다. 만일 user-agent 처럼 - 와 같이 있을 경우는 ${header['user-agent']} 로 접근하는 것이 좋다.

[] 를 이용해서 객체에 접근할 경우에 index 를 대신해서 사용할 수도 있다.

다음 예제는 이전 내용을 요약한 것이다.

예제 1.   jstlel01.jsp

<% response.setContentType("text/html;"); %>

<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>

<h3>header</h3>

<c:forEach items="${header}" var="h">

  <c:out value="${h}"/><br/>

</c:forEach>

<h3>header.cookie</h3>

<c:out value="${header.cookie}"/><br/>

<c:out value='${header["cookie"]}'/>

 

 

header 라는 객체가 갖고 있는 값들을 불러서 보여주는 소스이다. request.getHeader() 로 가져올 수 있는 것인데, 훨씬 깔끔한 소스로 보여진다.

JSTL 태그에서 기본적으로 EL을 사용한다. var 속성은 변수를 지정하는데, 여기에는 문자열 상수로 지정되며, 이 후에 이 변수를 참조하기 위해서는 EL 을 사용한다.

 

3.2          EL 내장객체

EL 로 접근할 수 있는 내장 객체들은 다음과 같다.

pageScope

page scope 의 변수들

requestScope

request scope 의 변수들

sessionScope

session scope 의 변수들

applicationScope

application scope 의 변수들

param

parameter 변수들 문자열

paramValues

parameter 변수들 문자열 배열

header

HTTP request 헤더

headerValues

HTTP request 헤더 문자열 배열

initParam

컨텍스트 초기 변수 web.xml 에서 지정

cookie

쿠키 변수들

pageContext

현재 페이지의 pageContext 객체

 

pageScope 의 변수는 스크립틀릿의 변수와는 틀리며, 이를 이용하려면 조금은 번잡한 과정을 거치게 된다. 따라서 가능하면 스크립틀릿은 사용하지 않기를 권장한다. 이를 활용하는 소스이다.

예제 2.   jstlel02.jsp

<% response.setContentType("text/html;"); %>

<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>

<%@ taglib prefix="c_rt" uri="http://java.sun.com/jstl/core_rt" %>

<% String[] abc = {"빨강","파랑","노랑"}; %>

 

<c:set var="t" value="hello"/>

<c_rt:set var="color" value="<%=abc%>"/>

 

<h3>pageScope</h3>

<c:forEach items="${pageScope}" var="h">

    <c:out value="${h}"/><br/>

</c:forEach>

 

<h3>colors</h3>

<c:forEach items="${color}" varStatus="i">

    <c:out value="${i.count}"/>.

    <c:out value="${color[i.index]}"/><br/>

</c:forEach>

 

 

<c:forEach/> 를 통해서 pageScope 의 값을 모두 출력해보면, String 배열변수인 abc 는 접근할 수 없게 되어있다. <c:set/> <c_rt:set/> 으로 정해놓은 t color 만 나타나는 것이 보인다.

color 의 값을 출력하는 코드를 보면 color 의 인덱스를 이용해 배열 내용을 뽑아 왔다. varStatus 대신 var 변수를 통해서 바로 내용을 출력할 수도 있다.

 

value 가 들어가는 자리에 표현식을 쓰기 위해서는 RT 기반의 태그를 사용해야 된다. 만일 <c_rt:set var="color" value="<%=abc%>"/> 에서 <c_rt:set/> 대신 <c:set/> 를 사용하면 color 가 갖게 되는 값은 "<%=abc%>" 문자열이 되어버린다.

 

3.3          EL 연산자

null 인지 아닌지 판단하기 위해서는 empty 라는 키워드를 사용한다. 세션 값이 없으면 세션에 값을 저장하고, 있을 경우 하나를 더한 후에 출력하는 코드이다

예제 3.   jstlel03.jsp

<% response.setContentType("text/html;"); %>

<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>

<c:if test="${!empty hit}">

    <c:set var="hit" value="${hit+1}" scope="session"/>

    <c:out value="${hit}"/> 번 리로드되었습니다.

</c:if>

<c:if test="${empty hit}">

    <c:set var="hit" value="1" scope="session"/>

    세션에 값을 저장했습니다.

</c:if>

<br>

<a href="jstlel03.jsp">reload</a>

 

 

EL 의 장점은 객체의 접근이 쉽다고 했다. ${empty 객체} 를 통해서, 객체의 null 을 확인할 수 있다. ${!empty hit} ${!empty sessionScope.hit} 로 대치해도 같은 결과가 나온다.

EL 의 연산자는 관계연산자, 산술연산자, 논리연산자, empty 연산자가 있고 다음 표와 같다.

연산자 구분

연산자

관계

< lt > gt <= le >= ge == eq != ne

산술

+ - * / div % mod

논리

&& and || or ! not

Empty

empty

 

연산자들간의 우선순위는 다음과 같다.

1. [] .

2. ()

3. - (단항) not ! empty

4. * / div % mod

5. + - (이항)

6. < > <= >= lt gt le ge

7. == != eq ne

8. && and

9. || or

 

4           JSTL Core

core 태그를 사용하기 위해서 페이지 상단에 다음과 같이 선언되어야 된다.

<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c"%>

가장 빈번하고 자주 쓰이는 것이다. Core 의 태그들은 다음과 같이 정리된다.

기능

태그

prefix

EL 지원

catch , out , remove , set

c

흐름 제어

choose (when , otherwise) , forEach , forTokens , if

URL 관리

Import (param) , redirect (param) , url (param)

 

4.1          <c:out/>

가장 많이 쓰게 되는 것은 JSP 의 표현식을 대체하는 <c:out/> 이다. 다음과 같은 형식을 갖고 있다.

body 없는 경우

<c:out value="value" [escapeXml="{true|false}"] [default="기본값"] />

 

body 있는 경우

<c:out value="value" [escapeXml="{true|false}"] />

기본값

</c:out>

 

 

[] 으로 둘러 쌓인 부분은 생략 가능한 부분이다. value default 값은 일반 문자열이나 EL 이 들어간다. value 안에 JSP의 표현식을 사용하려 한다면 RT 기반의 <c_rt:out> 을 사용해야 된다는 것은 이전 예제에서 살펴 보았다.

escapeXml 속성은 값 중에 포함된 < > & ' " 문자들을 각각 &lt; &gt; &amp; &#039; &#034; 로 출력한다. 생략될 경우 true 가 기본 값이다.

null 값의 처리에 대해서 JSP expression 의 경우는 "null" 문자열로 출력이 되었던 것을 jstl의 스펙에서는 이 경우 빈 문자열("")또는 기본값으로 처리한다고 명시되어있다.

 

4.2          <c:set/>, <c:remove/>

<c:set/> 의 기본형식은 다음과 같다. scope 속성이 생략될 경우 기본값은 page 이다.

Syntax 1: scope 에 해당하는 변수에 속성 값을 정한다.

<c:set value="value"

var="varName" [scope="{page|request|session|application}"]/>

 

Syntax 2: scope 에 해당하는 변수에 body 값을 정한다.

<c:set var="varName" [scope="{page|request|session|application}"]>

body content

</c:set>

 

Syntax 3: 속성 값으로 target 객체의 프로퍼티 값을 정한다.

<c:set value="value"

target="target" property="propertyName"/>

 

Syntax 4: body 값으로 target 객체의 프로퍼티 값을 정한다.

<c:set target="target" property="propertyName">

body content

</c:set>

 

변수에 값을 할당한다. 빈과 같은 객체에 할당하기 위해서는 target property속성을 이용한다.

 

<c:remove/> JSP removeAttribute() 와 같은 역할을 한다. 해당 scope 에 있는 변수를 제거하는 역할을 한다.

 

4.3          <c:catch/>

<c:catch/> body 위치에서 실행되는 코드의 예외를 잡아내는 역할을 담당한다. var 속성을 지정해서 변수를 선언하면 그 변수에 예외의 내용이 들어가게 된다.

 

다음 예제는 이상의 태그를 사용한 예제이다.

예제 4.   jstlcore01.jsp

<% response.setContentType("text/html"); %>

<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>

<h3>코어 </h3>

<h4>&lt;c:out></h4>

<pre>

${1+2} <c:out value="${1+2}"/>

${1>3} <c:out value="${1>3}"/>

${1 gt 3} <c:out value="${1 gt 3}"/>

 

${ 표시 <c:out value="${'${'}test}"/>

 

escapeXml 속성; 기본값은 false

false: <c:out value="<b>bold</b> <,>,&,',\" " escapeXml="false"/>

true:  <c:out value="<b>bold</b> <,>,&,',\" " escapeXml="true"/>

 

" 큰따옴표 사용주의; ' 작은따옴표로 대치

&lt;c:out value='&lt;font color="blue">파랑&lt;/font>'/>

<c:out value='<font color="blue">파랑</font>' escapeXml="false"/>

 

<hr><h4>&lt;c:set></h4>

set session scope var "name": <c:set var="name" value="하늘" scope="session"/>

c:out name: <c:out value="${name}"/>

expression name: <%= session.getAttribute("name")%>

 

set page scope var "name": <c:set var="name">

  hello

</c:set>

c:out name: <c:out value="${pageScope.name}"/>

c:out sessionScope.name: <c:out value="${sessionScope.name}"/>

expression name: <%= session.getAttribute("name")%>

 

<hr><h4>&lt;c:remove></h4>

remove session scope var "name": <c:remove var="name" scope="session"/>

expression name: <%= session.getAttribute("name")%>

c:out sessionScope.name: <c:out value="${sessionScope.name}"/>

 

<hr><h4>&lt;c:catch></h4>

<c:catch var="errmsg">

line1

<%=1/0 %>

line2

</c:catch>

<c:out value="${errmsg}"/>

</pre>

 

 

value 속성에 들어가는 값은 문자열과 EL 이다. EL의 경우 ${} 안에서 나온 결과값을 표시한다. 부등호 > gt 는 같은 뜻이다. "${" 를 표시하기 위해서는 EL 로 감싸야 된다. ${'${'} 로 해야 표시된다.

escapeXml 속성은 브라우저에서 특수한 기능을 하는 문자 표시 여부를 결정한다. false 값일 경우는 태그가 먹힌 굵은 글씨의 bold 가 나오고, true 일 경우는 '<' '>'를 각각 '&lt;','&gt;' 로 변환한다. 결과는 <b>bold</b> , 브라우저에서 태그가 보이도록 나온다.

큰따옴표와 작은따옴표는 바꿔서 쓸 수 있다. 대신 짝이 맞아야 된다. 또한 하나로 다 이어서 쓸 경우 변환과정에서 에러가 나기 때문에 주의해야된다.

따옴표 사용 예

외부

문자열내부

사용

<c:out value='<font color="blue">파랑</font>' />

작은

가능

<c:out value="<font color='blue'>파랑</font>" />

작은

가능

<c:out value="<font color="blue">파랑</font>" />

불가

session 스코프에 name 이라는 key "하늘"을 넣는다. <c:out value="${name}"/> 으로 scope 를 지정하지 않아도 내장 객체를 훑어서 sessionScope에서 걸리는 "name"키를 찾아서 출력한다. 이 값은 스크립틀릿에서도 참고할 수 있다.

page 스코프에 같은 key "hello" 라는 값을 넣으면 <c:out value="${name}"/> 은 더 이상 session 에 있는 값을 가져오지 않는다.

<c:remove/> 를 통해서 scope 속성에 지정된 key 값을 제거한다.

 

예제에서 <c:catch/> 태그는 body 실행 도중에 <%=1/0 %> 에서 예외가 발생한 것을 errmsg 라는 변수에 넣는다. 이 후에 <c:out/> 을 통해서 에러 메시지를 표시한다.

 

4.4          <c:if/>

<c:if/> 는 흔히 보는 조건문이다. 형식은 다음과 같다.

Syntax 1: Body 없는 경우

<c:if test="testCondition"

var="varName" [scope="{page|request|session|application}"]/>

 

Syntax 2: Body 있는 경우

<c:if test="testCondition"

[var="varName"] [scope="{page|request|session|application}"]>

body content

</c:if>

 

 

<c:if/> 에서 나온 결과를 varName 변수에 넣고, 나중에 활용이 가능하다. 변수의 scope는 임의로 지정할 수 있고, 생략될 경우 기본값은 page 이다.

 

4.5          <c:choose/>, <c:when/>, <c:otherwise/>

<c:choose/> 태그는 java switch 문과 같지만, 조건에 문자열 비교도 가능하고 쓰임의 범위가 넓다. 또한 <c:if/> 태그에 else 가 없기 때문에 이의 대체 기능도 수행한다.

형식은 다음과 같다.

<c:choose>

body content

(하나 이상의 <when> 과 하나 이하의 <otherwise> 서브태그)

    <c:when test="조건">

        body content

    </c:when>

   

    <c:otherwise>

        conditional block

    </c:otherwise>

</c:choose>

 

조건 판단을 수행하는 간단한 예제이다.

예제 5.   jstlcore02.jsp

<% response.setContentType("text/html"); %>

<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c"%>

<h3>조건</h3>

파라메터 없음:<c:out value="${empty param.name}" />

<h4>&lt;c:if test=""></h4>

<c:if test="${empty param.name}">

<form>

이름을 적어주세요.<br>

    <input type="text" name="name">

    <input type="submit" value="확인">

</form>

</c:if>

<c:if test="${!empty param.name}">

    안녕하세요. <c:out value="${param.name}"/>.

</c:if>

 

<h4>&lt;c:choose> &ltc:when test=""> &ltc:otherwise></h4>

<c:choose>

    <c:when test="${empty param.name}">

        <form>

        이름을 적어주세요.<br>

            <input type="text" name="name">

            <input type="submit" value="확인">

        </form>

    </c:when>

    <c:when test="${param.name=='admin'}">

        안녕하세요. 관리자님.

    </c:when>

    <c:otherwise>

        안녕하세요. <c:out value="${param.name}"/>.

    </c:otherwise>

</c:choose>

파라메터 name 값이 없는 경우 입력 폼을 출력한다. 파라메터 name 의 값이 "admin"일 경우 관리자를 표시하고, 그 외에는 파라메터 값을 그대로 출력한다.

파라메터의 유무는 empty !empty 연산자를 통해서 확인할 수 있다.

 

4.6          <c:forEach/>, <c:forTokens/>

<c:forEach/> 는 강력한 반복실행 태그이다. 형식은 다음과 같다.

Syntax 1: 객체 전체에 걸쳐서 반복

<c:forEach [var="varName"] items="collection"

           [varStatus="varStatusName"]

           [begin="begin"] [end="end"] [step="step"]>

    body content

</c:forEach>

 

Syntax 2: 지정한 횟수만큼 반복

<c:forEach [var="varName"]

           [varStatus="varStatusName"]

           begin="begin" end="end" [step="step"]>

    body content

</c:forEach>

 

<c:forEach/> 태그는 여러가지로 활용이 가능하다. 원하는 구간만큼 반복할 수도 있고, 객체를 받아와서 그 객체의 길이만큼 반복할 수도 있다. begin , end 속성은 시작번호와 끝번호를 지정하고, step 속성을 이용해서 증가 구간을 정할 수 있다. var 속성에서 정한 변수로 반복되는 내부 구간에서 사용할 수 있다.

 

<c:forTokens/> java.util.StringTokenizer 를 이용한 것이다. 형식은 다음과 같다.

Syntax

<c:forTokens items="stringOfTokens" delims="delimiters"

[var="varName"]

[varStatus="varStatusName"]

[begin="begin"] [end="end"] [step="step"]>

body content

</c:forEach>

 

<c:forEach/> <c:forTokens/> 를 활용한 예제이다.

예제 6.   jstlcore03.jsp

<% response.setContentType("text/html"); %>

<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c"%>

<h3>반복</h3>

<h4>&lt;c:forEach></h4>

 

<c:forEach var="one" begin="1" end="10">

    <c:out value="${one}"/>

</c:forEach>

<p><b>header</b></p>

<c:forEach var="h" items="${header}">

    <c:out value="${h.key}:${h.value}"/><br>

</c:forEach>

 

<h4>&lt;c:forTokens></h4>

<c:forTokens var="one"

            items="서울|인천,대전,대구,부산,광주,평양"

            delims="," varStatus="sts">

    <c:out value="${sts.count}:${one}"/>&middot;

</c:forTokens>

<hr>

<c:forTokens var="one"

            items="서울|인천,대전,대구,부산,광주,평양"

            delims=",|" varStatus="sts">

    <c:out value="${sts.count}:${one}"/>&#149;

</c:forTokens>

 

예제의 첫번째 <c:forEach/> 에서는 1에서 10까지 반복하면서 값을 출력한다. 이때 var속성의 one변수에는 진행중인 값이 저장된다.

두번째 <c:forEach/> 반복문을 보면 items 속성에 header 객체를 받아온다. header 객체는 Map 형태이고, getKey() getValue() 메소드의 사용이 가능하기 때문에 h.key h.value 를 통해서 출력할 수 있다.

<c:forTokens/> 태그는 StringTokenizer 와 동일한 기능을 한다. delims 속성에 정해진 char 로 나뉘어지게 된다. 마지막 반복구간에서 마디로 나누는 기준은 , | 두 가지이다.

varStatus 속성에서 정해준 변수는 .index .count 를 사용할 수 있고, 시작 번호는 각각 0 1 이다.

 

4.7          <c:import/>

이제 소개할 <c:import/> 는 아주 강력한 도구이다. 웹 어플리케이션 내부의 자원 접근은 물론이고, http, ftp 같은 외부에 있는 자원도 가져와서 페이지 내에 귀속시킨다. 자유롭게 가공할 수도 있고, 편집도 가능하다. <c:import/> 의 형식은 다음과 같다.

Syntax 1: 해당 주소를 바로 출력하거나 String 에 담아놓는다.

<c:import url="url" [context="context"]

        [var="varName"] [scope="{page|request|session|application}"]

        [charEncoding="charEncoding"]>

   <c:param> 서브 태그 위치

</c:import>

 

Syntax 2: 해당 주소의 컨텐츠를 Reader 객체로

<c:import url="url" [context="context"]

        varReader="varReaderName"

        [charEncoding="charEncoding"]>

    varReader 를 사용하는 액션

</c:import>

스트림으로 받아와서 파일로 저장하거나, DB에 입력할 수도 있도록 되어있다.

다음은 간단한 예제이다.

예제 7.   jstlcore04.jsp

<% response.setContentType("text/html"); %>

<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c"%>

 

<c:set var="url" value="http://www.google.co.kr/"/>

<c:import url="${url}" var="u"/>

<c:out value="${url}"/> 가져옵니다.

<hr>

<base href="<c:out value="${url}"/>">

    <c:out value="${u}" escapeXml="false"/>

</base>

<hr>

 

<c:set var="url" value="http://www.okjsp.pe.kr"/>

<c:import url="${url}" var="u"/>

<c:out value="${url}"/> 가져옵니다.

<hr>

<pre><c:out value="${u}"/></pre>

<hr>

 

<c:set var="url" value="ftp://ftp.dacom.co.kr"/>

<c:import url="${url}" var="u"/>

<c:out value="${url}"/> 가져옵니다.

<hr>

<pre><c:out value="${u}"/></pre>

<hr>

 

<c:set var="url" value="jstlcore02.jsp"/>

<c:import url="${url}" var="u">

    <c:param name="name" value="admin"/>

</c:import>

<c:out value="${url}"/> 가져옵니다.

<hr>

<c:out value="${u}" escapeXml="false"/>

<hr>

4개의 주소를 불러오는 예제이다.

처음에는 구글사이트를 불러서 그대로 표시한다. escapeXml 속성을 false 로 해야 브라우저에 태그가 나타나지 않는다.

<base href=""> 태그는 소스를 가져왔을 때 상대경로에 있는 주소의 기준점이 된다. 따라서 상대경로로 표시된 이미지 등을 깨지지 않고 표시할 수 있다.

두번째는 okjsp 사이트를 가져와서 소스를 보여준다. escapeXml 속성이 생략되면 true값으로 지정되고, 태그를 볼 수 있게 했다.

세번째는 ftp.dacom.co.kr 에 있는 내용을 가져온다.

마지막에는 앞에서 보았던 jstlcore02.jsp 를 불러오는 예제이다. <c:param/> 태그를 내부에 두어서 파라메터값을 보낼 수 있다.



 

4.8          <c:url/>

<c:url/> 태그는 컨텍스트를 자동으로 추가해서 주소를 자동으로 생성해준다. context 속성이 지정되었을 경우 value context 의 값은 / 로 시작을 해야된다. context 속성이 생략되면 당연히 현재의 컨텍스트가 적용된다. <c:url/> 의 형식은 다음과 같다.

Syntax 1: Body 없는 경우

<c:url value="value" [context="context"]

        [var="varName"] [scope="{page|request|session|application}"]/>

 

Syntax 2: Body 있는 경우 쿼리 스트링 파라메터 지정

<c:url value="value" [context="context"]

        [var="varName"] [scope="{page|request|session|application}"]>

    <c:param> 서브태그

</c:url>

 

다음은 간단한 예제이다.

예제 8.   jstlcore05.jsp

<% response.setContentType("text/html"); %>

<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c"%>

 

<c:url value="/images/tomcat.gif"/>

<img src="<c:url value="/images/tomcat.gif"/>">

코드를 실행하면, <img src="/chap9/images/tomcat.gif">  와 같이 출력이 된다. ROOT 컨텍스트일 경우는 <img src="/images/tomcat.gif"> 와 같이 출력된다.

다른 컨텍스트를 사용하는 경우 정적인 컨텐츠의 주소를 쓰기 위해서는 jsp 에서는 <img src="<%=request.getContextPath()%>/images/tomcat.gif"> 와 같이 처리를 해주어야 되었다. 이런 경우를 대체하는 태그이다.

 

4.9          <c:redirect/>

response.sendRedirect() 를 대체하는 태그이다. 컨텍스트를 지정해서 다른 컨텍스트로 이동이 가능하다.

<c:redirect/> 의 형식은 다음과 같다.

Syntax 1: Body 없는 경우

<c:redirect url="value" [context="context"]/>

 

Syntax 2: Body 있는 경우 쿼리 스트링 파라메터 지정

<c:redirect url="value" [context="context"]/>

    <c:param> 서브태그

</c:redirect>

 

다음은 간단한 예제이다.

예제 9.   jstlcore06.jsp

<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c"%>

 

<c:redirect url="/jstlcore01.jsp"/>

<c:url/> 태그와 마찬가지로 context 속성을 지정하면, value context 의 값은 / 로 시작을 해야된다. <c:param/> 태그를 중첩시켜서 사용할 수도 있다.

 

4.10       <c:param/>

<c:param/> 은 다음과 같이 url 에 바로 붙여서 쓸 수도 있다.

<c:import url="/exec/doIt">

  <c:param name="action" value="register"/>

</c:import>

이 방법은 아래 태그와 같은 효과가 있다.

<c:import url="/exec/doIt?action=register"/>

 

이제까지 기본적인 태그인 core 태그들에 대해서 살펴보았다. 다음 섹션에서 출력 형식을 지정하는 fmt 태그를 살펴보도록 하겠다.

 

5           JSTL 국제화 지역화 태그

다국어 문서를 처리할 때 유용하고, 날짜와 숫자 형식을 다루는 fmt 태그는 다음과 같은 종류가 있다.

기능

태그

prefix

Locale 설정

setLocale, requestEncoding

fmt

메시지 처리

bundle, message(param), setBundle

숫자 날짜 형식

formatNumber, formatDate, parseDate, parseNumber, setTimeZone, timeZone

 

fmt 태그를 사용하기 위해서 페이지 상단에 다음과 같이 선언되어야 된다.

<%@ taglib uri="http://java.sun.com/jstl/fmt" prefix="fmt"%>

 

 

5.1          <fmt:setLocale/>

<fmt:setLocale/> 의 형식은 다음과 같다.

Syntax

<fmt:setLocale value="locale"

        [variant="variant"]

        [scope="{page|request|session|application}"]/>

 

 

다국어 페이지를 만들 경우 사용할 경우 ResourceBundle 로 불러오는 *.properties 파일들과 연계되어서 사용할 수 있다. value 속성에 들어가는 locale 값은 [1]언어코드와 [2]국가코드로 이루어진다. 생략될 경우 톰캣 서버의 기본값으로 설정이 되고, 둘 중에 하나만 사용할 수도 있다. http://java.sun.com/j2se/1.4.1/docs/api/java/util/Locale.html api 에 보다 상세한 설명이 있다.

예제 10.                          jstlfmt01.jsp

<%@ taglib uri="http://java.sun.com/jstl/fmt" prefix="fmt"%>

<pre>

default locale : <%= response.getLocale() %>

set locale : ko <fmt:setLocale value="ko" />

now: <%= response.getLocale() %>

set locale : ja <fmt:setLocale value="ja" />

now: <%= response.getLocale() %>

set locale : en <fmt:setLocale value="en" />

now: <%= response.getLocale() %>

</pre>

예제를 값을 변경시켜서 실행하면, response 쪽에 영향을 주는 것을 알 수 있다.

 

5.2          <fmt:requestEncoding/>

다음으로 볼 것은 request.setCharacterEncoding() 역할을 하는 <fmt:requestEncoding/> 태그이다. 형식은 다음과 같다.

Syntax

<fmt:requestEncoding [value="charsetName"]/>

 

파라메터를 MS949 로 인코딩하는 경우 다음과 같이 사용하면 된다.

<fmt:requestEncoding value="MS949"/>

 

예제 11.                         jstlfmt02.jsp

<%@ page contentType="text/html;charset=euc-kr" %>

<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>

<%@ taglib uri="http://java.sun.com/jstl/fmt" prefix="fmt" %>

<fmt:requestEncoding value="euc-kr"/>

파라메터:<c:out value="${param.id}"/>

<form method="post">

    <input type="text" name="id">

    <input type="submit">

</form>

페이지 인코딩이 적용된 경우 request 에서 가져오는 parameter 와 맞지 않는 경우에 사용한다. 서버마다 차이가 있기 때문에, 테스트를 통해서 자신의 환경에 맞게 사용해야 된다. 톰캣4.1.19 의 경우 인코딩을 적용하지 않고도, 해결되는데 다음과 같은 형태로 사용할 수 있다.

예제 12.                         jstlfmt02b.jsp

<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c"%>

<%@ taglib uri="http://java.sun.com/jstl/fmt" prefix="fmt"%>

<% response.setContentType("text/html;"); %>

파라메터:<c:out value="${param.id}"/>

<form method="post">

    <input type="text" name="id">

    <input type="submit">

</form>

 

 

5.3          <fmt:bundle/>

properties 확장자를 사용하는 자원 파일을 읽어오는 역할을 하는 <fmt:bundle/> 에 대해서 알아보자. 형식은 다음과 같다.

Syntax

<fmt:bundle basename="basename"

        [prefix="prefix"]>

    body content

</fmt:bundle>

 

basename 속성에 지정된 properties 파일을 찾아서 locale 에 따라 읽어들인다.

properties 파일은 보통 WEB-INF/classes 아래에 위치하며 디렉토리의 깊이에 따라서 패키지형식의 이름을 취한다. TestBundle.properties 파일이 com/itexpert/chap9/msg 디렉토리에 있다면 basename="com.itexpert.chap9.msg.TestBundle" 이라고 지정하면 된다.

locale ko 라면 TestBundle_ko.properties 파일을 읽어오게 되며, locale 이 맞지 않는 경우에는 TestBundle.properties 처럼 코드가 붙지 않은 파일을 읽어온다.

prefix 속성은 key 명칭이 공통적인 부분을 지정해서 body 에서 표현되는 key 를 단축시킨다. import 에서 패키지명을 지정하면 클래스명만 쓸 수 있는 것과 같이 생각할 수 있다.

properties 파일의 경우 j2sdk /bin/native2ascii.exe 를 이용해서 유니코드로 변환될 필요가 있으나, 파일 수가 많을 경우 ant <native2ascii> 태스크를 이용해서 쉽게 처리할 수 있다. chap9.zip 소스에 포함된 build.xml 파일에 보면 다음과 같은 태스크가 지정되어 있다.

<native2ascii encoding="EUC-KR"

            src="${src.home}"

            dest="${build.home}/WEB-INF/classes"

            includes="**/*_ko.properties"/>

 

5.4          <fmt:message/>

번들 태그에서 정한 값들을 가져오는 태그는 <fmt:message/>이다. 다음은 <fmt:message/> 태그의 형식이다.

Syntax 1: body 없는 경우

<fmt:message key="messageKey"

        [bundle="resourceBundle"]

        [var="varName"]

        [scope="{page|request|session|application}"]/>

 

Syntax 2: 메시지 파라메터를 지정하는 body가 있는 경우

<fmt:message key="messageKey"

        [bundle="resourceBundle"]

        [var="varName"]

        [scope="{page|request|session|application}"]>

    <fmt:param> 서브태그

</fmt:message>

 

Syntax 3: 키와 선택적 메시지 파라메터를 지정하는 body가 있는 경우

<fmt:message [bundle="resourceBundle"]

        [var="varName"]

        [scope="{page|request|session|application}"]>

    key

    선택적 <fmt:param> 서브태그

</fmt:message>

 

번들에 있는 key 값을 불러온다. bundle 속성으로 번들을 직접 설정할 수도 있고, <fmt:bundle/> 태그 사이에 중첩되어서 키값만 받아서 출력할 수 있다.

예제 13.                         TestBundle.properties

greeting=Hello.

admin=kenu

 

예제 14.                         TestBundle_ko.properties

greeting=안녕하세요.

admin=허광남

 

예제 15.                         jstlfmt03.jsp

<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c"%>

<%@ taglib uri="http://java.sun.com/jstl/fmt" prefix="fmt"%>

<fmt:setLocale value="ko"/>

<fmt:bundle basename="com.itexpert.chap9.msg.TestBundle">

 <fmt:message>greeting</fmt:message><br>

 <fmt:message>admin</fmt:message>

</fmt:bundle>

 

locale "ko" 로 지정했기 때문에 TestBundle_ko.properties 파일을 읽어온다. "en"으로 정하거나 맞는 프로퍼티가 없을 경우는 기본프로퍼티인 TestBundle.properties 파일을 읽는다.

<fmt:message> 를 통해서 greeting 키와 admin 키를 읽어와서 표시한다.

 

5.5          <fmt:setBundle/>

페이지 전체에서 사용할 수 있는 번들을 지정할 수 있는데, 이에 대한 지정은 <fmt:setBundle/> 태그가 담당한다. var 속성에서 정한 변수를 이후에 나오는 <fmt:message/> 태그에서 basename 속성에 변수명으로 대체할 수 있다. <fmt:setBundle/> 의 형식은 다음과 같다.

Syntax

<fmt:setBundle basename="basename"

        [var="varName"]

        [scope="{page|request|session|application}"]/>

 

예제 15. jstlfmt03.jsp 는 다음과 같이 수정할 수 있다.

예제 16.                         jstlfmt04.jsp

<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c"%>

<%@ taglib uri="http://java.sun.com/jstl/fmt" prefix="fmt"%>

<fmt:setLocale value="ko"/>

<fmt:setBundle var="testBundle"

    basename="com.itexpert.chap9.msg.TestBundle"/>

 

<fmt:message bundle="${testBundle}" key="greeting"/><br>

<fmt:message bundle="${testBundle}" key="admin"/><br>

var 에서 변수를 설정할 때는 EL 을 사용하지 않는다. 다른 태그에서 이것을 불러오는 경우는 EL 을 사용해서 불러온다. testBundle 변수의 사용을 눈여겨 볼만하다.

 

5.6          <fmt:formatNumber/>

다음은 숫자 형식을 표현하는 <fmt:formatNumber/> 태그이고 형식은 다음과 같다.

Syntax 1: body 없는 경우

<fmt:formatNumber value="numericValue"

        [type="{number|currency|percent}"]

        [pattern="customPattern"]

        [currencyCode="currencyCode"]

        [currencySymbol="currencySymbol"]

        [groupingUsed="{true|false}"]

        [maxIntegerDigits="maxIntegerDigits"]

        [minIntegerDigits="minIntegerDigits"]

        [maxFractionDigits="maxFractionDigits"]

        [minFractionDigits="minFractionDigits"]

        [var="varName"]

        [scope="{page|request|session|application}"]/>

 

Syntax 2: 형식에 맞출 수치가 body에 있는 경우

<fmt:formatNumber [type="{number|currency|percent}"]

        [pattern="customPattern"]

        [currencyCode="currencyCode"]

        [currencySymbol="currencySymbol"]

        [groupingUsed="{true|false}"]

        [maxIntegerDigits="maxIntegerDigits"]

        [minIntegerDigits="minIntegerDigits"]

        [maxFractionDigits="maxFractionDigits"]

        [minFractionDigits="minFractionDigits"]

        [var="varName"]

        [scope="{page|request|session|application}"]>

    형식화될 수치

</fmt:formatNumber>

 

 

각 속성을 정리한 표는 다음과 같다.

속성

동적값

Type

설명

value

true

String 또는

Number

형식화될 수치

type

true

String

숫자, 통화, 퍼센트 중 어느 것으로 표시할 지 지정 {number|currency|percent}

pattern

true

String

사용자가 지정한 형식 패턴.

currencyCode

true

String

ISO 4217 통화 코드. 통화 형식일 때만 적용(type="currency")

currencySymbol

true

String

통화 기호. 통화 형식일 때만 적용

(type="currency")

groupingUsed

true

boolean

형식 출력에 그룹 분리기호를 포함할지 여부

maxIntegerDigits

true

int

형식 출력에서 integer 최대 자리수

minIntegerDigits

true

int

형식 출력에서 integer 최소 자리수

maxFractionDigits

true

int

형식 출력에서 소수점 이하 최대 자리수.

minFractionDigits

true

int

형식 출력에서 소수점 이하 최소 자리수.

var

false

String

형식 출력 결과 문자열을 담는 scope에 해당하는 변수명

scope

false

String

var scope

 

5.7          <fmt:parseNumber/>

반대로 정해진 패턴을 문자열에서 수치를 파싱해내는 태그는 <fmt:parseNumber/>이며 형식은 다음과 같다.

Syntax 1: body가 없는 경우

<fmt:parseNumber value="numericValue"

        [type="{number|currency|percent}"]

        [pattern="customPattern"]

        [parseLocale="parseLocale"]

        [integerOnly="{true|false}"]

        [var="varName"]

        [scope="{page|request|session|application}"]/>

 

Syntax 2: 파싱할 수치를 body 에 갖고 있는 경우

<fmt:parseNumber [type="{number|currency|percent}"]

        [pattern="customPattern"]

        [parseLocale="parseLocale"]

        [integerOnly="{true|false}"]

        [var="varName"]

        [scope="{page|request|session|application}"]>

    파싱할 수치

</fmt:parseNumber>

 

 

각 속성을 정리한 도표는 다음과 같다.

속성

동적값

Type

설명

value

true

String 또는

Number

파싱할 수치

type

true

String

숫자, 통화, 퍼센트 중 어느 것으로 표시할 지 지정 {number|currency|percent}

pattern

true

String

사용자가 지정한 형식 패턴.

parseLocale

true

String 또는

java.util.Locale

파싱 작업의 기본 형식 패턴(숫자, 통화, 퍼센트 각각)을 제공하는 Locale

integerOnly

true

boolean

주어진 값에서 integer 부분만 파싱할지 여부를 지정

var

false

String

파싱 결과 (java.lang.Number 타입)를 담는 scope에 해당하는 변수명

scope

false

String

var scope

 

5.8          <fmt:formatDate/>

다음은 날짜 형식을 표현하는 <fmt:formatDate/> 태그이고 형식은 다음과 같다.

Syntax

<fmt:formatDate value="date"

        [type="{time|date|both}"]

        [dateStyle="{default|short|medium|long|full}"]

        [timeStyle="{default|short|medium|long|full}"]

        [pattern="customPattern"]

        [timeZone="timeZone"]

        [var="varName"]

        [scope="{page|request|session|application}"]/>

 

 

각 속성을 정리한 도표는 다음과 같다.

속성

동적값

Type

설명

value

true

java.util.Date

형식화될 Date time

type

true

String

형식화할 데이터가 시간, 날짜, 모두 인지 셋 중 하나를 지정한다.

dateStyle

true

String

미리 정의된 날짜 형식. Java.text.DateFormat 클래스에 정의된 문법을 따른다. type="date", type="body", type속성이 생략된 경우 사용.

timeStyle

true

String

미리 정의된 날짜 형식. Java.text.DateFormat 클래스에 정의된 문법을 따른다.

type="time", type="body" 의 경우 사용.

pattern

true

String

사용자 지정 형식 스타일

timeZone

true

String 또는

java.util.TimeZone

형식화 시간에 나타날 타임존

var

false

String

형식 출력 결과 문자열을 담는 scope에 해당하는 변수명

scope

false

String

var scope

 

5.9          <fmt:parseDate/>

정해진 패턴의 문자열에서 날짜를 파싱해내는 태그는 <fmt:parseDate/>이며 형식은 다음과 같다.

Syntax 1: body 없는 경우

<fmt:parseDate value="dateString"

        [type="{time|date|both}"]

        [dateStyle="{default|short|medium|long|full}"]

        [timeStyle="{default|short|medium|long|full}"]

        [pattern="customPattern"]

        [timeZone="timeZone"]

        [parseLocale="parseLocale"]

        [var="varName"]

        [scope="{page|request|session|application}"]/>

 

Syntax 2: 파싱한 값이 body 에 있는 경우

<fmt:parseDate [type="{time|date|both}"]

        [dateStyle="{default|short|medium|long|full}"]

        [timeStyle="{default|short|medium|long|full}"]

        [pattern="customPattern"]

        [timeZone="timeZone"]

        [parseLocale="parseLocale"]

        [var="varName"]

        [scope="{page|request|session|application}"]>

    파싱할 Date time

</fmt:parseDate>

 

 

각 속성을 정리한 도표는 다음과 같다.

속성

동적값

Type

설명

value

true

java.util.Date

파싱할 Date time

type

true

String

파싱할 데이터가 시간, 날짜, 모두 인지 셋 중 하나를 지정한다.

dateStyle

true

String

미리 정의된 날짜 형식. Java.text.DateFormat 클래스에 정의된 문법을 따른다. type="date", type="body", type속성이 생략된 경우 사용.

timeStyle

true

String

미리 정의된 날짜 형식. Java.text.DateFormat 클래스에 정의된 문법을 따른다.

type="time", type="body" 의 경우 사용.

pattern

true

String

사용자 지정 형식 스타일

timeZone

true

String 또는

java.util.TimeZone

형식화 시간에 나타날 타임존

parseLocale

true

String 또는

java.util.Locale

파싱하는 동안 적용될 미리 정의된 형식 스타일의 Locale

var

false

String

파싱 결과(java.util.Date)를 담는 scope에 해당하는 변수명

scope

false

String

var scope

 

다음은 숫자, 날짜에 대한 태그 사용 예제이다.

예제 17.                         jstlfmt05.jsp

<%@ page pageEncoding="MS949" %>

<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>

<%@ taglib uri="http://java.sun.com/jstl/fmt" prefix="fmt" %>

<pre><fmt:setLocale value="ko_KR"/>

number  : <fmt:formatNumber value="9876543.61" type="number"/>

currency: <fmt:formatNumber value="9876543.61" type="currency"/>

percent : <fmt:formatNumber type="percent">9876543.61</fmt:formatNumber>

 

pattern=".000"    :<fmt:formatNumber value="9876543.61" pattern=".000" />

pattern="#,#00.0#":<fmt:formatNumber value="9876543.612345" pattern="#,#00.0#"/>

 

<jsp:useBean id="now" class="java.util.Date"/>

<c:out value="${now}"/>

date: <fmt:formatDate value="${now}" type="date"/>

time: <fmt:formatDate value="${now}" type="time"/>

both: <fmt:formatDate value="${now}" type="both"/>

 

default:<fmt:formatDate value="${now}"

            type="both" dateStyle="default" timeStyle="default"/>

short  :<fmt:formatDate value="${now}"

            type="both" dateStyle="short"   timeStyle="short"  />

medium :<fmt:formatDate value="${now}"

            type="both" dateStyle="medium"  timeStyle="medium" />

long   :<fmt:formatDate value="${now}"

            type="both" dateStyle="long"    timeStyle="long"   />

full   :<fmt:formatDate value="${now}"

            type="both" dateStyle="full"    timeStyle="full"   />

 

pattern="yyyyMMdd HHmmss"

         <fmt:formatDate value="${now}" type="both"

            pattern="yyyyMMdd HHmmss"/>

</pre>

 

 

5.10       <fmt:setTimeZone/>, <fmt:timeZone/>

특정 스코프의 타임존을 설정하는 <fmt:setTimeZone/> 태그의 형식은 다음과 같다.

Syntax

<fmt:setTimeZone value="timeZone"

        [var="varName"]

        [scope="{page|request|session|application}"]/>

 

타임존을 부분 적용하는 <fmt:timeZone/> 태그는 다음과 같은 형식이다.

Syntax

<fmt:timeZone value="timeZone">

    body content

</fmt:timeZone>

 

타임존을 적용한 시간 표시 예제이다.

예제 18.                         jstlfmt06.jsp

<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c"%>

<%@ taglib uri="http://java.sun.com/jstl/fmt" prefix="fmt"%>

<pre><fmt:setLocale value="ko_KR"/>

<jsp:useBean id="now" class="java.util.Date"/>

 

default: <c:out value="${now}"/>

Korea   KST  : <fmt:formatDate value="${now}" type="both" dateStyle="full"

                   timeStyle="full"/>

<fmt:timeZone value="GMT">

Swiss   GMT  : <fmt:formatDate value="${now}" type="both" dateStyle="full"

                   timeStyle="full"/>

</fmt:timeZone>

<fmt:timeZone value="GMT-8">

NewYork GMT-8: <fmt:formatDate value="${now}" type="both" dateStyle="full"

                   timeStyle="full"/>

</fmt:timeZone>

</pre>

 

 

이상으로 태그를 이용해서 숫자, 날짜, 시간 등을 표현하는 방법을 알아보았다. 태그의 속성들이 직관적이기 때문에 사용에 그리 불편하지 않을 것이다.

 

 

6           JSTL SQL 태그

DataSource 를 이용해서 SQL을 처리하는 sql 태그는 다음과 같은 것들이 있다.

기능

태그

prefix

DataSource 설정

SetDataSource

sql

SQL

query (dateParam, param) , update (dateParam, param) ,

transaction

 

sql 태그를 사용하기 위해서 페이지 상단에 다음과 같이 선언되어야 된다.

<%@ taglib uri="http://java.sun.com/jstl/sql" prefix="sql"%>

 

6.1          <sql:setDataSource/>

DataSource 를 지정하는 방식은 <sql:setDataSource/> 태그의 사용법은 다음과 같다.

Syntax

<sql:setDataSource

        {dataSource="dataSource" |

            url="jdbcUrl"

            [driver="driverClassName"]

            [user="userName"]

            [password="password"]}

        [var="varName"]

        [scope="{page|request|session|application}"]/>

 

오라클에서 사용을 한다면 다음과 같이 DataSource 를 설정할 수 있다.

<sql:setDataSource

            url="jdbc:oracle:thin:@localhost:1521:ora81"

            driver="oracle.jdbc.driver.OracleDriver"

            user="scott"

            password="tiger"

        var="okjspDS"

        scope="application" />

 

이미 컨텍스트에 JNDI 설정이 되어있다면 다음과 같이 바로 불러서 사용하거나 <sql:query/> 에서 바로 사용할 수 있다.

기존의 dataSource 를 불러와 사용하는 경우

<sql:setDataSource

        dataSource="jdbc/myora81"

        var="okjspDS"

        scope="application" />

 

<sql:query/> 에서 바로 사용하는 경우

<sql:query var="emp"

        dataSource="jdbc/myora81">

 

6.2          <sql:query/>

java 와는 달리 sql 문장을 문자열로 연결하지 않아도 가독성을 높여서 작성할 수 있다. <sql:query/>태그의 형식은 다음과 같다.

 

Syntax 1: body 없는 경우

<sql:query sql="sqlQuery"

        var="varName" [scope="{page|request|session|application}"]

        [dataSource="dataSource"]

        [maxRows="maxRows"]

        [startRow="startRow"]/>

 

Syntax 2: body 에 쿼리의 파라메터가 있는 경우

<sql:query sql="sqlQuery"

        var="varName" [scope="{page|request|session|application}"]

        [dataSource="dataSource"]

        [maxRows="maxRows"]

        [startRow="startRow"]>

    <sql:param> 액션들

</sql:query>

 

Syntax 3: 쿼리와 파라메터들이 body 에 있는 경우

<sql:query var="varName"

        [scope="{page|request|session|application}"]

        [dataSource="dataSource"]

        [maxRows="maxRows"]

        [startRow="startRow"]>

    sqlQuery

    선택적 <sql:param> 액션들

</sql:query>

 

 

6.3          <sql:dateParam/> , <sql:param/>

파라메터에는 두 가지가 있는데, 날짜 형식의 <sql:dateParam/> 와 일반적인 <sql:param/>태그가 있으며 형식은 다음과 같다.

Syntax

<sql:dateParam value="value" type="[timestamp|time|date]"/>

 

Syntax 1: value 속성에 파라메터 값이 지정된 경우

<sql:param value="value"/>

 

Syntax 2: body 내용에 파라메터 값이 지정된 경우

<sql:param>

    parameter value

</sql:param>

<sql:dateParam/> java.sql.PreparedStatement.setTimestamp() 역할을 하고,

<sql:param/> java.sql.PreparedStatement.setString() 의 역할을 한다. 바인드변수의 순서에 따라서 써주면 된다.

 

7장의 jdbc_resultset.jsp 파일을 JSTL로 바꾸어서 변경한 것이다.

예제 19.                         jstlsql01.jsp

<%@ page pageEncoding="MS949" %>

<%@ taglib prefix="sql" uri="http://java.sun.com/jstl/sql" %>

<%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt" %>

<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>

<fmt:setLocale value="ko" />

<sql:query var="emp"

        dataSource="jdbc/myora81">

SELECT  EMPNO AS 사원번호, ENAME AS 이름,

            SAL AS 월급여, HIREDATE AS 입사일

    FROM EMP

</sql:query>

 

<table border="1">

  <tr>

<%-- 필드의 정보를 출력한다.            --%>

  <c:forEach var="columnName" items="${emp.columnNames}">

    <th><c:out value="${columnName}"/></th>

  </c:forEach>

 

<%-- 데이터를 한 줄씩 출력한다.         --%>

  <c:forEach var="row" items="${emp.rowsByIndex}">

    <tr>

<%-- 필드의 길이만큼 반복한다.          --%>

      <c:forEach var="column" items="${row}" varStatus="i">

        <c:choose>

          <c:when test="${i.index==3}">

      <td><fmt:formatDate value="${column}" pattern="yyyy/MM/dd"/></td>

          </c:when>

          <c:otherwise>

      <td><c:out value="${column}"/></td>

          </c:otherwise>

        </c:choose>

      </c:forEach>

  </c:forEach>

</table>

<hr>

<table border="1">

  <c:forEach var="row" items="${emp.rows}">

  <tr>

    <td>번호: <c:out value="${row['사원번호']}"/></td>

    <td>이름: <c:out value="${row['이름']}"/></td>

  </tr>

  </c:forEach>

</table>

 

dataSource="jdbc/myora81" JNDI 7장에서 설명한 것처럼 컨텍스트에 설정된 DataSource 명이다.

SQL문은 보기 좋게 정렬을 해도 문자열로 덧붙일 필요가 없다. body 에 있는 sql문을 실행한 결과는 emp 라는 변수에 담겨서 이후에 사용이 된다. 이 변수는 ResultSet 과 같은데, JSTL에서 확장한 ResultSet 이고, javax.servlet.jsp.jstl.sql public interface Result 클래스로 내부적으로 정의된다. 지원하는 메소드는 다음과 같다.

javax.servlet.jsp.jstl.sql

public interface Result

public java.util.SortedMap[] getRows()

public Object[][] getRowsByIndex()

public String[] getColumnNames()

public int getRowCount()

public boolean isLimitedByMaxRows()

 

 

위와 같은 메소드들이 내부적으로 정의되어있기 때문에 각각의 getter 메소드들을 사용해서 변수 emp를 활용할 수 있다.

<c:forEach/> items 에 있는 ${emp.columnNames} getColumnNames() 메소드를 불렀다는 것을 알 수 있다. 이전의 7장에서 ResultSetMetaData 를 활용해서 뽑아낸 정보와 같은 효과를 볼 수 있다.

테이블 내용을 반환하는 ${emp.rowsByIndex} 도 유념할 만하다. 한 행을 row라는 변수에 넣은 뒤에 다음의 <c:forEach/> 에서 이 row변수의 컬럼별로 내용을 출력한다.

column 이라는 변수에 넣은 뒤에 column index 3일 경우 날짜형식을 출력하기 위해서 <fmt:formatDate/> 태그를 사용했고, 그 외의 경우는 바로 출력하게 했다.

다음 <c:forEach/> 에서는 결과를 SortedMap 배열에 넣은 뒤에 한 줄씩 빼서 컬럼이름으로 빼내는 방식이다.

 

6.4          <sql:update/>

java.sql.Statement.executeUpdate() 메소드에 해당하는 <sql:update/> 태그의 형식은 다음과 같다.

Syntax 1: body 없는 경우

<sql:update sql="sqlUpdate"

        [dataSource="dataSource"]

        [var="varName"] [scope="{page|request|session|application}"]/>

 

Syntax 2: update 파라메터가 body에 있는 경우

<sql:update sql="sqlUpdate"

        [dataSource="dataSource"]

        [var="varName"] [scope="{page|request|session|application}"]>

    <sql:param> 액션들

</sql:update>

 

Syntax 3: update 문과 선택적 update 파라메터가 body에 있는 경우

<sql:update [dataSource="dataSource"]

        [var="varName"] [scope="{page|request|session|application}"]>

    sqlUpdate

    선택적 <sql:param> 액션들

</sql:update>

형식과 동작은 <sql:query/> 태그와 동일하다. 다른 점은 executeUpdate() 메소드를 수행하기 때문에 DB에 변경을 가할 수 있다는 것이다.

 

6.5          <sql:transaction/>

트랜잭션을 구현하는 <sql:transaction/> 태그의 형식은 다음과 같다.

Syntax

<sql:transaction [dataSource="dataSource"]

        [isolation=isolationLevel]>

    <sql:query> <sql:update> 문들

</sql:transaction>

 

isolationLevel ::= "read_committed"

                | "read_uncommitted"

                | "repeatable_read"

                | "serializable"

격리 수준(isolationLevel) java.sql.Connection setTransactionIsolation() 메소드를 사용한다. 정리해 놓은 도표는 7 JDBC Transaction 을 참고하기 바란다.

 

7           JSTL XML 태그

7.1          xml 태그와 XPath

xml 태그를 사용하기 위해서는 XPath 를 먼저 이해할 필요가 있다. xml 소스 트리의 정확한 위치를 지정해주기 위한 경로지정 문법이며 XSLT XPointer 를 위해서 만들어진 것이다. xml 엘리먼트들을 노드(node) 로 접근한다. 파일 시스템과 유사하며 다음과 같은 특성이 있다.

l        / 로 시작하면 절대경로처럼 root node 에서 시작된다.

l        //로 시작할 경우는 모든 영역에서 해당 엘리먼트를 선택하게 된다.

l        표시는 이전 엘리먼트 아래의 모든 자식 엘리먼트를 나타낸다.

l        동일한 엘리먼트들이 있을 경우, [] 안에 포함된 숫자는 엘리먼트의 순번이다. 조건식이 올 경우 해당하는 것이 선택된다. last() 일 경우는 맨 마지막 엘리먼트를 표시한다.

l        속성은 @ 로 시작된다.

l        normalize-space() 함수는 앞뒤 공백을 제거하는 trim() 역할을 한다.

이 장에 나오는 XPath의 기능은 이 정도로 소개하겠고, XPath에 관한 보다 자세한 내용은 이 장의 마지막에 소개한 인터넷 튜토리얼을 참고하기 바란다.

 

JSTL에서 XPath를 통해서 내장객체에 쉽게 접근할 수 있다.

표현

매핑

$foo

pageContext.findAttribute("foo")

$param:foo

request.getParameter("foo")

$header:foo

request.getHeader("foo")

$cookie:foo

maps to the cookie's value for name foo

$initParam:foo

application.getInitParameter("foo")

$pageScope:foo

pageContext.getAttribute(

"foo", PageContext.PAGE_SCOPE)

$requestScope:foo

pageContext.getAttribute(

"foo", PageContext.REQUEST_SCOPE)

$sessionScope:foo

pageContext.getAttribute(

"foo", PageContext.SESSION_SCOPE)

$applicationScope:foo

pageContext.getAttribute(

"foo", PageContext.APPLICATION_SCOPE)

예를 들어서 다음 문장은 parameter 로 받은 "name"의 값이 bar엘리먼트의 x속성의 값과 같은 것들을 선택하게 된다.

/foo/bar[@x=$param:name]

 

xml 태그는 다음과 같은 것들이 있다.

기능

태그

prefix

기본

out, parse, set

x

흐름 제어

choose (when, otherwise), forEach, if

변환

transform (param)

 

xml 태그를 사용하기 위해서 페이지 상단에 다음과 같이 선언되어야 된다.

<%@ taglib uri="http://java.sun.com/jstl/xml" prefix="x"%>

 

7.2          <x:out/>

XPath에 지정한 패턴에 따라 xml내용을 출력하는 <x:out/> 태그의 형식은 다음과 같다.

Syntax

<x:out select="XPathExpression" [escapeXml="{true|false}"]/>

 

 

7.3          <x:parse/>

xml문서를 읽어서 파싱하는 <x:parse/> 태그는 다음과 같은 형식이다.

Syntax 1: String 또는 Reader 객체로 지정된 XML 문서

<x:parse xml="XMLDocument"

        {var="var" [scope="scopeName"]|varDom="var" [scopeDom="scopeName"]}

        [systemId="systemId"]

        [filter="filter"]/>

 

Syntax 2: body 내용으로 지정된 XML 문서

<x:parse

        {var="var" [scope="scopeName"]|varDom="var" [scopeDom="scopeName"]}

        [systemId="systemId"]

        [filter="filter"]>

    파싱할 XML 문서

</x:parse>

scopeName {page|request|session|application} 중의 하나

 

 

7.4          <x:set/>

XPath에 따라 선택된 내용을 변수에 저장하는 <x:set/> 태그의 형식은 다음과 같다.

Syntax

<x:set select="XPathExpression"

        var="varName" [scope="{page|request|session|application}"]/>

 

7.5          <x:if/>

<c:if/> 태그와 마찬가지로 xml태그에도 <x:if/> 가 있고 형식은 <c:if/> 태그와 유사하다. <x:if/>의 형식은 다음과 같다.

Syntax 1: Body 없는 경우

<x:if select="XPathExpression"

        var="varName" [scope="{page|request|session|application}"]/>

 

Syntax 2: Body 있는 경우

<x:if select="XPathExpression"

        [var="varName"] [scope="{page|request|session|application}"]>

    body content

</x:if>

test 속성 대신에 select 속성으로 진위를 따지는데, 다음 3가지 기준을 유념할 필요가 있다. 이 세 가지 기준은 <x:choose/> <x:when/> <x:forEach/> 에서도 동일하게 사용된다.

1. number true 인 때는 + 또는 – 0 도 아니고, NaN(Not A Number) 도 아닐 경우

2. node-set true 인 때는 empty 가 아닐 경우

3. string true 인 때는 길이가 0 이 아닐 경우

 

7.6          <x:choose/>,  <x:when/>,  <x:otherwise/>

<c:choose/> 태그와 마찬가지로 xml태그에도 <x:choose/> 가 있고 형식은 <c:choose/> 태그와 유사하다.

Syntax

<x:choose>

    body content (<x:when> and <x:otherwise> 서브태그)

</x:choose>

 

Syntax

<x:when select="XPathExpression">

    body content

</x:when>

 

Syntax

<x:otherwise>

    conditional block

</x:otherwise>

 

7.7          <x:forEach/>

<x:forEach/> 태그는 XPath에 따라서 해당하는 엘리먼트 수만큼 반복하게 된다.

Syntax

<x:forEach [var="varName"] select="XPathExpression">

    body content

</x:forEach>

 

 

xml 태그를 활용한 예제이다.

예제 20.                         jstlxml01.jsp

<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>

<%@ taglib uri="http://java.sun.com/jstl/xml" prefix="x" %>

<% response.setContentType("text/html;"); %>

<%-- 파라메터 받아서 출력 --%>

<c:if test="${!empty param.name}">

param: <x:out select="$param:name"/>

</c:if>

<form>

name: <input type="text" name="name">

<input type="submit">

</form>

<hr>

<%-- xml 데이터를 xdata 변수에 할당 --%>

<x:parse var="xdata">

<namecard>

    <person>

        <name>허광남</name>

        <id>남자</id>

        <email>kenu@email.com</email>

        <phone>111-2222-3333</phone>

    </person>

    <person>

        <name>노재춘</name>

        <id>남자</id>

        <email>suribada@email.com</email>

        <phone>222-3333-4444</phone>

    </person>

    <person>

        <name>이선재</name>

        <id>남자</id>

        <email>hsboy@email.com</email>

        <phone>333-4444-5555</phone>

    </person>

</namecard>

</x:parse>

<%-- XPath 를 이용해서 xdata에서 추출 --%>

<x:out select="$xdata//person[1]/name"/>

<x:out select="$xdata//person[last()]/name"/>

<hr>

<%-- person 으로 반복해서 email phone 출력 --%>

<table border="1">

<x:forEach select="$xdata//person">

<tr><td><x:out select="email" /></td>

<td><x:out select="phone" /></td></tr>

</x:forEach>

</table>

 

파라메터 name 의 접근은 EL에서는 ${param.name} 으로 사용하지만 XPath 에서는 $param:name 을 사용한다는 차이가 있다.

파라메터를 받아서 <x:out/> 으로 출력하는 부분이 제일 상단이고, 그 다음은 xml 데이터를 파싱하는 부분이다.

DTD 까지 쓰지 않아도 형식이 잘 갖춰지기만 하면 (well-formed) xml 데이터로 인식을 한다. 이것을 xdata라는 변수에 할당한 다음에 이후에 처리하게 된다.

 

xml 데이터는 파일로 따로 만든 후에 접근할 수 있다. 이때는 <c:import> 를 같이 사용하는데, 다음과 같이 쓸 수 있다.

예제 21.                         namecard.xml

<?xml version="1.0" encoding="euc-kr" ?>

<namecard>

    <person>

        <name>허광남</name>

        <id>남자</id>

        <email>kenu@email.com</email>

        <phone>111-2222-3333</phone>

    </person>

    <person>

        <name>노재춘</name>

        <id>남자</id>

        <email>suribada@email.com</email>

        <phone>222-3333-4444</phone>

    </person>

    <person>

        <name>이선재</name>

        <id>남자</id>

        <email>hsboy@email.com</email>

        <phone>333-4444-5555</phone>

    </person>

</namecard>

 

 

예제 22.                         jstlxml02.jsp

<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c"%>

<%@ taglib uri="http://java.sun.com/jstl/xml" prefix="x"%>

<% response.setContentType("text/html;"); %>

<%-- namecard.xml 파일을 불러와 xdata 변수에 할당 --%>

<c:import url="namecard.xml" var="xmldata" />

<x:parse xml="${xmldata}" var="xdata"/>

 

<%-- XPath 를 이용해서 xdata에서 추출 --%>

<x:out select="$xdata//person[1]/name"/>

이하 생략

 

xdata 변수에 들어간 xml 에서 추출하는 방식은 XPath 를 사용한다고 했다.

$select="$xdata//person[1]/name" 에서 person[1] person 으로 사용하는 것과 같다. [] 안에는 순서가 들어가고 생략될 경우 첫 엘리먼트를 찾기 때문이다.

<x:forEache/> 태그로 <person> 엘리먼트 수만큼 반복하게 했다. 이때 자동으로 기준은 <person> 이 되기 때문에 그 이후에 <email> 이나 <phone> 엘리먼트들은 /person/email /person/phone 을 바로 참조하게 된다.

 

7.8          <x:transform/>, <x:param/>

xml xslt 파일을 결합해서 새로운 형식의 문서를 생성해 내는 <x:transform/>의 형식은 다음과 같다.

Syntax 1: Body 없는 경우

<x:transform

        xml="XMLDocument" xslt="XSLTStylesheet"

        [xmlSystemId="XMLSystemId"] [xsltSystemId="XSLTSystemId"]

        [{var="varName" [scope="scopeName"]|result="resultObject"}]>

 

Syntax 2: 변환 파라메터를 body에서 지정하는 경우

<x:transform

        xml="XMLDocument" xslt="XSLTStylesheet"

        [xmlSystemId="XMLSystemId"] [xsltSystemId="XSLTSystemId"]

        [{var="varName" [scope="scopeName"]|result="resultObject"}]>

    <x:param> 액션들

</x:transform>

 

Syntax 3: XML문서와 선택적 변환 파라메터들이 body에 지정된 경우

<x:transform

        xslt="XSLTStylesheet"

        xmlSystemId="XMLSystemId" xsltSystemId="XSLTSystemId"

        [{var="varName" [scope="scopeName"]|result="resultObject"}]>

    XML Document

    optional <x:param> actions

</x:parse>

scopeName {page|request|session|application} 중에 하나

 

var 속성에 지정된 결과와 result 속성에 지정된 결과의 차이점은 var 속성은 scope 지정해서 다른 곳에서도 사용할 수 있고, result 는 현재 페이지에서만 사용할 수 있다는 것이다.

또한 타입도 차이가 나는데, varorg.w3c.dom.Document , resultjavax.xml.transform.Result 객체로 저장이 된다.

 

xml의 파라메터를 지정하는 <x:param/> 태그의 형식은 다음과 같다.

Syntax

Syntax 1: value 속성에 파라메터 값이 지정된 경우

<x:param name="name" value="value"/>

 

Syntax 2: body 내용에 파라메터 값이 지정된 경우

<x:param name="name">

    parameter value

</x:param>

 

 

여기서 잠깐

<x:transform/> 태그를 사용할 때 jdk1.4 내에 있는 xalan jstl이 충돌을 일으킨다.

이런 경우, 톰캣 실행을 중지하고, jstl WEB-INF/lib디렉토리에 있는 xalan.jar 파일과 xercesImpl.jar 파일 두 개를 <CATALINA_HOME>/common/endorsed 디렉토리에 복사한다. 이전 버전의 xercesImpl.jar 파일을 덮어씌운다. 만일 이 과정이 생략되면, 다음과 같은 예외를 만나게 된다.

org.apache.xml.utils.WrappedRuntimeException: 

The output format must have a '{http://xml.apache.org/xslt}content-handler' property!

<x:transform/> 활용 예제를 보자.

예제 23.                         jstlxml03.jsp

<%@ page pageEncoding="MS949" %>

<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>

<%@ taglib prefix="x" uri="http://java.sun.com/jstl/xml" %>

 

<html>

<head>

  <title>JSTL: XML Support -- Transform</title>

</head>

<body bgcolor="#FFFFFF">

<c:set var="xml">

    <?xml version="1.0" encoding="MS949"?>

    <namecard>

        <person>

            <name>허광남</name>

            <id>남자</id>

            <email>kenu@email.com</email>

            <phone>111-2222-3333</phone>

        </person>

        <person>

            <name>노재춘</name>

            <id>남자</id>

            <email>suribada@email.com</email>

            <phone>222-3333-4444</phone>

        </person>

        <person>

            <name>이선재</name>

            <id>남자</id>

            <email>hsboy@email.com</email>

            <phone>333-4444-5555</phone>

        </person>

    </namecard>

</c:set>

 

<c:set var="xsl">

    <?xml version="1.0"?>

    <xsl:stylesheet

    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

        <xsl:template match="/">

        <table border="1">

            <tr>

                <th>이름  </th>

                <th>이메일</th>

                <th>연락처</th>

            </tr>

        <xsl:for-each select="namecard/person">

            <tr>

                <td><xsl:value-of select="name" /></td>

                <td><xsl:value-of select="email" /></td>

                <td><xsl:value-of select="phone" /></td>

            </tr>

        </xsl:for-each>

        </table>

        </xsl:template>

 

    </xsl:stylesheet>

</c:set>

 

<x:transform xml="${xml}" xslt="${xsl}"/>

 

</body>

</html>

 

 

jsp 소스 안에 있는 xml(예제 21. namecard.xml) xsl을 따로 파일로 빼놓으면 아래와 같이 바뀐다.

예제 24.                         namecard.xsl

<?xml version="1.0" encoding="euc-kr" ?>

<xsl:stylesheet

xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

    <xsl:template match="/">

    <table border="1">

        <tr>

            <th>이름  </th>

            <th>이메일</th>

            <th>연락처</th>

        </tr>

    <xsl:for-each select="namecard/person">

        <tr>

            <td><xsl:value-of select="name" /></td>

            <td><xsl:value-of select="email" /></td>

            <td><xsl:value-of select="phone" /></td>

        </tr>

    </xsl:for-each>

    </table>

    </xsl:template>

 

</xsl:stylesheet>

 

xsl 에 관한 문법적인 내용은 여기에서 다루지 않겠다.

namecard.xsl 파일은 namecard.xml html 을 입히는 역할을 하게 되며, 데이터를 제외한 html 틀을 갖고 있다고 볼 수 있다.

이 두 개의 파일을 하나로 합쳐서 html 코드를 만들어 내는 소스는 다음과 같다.

예제 25.                         jstlxml04.jsp

<%@ page pageEncoding="MS949" %>

<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>

<%@ taglib prefix="x" uri="http://java.sun.com/jstl/xml" %>

 

<html>

<head>

  <title>JSTL: XML Support -- Transform</title>

</head>

<body bgcolor="#FFFFFF">

<h1>연락처</h1>

<c:import var="xml" url="namecard.xml" charEncoding="MS949"/>

<c:import var="xsl" url="namecard.xsl" charEncoding="MS949"/>

 

<x:transform xml="${xml}" xslt="${xsl}"/>

 

</body>

</html>

 

jstlxml03.jsp 에서 <x:set/> 부분은 <c:import/> 로 바뀌었고, 파일을 불러올 때 charEncoding 속성을 통해서 인코딩해 주었다.

xml 변수와 xsl 변수 두 개를 파싱하지 않고 바로 <x:transform/> 을 통해서, jsp 파일에 출력했다.

<x:transform/> var 속성을 주면 출력되지 않고, 변수에 org.w3c.dom.Document 타입으로 저장된다.

 

 

이렇게 JSTL 4가지 표준 태그에 대해서 알아보았다. 프로그래밍의 기본인 조건, 반복, 연산이 가능하기 때문에 스크립틀릿을 거의 모두 제거할 수 있음을 알 수 있었다.

 

8           참고자료

JSTL 스펙

http://java.sun.com/products/jsp/jstl/

자카르타 taglibs

http://jakarta.apache.org/taglibs/doc/standard-doc/intro.html

Hans Bergsten article

JSTL 1.0: Standardizing JSP, Part 1

http://www.onjava.com/pub/a/onjava/2002/08/14/jstl1.html

JSTL 1.0: What JSP Applications Need, Part 2

http://www.onjava.com/pub/a/onjava/2002/09/11/jstl2.html

JSTL 1.0: What JSP Applications Need, Part 3

http://www.onjava.com/pub/a/onjava/2002/10/30/jstl3.html

JSTL in Action by Alex Garrett

http://www.codercoop.com/Members/alex_garrett/jstlnewapproach

XPath Tutorial

http://www.zvon.org/xxl/XPathTutorial/General/examples.html

XSL Tutorial

http://www.w3schools.com/xsl/

XSLT Tutorial

http://www.zvon.org/xxl/XSLTutorial/Books/Book1/



[1] http://ftp.ics.uci.edu/pub/ietf/http/related/iso639.txt

[2] http://userpage.chemie.fu-berlin.de/diverse/doc/ISO_3166.html


'프로그래밍 > Web' 카테고리의 다른 글

[javascript] DOM 스크립트  (0) 2010.01.15
[jstl] jstl 사용하기  (0) 2010.01.08
[jsp] jstl 설치  (0) 2010.01.08
[servlet] 서블릿에서 jsp로 포워드하기  (0) 2010.01.07
[javascript] addLoadEvent  (0) 2010.01.04

[jsp] jstl 설치

프로그래밍/Web 2010. 1. 8. 11:30 Posted by galad
출처: http://yangwenry.springnote.com/pages/198199

예) <%@ taglib prefix="c"  uri="http://java.sun.com/jstl/core"  %>

위와같이 JSP 파일에 선언해주면 되는데 하기전에 라이브러리 파일과 tld 파일을 설치해 줘야한다.

- JSTL 설치하기

1. JSTL 다운로드

JSTL 은 아래 두사이트에서 다운로드 할수있다.
  --> 여기서 다운로드를 해봤는데 모든 툴들이 하나로 통합되어 진거 같다.
        JSTL 만 따로 받고싶은 나로선 별로 내키진 않았다.

2) http://apache.org 
  --> 여기서는 jakarta-taglibs-standard-1.1.2.zip 파일을 받으면 된다.


2. 설치
  - WEB-INF/lib 디렉토리에 jstl.jar 와 standard.jar 파일을넣는다.
  - WEB-INF/tld 에다가 tld 폴더를 복사한다.

3. WEB.XML 설정
  --> 처음에 uri="http://java.sun.com/jstl/core" 라고 쓰는걸 보고 sun 에서 해당 url 을 지원해 주는줄 알았으나 그게 아니고 WEB.xml 파일에 아래와같이 설정해 줘야지 쓸수 있는것이다.


             <taglib>
                           <taglib-uri>http://java.sun.com/jstl/core</taglib-uri>
                           <taglib-location>/WEB-INF/tld/c.tld</taglib-location>
             </taglib>
 
             <taglib>
                          <taglib-uri>http://java.sun.com/jstl/xml</taglib-uri>
                          <taglib-location>/WEB-INF/tld/x.tld</taglib-location>
             </taglib>
 
             <taglib>
                           <taglib-uri>http://java.sun.com/jstl/fmt</taglib-uri>
                          <taglib-location>/WEB-INF/tld/fmt.tld</taglib-location>
             </taglib>


4. JSP 선언
  --> 위에서 말한것처럼 JSP 파일에는 아래와같이 선언해주면 된다.

<%@ taglib prefix="c"  uri="http://java.sun.com/jstl/core"  %>




- EL(expression language) 내장객체

 
pageScope  ::  page 범위에 포함된 속성 값에 접근
requestScope  ::  request 범위에 포함된 속성값에 접근
sessionScope ::  session 범위에 포함된 속성값에 접근
applicationScope  ::  application 범위에 포함된 속성값에 접근
param  ::  request.getParameter("aa")와 동일한 기능. 사용은  $(param.aa)
paramValues  ::  request.getParameterValues의 기능. $(paramValues.aa)
header  ::  request.getHeader('aa") 와 동일.  $(header.aa)
headerValues  ::  request.getHeaderValues("aa")와 동일 $(headerValues.aa)
initParam  ::  컨텍스트의 초기화 파라미터값
cookie  ::  쿠키 정보에 접근
pageContext  :: PageContext 객체   
 

'프로그래밍 > Web' 카테고리의 다른 글

[jstl] jstl 사용하기  (0) 2010.01.08
[jsp] jstl 설명  (0) 2010.01.08
[servlet] 서블릿에서 jsp로 포워드하기  (0) 2010.01.07
[javascript] addLoadEvent  (0) 2010.01.04
[jQuery] 브라우져 알아내기  (0) 2009.12.17

[java] 파일 관련

프로그래밍/Java 2010. 1. 7. 14:16 Posted by galad
출처: http://wearekorean.co.kr/zbxe/645

1. File 객체로 작업하기

        1> File 객체의 정의

                 * File객체는 하드디스크에 존재하는 실제 파일이나 디렉토리가 아니고 그것에 대한 경로(Pathname) 또는 참조(reFerence)를 추상화한 객체이다. 파일 객체는 새 파일에  대한 경로나 만들고자하는 디렉토리를 캡슐화한 것이다.

        2> File 객체의 용도

                 * 물리적 파일 시스템에 대해 캡슐화한 경로명을 확인하고 실제의 파일이나 디렉토리와 대응되는지 알아볼 때.

                 * 파일 스트림객체를 생성하고자 할 때.


2.  File 객체 생성하기

        1>File 객체를 생성하는 데에는 네 개의 생성자를 사용할 수 있다.

                * 인자로 String 객체를 전달하는 것.

                       File mtDir - new File("c:/j2SDK 1.4.0/src/java/io");

                       File 클래스의 생성자는 인자로 전달된 경로를 확인하지 않는다 .

                       File 클래스의 생성자로 어떤 문자열을 넘겨도 된다는 것을 알 수 있다.

                       File 객체는 불변적이므로 객체를 생성하고 나면 그것이 가진 경로를 바꿀 수 없다

                * 첫번째 인자로 부모 디렉토리를 가진 File객체 전달, 두번째 인자로 String객체 전달.

                  부모 디렉토리 - 해당 파일을 가지고 있는 디렉토리.

                * 첫번째 인자로 부모 디렉토리의 경로를 String객체로 전달, 두번째 인자로 String객체  전달.

                * URL이용.

        2>경로에 대한 이식성을 고려

                * 경로 이름을 만드는 것은 시스템에 의존적이지만 File 클래스의 separator 변수를 사용함으로써 좀 더 시스템에 독립적으로 myFile에 대한 경로를 지정 가능.

        3>절대경로와 상대경로

                * 절대 경로 : 접두사(c:\, c://)를 포함하는 경로.

                  ex) cd c:\java\API 이런 식의 경로 이동을 하는 방법이 절대 경로.

                * 상대 경로 : 접두사가 없는 경로.

                  ex) cd java 이런 식의 경로 이동을 하는 방법이 상대 경로.

        4>시스템 속성에 접근하기

                * 파일에 대한 상대 경로를 지정하는 것이 시스템 독립적이긴 하지만 현재의 환경에 독립적인 경로를 지정하고자 하는데, 현재 디렉토리 또는 현재 디렉토리의 하위 디렉토리는 데이터 파일을 저장하기에 적합하지 않은 상황도 있을 수 있다. 이런 경우에 시스템 속성에 접근하는 것이 도움이 될 수 있다.


3. File 객체를 확인하고 테스트하기

        1> File 객체에 대한 정보를 얻을 수 있는 메서드

                getName() - 경로를 제외한 파일의 이름. 즉, 경로의 가장 마지막 부분을 String 객체로 리턴한다.

                getPath() - 파일이나 디렉토리 이름을 포함한 File 객체의 경로를 String으로 리턴한다.

                isAbsolute() - File 객체가 절대경로를 참조하고 있다면 true, 아니라면 false를 리턴한다.

                getParent() - 현재 File 객체가 나태내는 파일 EH는 디렉토리의 부모 디렉토리의 이름을 String으로 리턴한다. 이때 리턴되는 경로는 파일 이름을 포함하지 않은 순수한 경로명이다. 만약 File 객체가 현재 디렉토리에서 단순히 파일 이름만을 사용해서 만들어져 부모 디렉토리가 명시되어 있지 않을 경우에는 null을 리턴한다.

                toString() - 현재 File 객체의 String표현을 리턴하며 File 객체가 String 객체로 변환될 필요가 있을 때 자동으로 호출된다.

                hashCode() - 현재 File 객체의 해시코드 값을 리턴한다.

                equals() - 두 개의 File 객체가 동일한 것인지 비교할 때 사용되는 메소드이다. 인자로 넘겨지는 File 객체가 현재의 객체와 같은 경로를 가지고 있으면 true를 그렇지 않으면 false를 리턴한다.

        2> File 객체가 참조하는 파일이나 디렉토리를 테스트하기 위한 메서드

                exist() - File 객체가 참조하는 파일 또는 디렉토리가 실제로 존재하면 true를, 그렇지않으면 false를 리턴한다.

                isDirectory() - File 객체가 디렉토리를 참조하는 경우 true를, 그렇지 않으면 false를 리턴한다.

                isFile() - File 객체가 파일를 참조하는 경우 true를, 그렇지 않으면 false를 리턴한다.

                isHidden() - File 객체가 숨김 속성이 있는 파일을 참조하는 경우 true를, 그렇지 않으면 false를 리턴한다.

                canRead() - File 객체가 참조하는 파일 또는 디렉토리를 읽을 권한이 있다면 true를, 없다면 false를 리턴한다. 만약 권한이 없는데 읽으려고 시도하면 SecurityException이 발생한다.

                canWrite() - File 객체가 참조하는 파일 또는 디렉토리에 쓰기 권한이 있다면 true를, 없다면 false를 리턴한다. 만약 권한이 없는데 읽으려고 시도하면 SecurityException이 발생한다.

                getAbsolutePath() - 현재의 File 객체가 참조하는 파일 또는 디렉토리의 절대경로를 리턴한다. 만약 객체가 절대경로를 포함하고 있다면 getPath() 메소드에 의해 리턴되는 것과 동일한 문자열을 리턴할 것이다. 그렇지  않다면 윈도우즈 환경에서는 현재 디렉토리가 나타내는 경로의 드 라이브 이름을 사용하거나 경로에 드라이브 이름이 명시되어 있지 않다면 현재 사용자 디렉토리에 대해서 절대경로가 결정된다. 유닉스 환경에서는 현재 사용자 디렉토리에 대해서 절대 경로가 결정된다.

                getAbsoluteFile() - 현재 File 객체가 참조하는 파일 또는 디렉토리의 절대경로를 포함한 File 객체를 리턴한다.

 

=======================================소스 코드=======================================

import java.io.File;

 

public class TryFile {
  public static void main(String[] args) {

 

    // 디렉토리를 참조하는 객체 생성
    File myDir = new File("C:/javaex1");
    System.out.println(myDir + (myDir.isDirectory() ? " is" : " is not") + " a directory.");

 

    // 파일을 참조하는 객체 생성
    File myFile = new File(myDir, "TryFile3.java");
    System.out.println(myFile + (myFile.exists() ? " does" : " does not") + " exist");
    System.out.println(myFile + (myFile.isFile() ? " is" : " is not") + " a file.");
    System.out.println(myFile + (myFile.isHidden() ? " is" : " is not") + " hidden");
    System.out.println("You can" + (myFile.canRead() ? " " : "not ") + "read " + myFile);
    System.out.println("You can" + (myFile.canWrite() ? " " : "not ") + "write " + myFile);
    return;
  }

}

 


=======================================소스 코드=======================================

 

        3> 존재하는 파일 또는 디렉토리에 대해 더 많은 정보를 제공해주는 메서드

                list() - 현재 File 객체가 디렉토리를 나태내고 있다면 디렉토리 내의 파일 이름과 하위 디렉토리의 이름들을 담고 있는 String 배열이 리턴된다. 만일 디렉토리가 비어 있다면 배열도 비어있을 것이다. 또한 File 객체가 파일을 나태내고 있다면 null을 리턴할 것이다. 이 메소드는 허가되지 않은 디렉토리를 접근하려 할 경우 SecurityException을 발생시킨다.

                listFiles() - 이 메소드를 호출한 객체가 디렉토리라면, 그 디렉토리 내의 파일과 하위 디렉토리에 대응되는 File 객체 배열이 리턴된다. 빈 디렉토리라면 빈 배열이 리턴될 것이다. 호출된 객체가 디렉토리가 아니거나 입출력 오류가 발생한다면 null을 리턴할 것이다. 이 메소드는 허가되지 않은 디렉토리에 접근하려 할 때 SecurityException을 발생시킨다.

                length() - 현재 File 객체가 참조하는 파일의 길이를 바이트 단위로 표현한 long 형의 값을 리턴한다. 현재 File 객체의 경로가 존재하지 않는 파일을 참조하고 있다면 0을 리턴할 것이다. 만약 그 경로가 디렉토리를 참조한다면, 정의되지 않은 값이 리턴된다.

                lastModified() - 현재 File 객체가 나타내는 파일 또는 디렉토리가 마지막으로 수정된 시각을 나타내는 long형의 값을 리턴한다. 이때 시각은 그리니치 표준시(GMT)로 1970년 1월 1일 자정 이후로부터 지난 시간을 멀리 초 단위로 계산한 값이다. 파일이 존재하지 않는다면 0을 리턴한다.

 

=======================================소스 코드=======================================

import java.io.File;
import java.util.Date;   // Date 클래스를 사용하기 위해 포함시킴
 
public class TryFile2 {
  public static void main(String[] args) {
 
    // 디렉토리를 참조하는 객체 생성
    File myDir = new File("C:/javaex1");
    System.out.println(myDir.getAbsolutePath()  + (myDir.isDirectory() ? " is " : " is not ") + "a directory");
    System.out.println("The parent of " + myDir.getName() + " is " + myDir.getParent());
 
    // 디렉토리 내의 파일 리스트를 얻어옴
    File[] contents = myDir.listFiles();
 
    // 파일 리스트를 출력
    if (contents != null) {
      System.out.println("\nThe " + contents.length + " items in the directory " + myDir.getName() + " are:");
      for (int i = 0; i < contents.length; i++) {
        System.out.println(contents[i] + " is a "  + (contents[i].isDirectory() ? "directory" : "file") + " last modified " 
                   + new Date(contents[i].lastModified()));
      }
    } else {
      System.out.println(myDir.getName() + " is not a directory");
    }
 
    System.exit(0);
  }
}
 

=======================================소스 코드=======================================

 

        4> 파일 리스트 필터링

                * list()와 listFiles() 메서드는 파일 리스트를 필터링하는 인자를 받도록 오버로드 되어 있다.

                * list() 메서드의 인자는 FilenameFilter 타입의 변수여야 하지만,

                * listFiles() 메서드는 FilenameFilter와FileFilter 두 가지를 모두 사용할 수 있다.

 

4. 파일과 디렉토리를 생성하고 수정하기

        File 클래스에는 그 파일을 읽기 전용으로 만들거나 이름을 바꾸는 등 물리적인 파일에 변화를 줄 수 있는 메서드가 있다. 또한 파일 또는 디렉토리를 생성하거나 삭제할 수 있게 해주는 메서드들도 있다.

                renameTo(File path) - 현재 객체가 나타내는 파일의 이름이 메소드의 인자로 전달된 File 객체가 나타내는 경로를 변경될 것이다. 이것은 프로그램에서 현재의 File 객체를 변경하는 것이 아니라 물리적인 파일을 실제로 바꾸는 것이라는 점을 주의해야 한다. 따라서 현재 File 객체가 나타내던 파일은이 메소드가 수행되고 나면 새로운 이름을 가지게 되므로 더 이상 존재하지 않을 것이며 다른 디렉토리에 위치하게 될 수도 있다. 새로운 경로에 있는 파일의 디렉토리가 원래의 것과 다르다면 파일은 새로운 디렉토리로 옮겨질 것이다. 만일 새로운 경로가 존재하지 않는 디렉토리이거나 그 곳에 쓰길을 할 수 없다면 이 메소드는 실패할 것이다. 이 메소드는 작업이 성공적으로 이루어지면 true를 리턴하고, 그렇지 않으면 false를 리턴한다.

                setReadOnly() - 현재 객체가 나타내는 파일을 읽기 전용으로 설정한다. 성공하면 true를 리턴한다.

                mkdir() - 현재의 File 객체에 의해 지정된 경로로 디렉토리를 생성한다. 이 메소는 생성하려는 디렉토리의 부모 디렉토리가 미리 존재하지 않으면 실패할 것이다. 이 메소드는 성공하면 true를 리턴하고, 그렇지 않으면 false를 리턴한다.

                mkdirs() - 현재 File 객체가 나타내는 디렉토리를 생성하며, 이때 필요한 모든 부모 디렉토리도 함께 생성한다. 새로운 디렉토리가 성공적으로 생성되었다면 true를 그렇지 않으면 false를 리턴한다. 메소드가 false를 리턴한 경우에도 부모 경로 중 일부가 생성되었을 수도 있다.

                createNewFile() - 현재 File 객체로 정의돈 경로에 비어있는 새로운 파일을 생성한다. 파일이 성공적으로 생성되면 true를 리턴한다. 경로에 지정된 디렉토리가 존재하지 않는다면 IOException 예외가 발생하고, 지정된 파일이 이미 존재한다면 실패한다.

                createTempFile(String prefix, String suffix, File directory) - 이것은 directory 디렉토리에 처음 두 개의 인자를 사용해서 생성된 이름으로 임시 파일을 생성하는 정적 메소드이고, 생성된 파일에 해당하는 File 객체를 리턴한다. 문자열 prefix는 파일 이름의 앞부분을 나타내며 최소한 세 글자 이상은 되어야 한다. 문자열 suffix는 파일의 확장자를 나타낸다. 파일 이름이 prefix와 다섯자 이상은 생성된 문자, 그리고 확장자로 이루어진다. 만약 suffix가 null이라면 확장자는 .tmp 가 될 것이다. prefix나 suffix가 현재 시스템의 파일 이름으로 쓰기에 너무 길다면 끝 부분을 잘라내고 사용하지만, 세 글자 이하로 잘라내지는 않는다. directory 인자가 null이라면 시스템의 임시 디렉토리가 사용될 것이다. 만일 파일이 생성될 수 없다면 IOEception이 발생하며 prefix가 세글자 이하라면 IllegalArgument Exception이 발생할 것이다.

                createTempFile(String prefix, String suffix) - createTempFile(String prefix, String suffix, File directory)와 동일하다.

                delete() - 현재 File 객체가 나타내고 있는 파일 또는 디렉토리를 삭제하며 성공적으로 삭제되었다면 true를 리턴한다. 이 메소드는 비어있지 않은 디렉토리는 지우지 않는다. 그러므로 디렉토리를 삭제하려면 디렉토리 내의 모든 파일을 먼저 지워야 한다.

                deleteOnExit() - 현재 File 객체가 나타내는 파일 또는 디렉토리가 프로그램이 끝날 때에 삭제 되도록 한다. 이 메소드는 값을 리턴하지 않으며, 삭제는 JVM이 정상적으로 종료될 경우에만 시도된다. 일단 File 객체에 대해서 이 메소드를 호출하면 삭제 작업은 돌이킬 수 없기 때문에 주의해서 사용해야 한다.

5. 파일 출력 스트림 생성하기

        디스크에 존재하는 물리적인 파일에 무언가 쓰고자 할 때 FileOutputStream 객체를 사용할 수 있다.

         1>FileOutputStream 객체의 다섯 개의 생성자

                FileOutputStream(String filename) - filename이라는 이름의 파일에 대한 출력 스트림을 생성한다. 파일에 이미 존재하는 내용을 덮어쓰게 된다. 어떤 이유로든 파일이 열리지 않는다면 FileNotFoundException이 발생한다.

                FileOutputStream(String filename, boolean append) - filename이라는 이름의 파일에 대한 출려 스트림을 생성하며, 만약 append인자 값이 true이고 파일 내용이 존재한다면 그 내용 뒤에 덧붙여 쓴다. append인자 값이 false라면 이미 존재하는 파일의 내용을 덮어쓰게 된다. 어떤 이유로든 파일이 열리지 않는다면 FileNotFoundException이 발생한다.

                FileOutputStream(File file) - File 객체가 나타내는 파일에 대한 출력스트림을 생성하며, 이미 파일 내용이 존재하면 그 내용을 덮어쓴다. 어떤 이유로든 파일이 열리지 않는다면 FileNotFoundException이 발생한다.

                FileOutputStream(File file, boolean append) - File 객체가 나타내는 파일에 대한 출력 스트림을 생성하며, 만약 append 인자 값이 true이고 파일 내용이 이미 존재한다면 그 내용 뒤에 덧붙여 쓴다. 어떤 이유로든 파일이 열리지 않는다면 FileNotFoundException이 발생한다.

                FileOutputStream(FileDescriptor desc) - desc와 해당하는 출력 스트림을 생성한다. FileDescriptor 객체는 파일에 대해 이미 존재하고 있는 연결을 참조한다. 그래서 파일이 반드시 존재하므로 이 생성자는 FileNotFoundException이 발생한다.

  

6. 파일이 존재하는 것을 보장하기

        1> 파일이 존재하면 이 파일에 데이터를 덧붙이고 존재하지 않는 파일이면 생성하고자 할 때 파일 출력 스트림을 생성해야하는데, 여기서 확인해야 할 것들이 있다.

        2> File 객체를 사용해서 실제로 디렉토리가 아니라 파일을 나타내고 있는지 확인한다. 만일 파일이 아니라면 더 이상 진행하지 말고 오류 메시지를 출력해 주어야 한다.

        3> 그 파일이 존재하는지 확인하기 위해 File 객체를 사용한다. 파일이 존재하지 않는다면 File 객체가 절대경로를 가지고 있는지 확인해야 한다. 이것은 부모 디렉토리를 얻어오고 확인하는 데 사용된다.

        4> 부모 디렉토리에 대한 경로를 얻어오고 이것을 사용해서 다른 File 객체를 생성한다. 부모 디렉토리가 존재하는지 확인하기 위해 새로운 File 객체를 사용한다. 만약 존재하지 않는다면 File 객체의 mkdir() 메서드를 사용해서 새로 생성한다.

 

=======================================소스 코드=======================================

import java.io.File;
import java.io.FileOutputStream;
import java.io.FileNotFoundException;

public class GuaranteeAFile {
  public static void main(String[] args) {
    String filename = "C:/Beg Java Stuff/Bonzo/Beanbag/myFile.txt";
    File aFile = new File(filename);    //File 객체 생성

    //경로가 파일인지를 확인
    if (aFile.isDirectory()) {

      // 오류 메세지 후에 종료함

      // 여기서 키보드로부터 입력을 받아 다시 시도하도록 할 수 있음
      System.out.println("The path " + aFile.getPath() + " does not specify a file. Program aborted.");
      System.exit(1);
    }

    // 파일이 존재하지 않을 경우
    if (!aFile.isFile()) {
      // 부모 디렉토리를 확인
      aFile = aFile.getAbsoluteFile();
      File parentDir = new File(aFile.getParent());
      if (!parentDir.exists()) {   // ... and create it if necessary
        parentDir.mkdirs();
      } 
    }

    // 스트림에 대한 참조를 저장할 장소
    FileOutputStream outputFile = null; 
    try {

      // 데이터를 추가하는데 사용될 스트림 생성
      outputFile = new FileOutputStream(aFile, true);
    } catch (FileNotFoundException e) {
      e.printStackTrace(System.err);
    } 
    System.exit(0);
  } 
}

=======================================소스 코드=======================================

 

7. 파일 덮어쓰는 것을 방지하기

        * 이미 파일이 존재할 때 그 파일을 덮어쓰고 싶을 않을 때 덮어쓰기를 막을 수 있는 방법이 있다. 저장하려는 원래 이름을 어떠한 방법으로든 바꿔준다면 그것이 덮어쓰기를 막을 수 있는 한 가지 방법이 될 수 있다.

 

=======================================소스 코드=======================================

import java.io.File;
import java.io.FileOutputStream;
import java.io.FileNotFoundException;

 
public class AvoidOverwritingFile {
  public static void main(String[] args) {
    String filepath = "C:/Beg Java Stuff/myFile.txt";
    File aFile = new File(filepath);
    FileOutputStream outputFile = null;     // 스트림에 대한 참조를 저장할 장소
    if (aFile.isFile()) {
      File newFile = aFile;                 // 원래의 파일을 가지고 시작함
     
      // 유일한 이름이 될 때까지 파일 이름에 "_old"를 덧붙임
      do {
        String name = newFile.getName();    // 파일의 이름을 얻어옴
        int period = name.indexOf('.');         // 확장자의 구분자를 찾음
        newFile = new File(newFile.getParent(), name.substring(0, period) + "_old" + name.substring(period));
      } while (newFile.exists());             // 이름이 바뀔 때까지 반복
      aFile.renameTo(newFile);               
    }
 
    // 새로운 파일 생성
    try {
      // 데이터를 추가하기 위한 스트림 생성
      outputFile = new FileOutputStream(aFile);
      System.out.println("myFile.txt output stream created");
    } catch (FileNotFoundException e) {
      e.printStackTrace(System.err);
    } 
    System.exit(0);
  }
}
 
 

=======================================소스 코드=======================================


8. FileDescriptor 객체

        1> FileDescriptor 객체

                * FileOutputStream에는 FileDescriptor 타입의 객체를 리턴해주는 getFD() 메서드가 있다.

                * 여기서 FileDescriptor는 물리적인 파일에 대한 현재의 연결을 나타내는 객체이다.

                * 직접 FileDescriptor 객체를 생성할 수는 없고 파일 스트림을 나타내는 객체로부터 getFD() 메서드를 호출해서 FileDescriptor 객체를 얻을 수 있다

                * 스트림을 한번 닫고 나면 파일에 대한 연결이 끊어지므로 더 이상 FileDescriptor 객체를 얻을 수 없다

        2> FileDescriptor 객체 사용

                * 표준 스트림에 대응되는 바이트나 문자 스트림을 만들고자 할 때 편리하게 사용할 수 있다

 

 

<요약>


1> File클래스의 객체는 파일 또는 디렉토리의 경로를 포함한다. File 객체가 가지고 있는 경로는 물리적인 파일이나 디렉토리와 반드시 대응되어야 할 필요는 없다.

2> File 객체가 가지고 있는 경로가 실제의 파일이나 디렉토리를 참조하는지를 확인하기 위해 File객체를 사용할 수 있다. 만약 실제 파일이나 디렉토리를 참조하고 있지 않은 경우 필요한 디렉토리나 파일을 생성할 수 있는 메소드들이 있다.

3> File클래스는 임시 파일을 생성할 수 있는 정적 메소드를 가지고 있다.

4> FileDescriptor 타입의 객체도 물리적인 파일을 나타낼 수 있다.

5> FileOutputStream 객체는 File 객체로부터 생성될 수 있으며, 쓰기 위해 파일이 열린다. 만약 파일이 존재하는 않는다면 가능한 곳에 새로 생성된다.


'프로그래밍 > Java' 카테고리의 다른 글

[java] getClass, getMethod, invoke  (0) 2010.01.22
[java] Pattern / Matcher  (0) 2010.01.22
[java] thorws .....  (0) 2009.12.11
[java] 소스 분석  (0) 2009.09.06
[HttpURLConnection] POST로 파라미터 넘기기  (0) 2009.07.27
public class FileBrowsingAction extends HttpServlet {

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //super.service(request, response); // 없어야됨. 있으면 슈퍼클래스에서 응답처리됨.
       
        // 파일 목록 얻기
       
       
        String jspName = "/file_browsing.jsp";
       
        getServletConfig().getServletContext().getRequestDispatcher(jspName).forward(request,response);
    }
}

서블릿도 안쓰다보니 까먹었다.

'프로그래밍 > Web' 카테고리의 다른 글

[jsp] jstl 설명  (0) 2010.01.08
[jsp] jstl 설치  (0) 2010.01.08
[javascript] addLoadEvent  (0) 2010.01.04
[jQuery] 브라우져 알아내기  (0) 2009.12.17
[jQuery] jQuery로 현재 페이지에서 스크롤된 높이 알아내기  (0) 2009.12.17

[javascript] addLoadEvent

프로그래밍/Web 2010. 1. 4. 16:29 Posted by galad
출처: http://simon.incutio.com

function addLoadEvent(func) {
    var oldonload = window.onload;

    if(typeof window.onload != 'function') {
        window.onload = func;
    }
    else {
        window.onload = function() {
            oldonload();
            func();
        };
    }
}

addLoadEvent(functionA);

기존의 함수(oldonload)와 새 함수(func)를 모두 실행하는 무명함수를 window.onload에 attach.
addLoadEvent(함수명)이 실행될때마다 계속 초기에 실행되는 함수가 증가.

[jQuery] 브라우져 알아내기

프로그래밍/Web 2009. 12. 17. 15:43 Posted by galad
var m_browser;
var m_version;

function detectBrowser() {
    if($.browser.msie) {
        m_browser = "msie";
    }
    else if($.browser.safari) {
        m_browser = "safari";
    }
    else if($.browser.opera) {
        m_browser = "opera";
    }
    else if($.browser.mozilla) {
        m_browser = "mozilla";
    }

    m_version = $.browser.version;

    //alert(m_browser + " " + m_version);
}

$.browser.mozilla
$.browser.version

http://visualjquery.com/ 여기서 Utilites > User Agent 참고
$(window).scrollTop()

간단하군....
div에다가 createElement로 노드들을 추가하면 div의 높이가 변하는게 당연해 보이는데 - IE6에서는 변한다
Firefox, Crome 등의 브라우저에서는 초기에 설정된 값이 변하지 않는다.

여기저기 뒤져서
1. html, body, div의 height를 100%로 주면 된다 - http://www.webmasterworld.com/forum83/200.htm
  하지만 이건 창 크기가 변할 때 쓰는 듯하고.(element가 추가되는 경우에는 제대로 div가 커지지 않았음)

2. min-height를 주면 된다 - http://forum.standardmag.org/viewtopic.php?id=2239
  안된다 ㅠ.ㅠ

등의 글을 참고했지만 안됨...

모르겠음 ㅠ.ㅠ

그냥 추가되는 노드의 수 만큼 직접 height를 수정하는게 나을 듯.
출처: http://srchun.springnote.com/pages/4799503

브라우저 별로 크기가 다르다는 얘기..

scrollHieght 찾다가 나왔음...
        var el = document.createElement("span");
        el.setAttribute("title", key);
        el.setAttribute("class", "dpCatLabel");
      //el.setAttribute("onclick", "alert('TEST');"); // DOESN'T WORK. onclick is not attribute.
      el.onclick=function(){alert("TEST");};
        var txt = document.createTextNode(label);
        el.appendChild(txt);

onclick 등은 이벤트라서 setAttribute로 붙일 수 없고,
el.onclick=function;  으로 붙이자.

[jQuery] jQuery를 이용한 ajax

프로그래밍/Web 2009. 12. 16. 11:20 Posted by galad
function ajaxGetDpCatList() {
    //alert("ajax로 전체 전시 카테고리 정보 얻기");
    //alert($(this).attr("title"));
   
    var selectedCatId = $(this).attr("title");
    $("#selectedCatId").val(selectedCatId);
    //alert($("#selectedCatId").val());
   
    $.ajax({
        url: '${pageContext.request.contextPath}/categoryMapping/getDpCatList.omp',
        type: 'POST',
        dataType: 'json',
        timeout: 5000,
        error: function(){
            alert('전시 카테고리 정보를 얻는 중에 오류가 발생했습니다.');
        },
        success: function(data){
            //alert(data);
            //alert(data.dpCatList[0].key + " " + data.dpCatList[0].value);
            showDpCatList(data);
        }
    });
}

- json 형식으로 결과를 받겠다 해놓고, 결과가 json형식에 안맞아도 error.
- timeout 시간이 넘어가도 error. 처음엔 개발장비서 할 떄 계속 에러나서 원인을 못찾았었음. 주의할 것.

$.ajax외에도 $.post 같은 좀 더 간단한 jQuery 메소드가 있음.
http://www.ibm.com/developerworks/kr/library/wa-jquery3/

[javascript] HTML DOM 지우기

프로그래밍/Web 2009. 12. 16. 10:25 Posted by galad
createElement로 생성한 노드들을 지울때, 특정 노드 밑에 딸린 노드들을 몽창 한번에 지우는 메소드가 없는 건지 못찾은 건지,
아무튼 parentNode에 딸린 노드들을 전부 찾아서(getElementsByTag), for 루프 돌면서 지우는데 절반만 지워져서 헤매다가 원인을 찾았음

function deleteNodes(parentNode, tag) {
    var nodes = parentNode.getElementsByTagName(tag);
    var length = nodes.length;
    
    // 이건 nodes가 실시간으로 줄어들면서 length 자체가 줄어든다.
    // 따라서 아래의 for문에서 기존 nodes의 갯수만큼 루핑하면서 0번만 계속 지움.
    // i번을 삭제하면 stack overflow 남
    /*for(var i = 0; i < nodes.length; i++) {
        var node = nodes[i];
        parentNode.removeChild(node);
    }*/
    
    for(var i = 0; i < length; i++) {
        var node = nodes[0];
        parentNode.removeChild(node);
    }
}

위에 써놓은 것처럼

for(var i = 0; i < nodes.length; i++) {
    var node = nodes[i];
    parentNode.removeChild(node);
}

nodes.length로 한계치를 정하면 for 문 안에서 자식 노드를 하나씩 지울 때마다 nodes.length 가 하나씩 줄어든다. 실시간 반영?!
그래서 length를 따로 저장하고 맨 처음 것만 계속 지웠음.

'프로그래밍 > Web' 카테고리의 다른 글

[javascript] HTML DOM 생성 후 이벤트 추가  (0) 2009.12.16
[jQuery] jQuery를 이용한 ajax  (0) 2009.12.16
[jQuery] jQuery를 이용한 팝업. div, layer  (0) 2009.12.16
[json] json 사용법  (0) 2009.12.15
[html] html 특수기호  (3) 2009.09.08
출처: http://whdrnr01.textcube.com/7?t=c&i=0

jQuery를 이용해서, div의 설정 변경을 통한 레이어 팝업.
ajax랑 함께 쓰면, ajax를 이용해서 데이터를 얻어온 후, div의 안에 원하는 형태로 데이터를 넣고 나서 보여주는 형식이 될 듯.

소스출처: http://yensdesign.com/tutorials/popupjquery/

/**
 * jQuery를 이용한 초기 설정
 */
$(document).ready(function() {
    // 마우스 오버 시 배경색 반전
    $(".catLabel1").hover(
        function() { // hover 시
            $(this).css({"background-color":"yellow", "font-weight":"bolder" });
        },
        function() { // out 시
            $(this).css({"background-color":"white", "font-weight":"normal" });
        }
    );

    $(".catLabel2").hover(
            function() { // hover 시
                $(this).css({"background-color":"yellow", "font-weight":"bolder" });
            },
            function() { // out 시
                $(this).css({"background-color":"white", "font-weight":"normal" });
            }
        );
   
    // 표준분류 선택 시 전시 카테고리 목록을 표시한다.
    $(".catLabel1").click(showAlert);
    $(".catLabel2").click(ajaxGetDpCatList);
   
    //CLOSING POPUP
    //Click the x event!
    /*$("#popupContactClose").click(function(){
        disablePopup();
    });*/
    //Click out event!
    $("#backgroundPopup").click(function(){
        disablePopup();
    });
    //Press Escape event!
    $(document).keypress(function(e){
        if(e.keyCode==27 && popupStatus==1){
            disablePopup();
        }
    });
});

/**
 * 표준 분류의 대분류 선택 시 경고 메시지
 */
function showAlert() {
    alert("표준 카테고리의 중분류를 선택해 주세요.");
}

/**
 * ajax로 전시 카테고리 목록 얻어오기
 */
function ajaxGetDpCatList() {
    //alert("ajax로 전체 전시 카테고리 정보 얻기");
    //alert($(this).attr("title"));
   
    var selectedCatId = $(this).attr("title");
    $("#selectedCatId").val(selectedCatId);
    //alert($("#selectedCatId").val());
   
    $.ajax({
        url: '${pageContext.request.contextPath}/categoryMapping/getDpCatList.omp',
        type: 'POST',
        dataType: 'json',
        timeout: 5000,
        error: function(){
            alert('전시 카테고리 정보를 얻는 중에 오류가 발생했습니다.');
        },
        success: function(data){
            //alert(data);
            //alert(data.dpCatList[0].key + " " + data.dpCatList[0].value);
            showDpCatList(data);
        }
    });
}

/**
 * 전시 카테고리 목록 표시
 */
function showDpCatList(data) {
    //alert($("#selectedCatId").val());
    //alert(data.dpCatList.length);

    var dpCatListPopup = document.getElementById("dpCatListPopup");

    // dpCatListPopup 의 내용을 비움. 안하면 계속 늘어남
    deleteNodes(dpCatListPopup, "span");
    deleteNodes(dpCatListPopup, "br");

    // 전시 카테고리 표시용 목록 만들기
    var list = data.dpCatList;
    for(var i = 0; i < list.length; i++) {
        var key = list[i].key;
        var label = list[i].value;

        var el = document.createElement("span");
        el.setAttribute("title", key);
        el.setAttribute("class", "dpCatLabel");
        //el.setAttribute("onclick", "alert('TEST');"); // DOESN'T WORK. onclick is not attribute.
        el.onclick=function(){alert("TEST");};
        var txt = document.createTextNode(label);
        el.appendChild(txt);

        dpCatListPopup.appendChild(el);
        dpCatListPopup.appendChild(document.createElement("br"));
    }

    setPopupPosition();
    loadPopup();
}

function deleteNodes(parentNode, tag) {
    var nodes = parentNode.getElementsByTagName(tag);
    var length = nodes.length;
   
    // 이건 nodes가 실시간으로 줄어들면서 length 자체가 줄어든다.
    // 따라서 아래의 for문에서 기존 nodes의 갯수만큼 루핑하면서 0번만 계속 지움.
    // i번을 삭제하면 stack overflow 남
    /*for(var i = 0; i < nodes.length; i++) {
        var node = nodes[i];
        parentNode.removeChild(node);
    }*/
   
    for(var i = 0; i < length; i++) {
        var node = nodes[0];
        parentNode.removeChild(node);
    }
}

//0 means disabled; 1 means enabled;
var popupStatus = 0;

/**
 * set popup position
 */
function setPopupPosition(){
    var windowWidth = document.documentElement.clientWidth;
    var windowHeight = document.documentElement.scrollHeight; //clientHeight;
    var popupHeight = $("#dpCatListPopup").height();
    var popupWidth = $("#dpCatListPopup").width();
   
    //centering
    $("#dpCatListPopup").css({
        "position": "absolute",
        "top": 0, //windowHeight/2-popupHeight/2,
        "left": windowWidth/2-popupWidth/2
    });

    //only need force for IE6
    $("#backgroundPopup").css({
        "height": windowHeight
    });
   
}

function loadPopup(){
    //loads popup only if it is disabled
    if(popupStatus==0){
        $("#backgroundPopup").css({
            "opacity": "0.7"
        });
        $("#backgroundPopup").fadeIn("slow");
        $("#dpCatListPopup").fadeIn("slow");
        popupStatus = 1;
    }
}

function disablePopup(){
    //disables popup only if it is enabled
    if(popupStatus==1){
        $("#backgroundPopup").fadeOut("slow");
        $("#dpCatListPopup").fadeOut("slow");
       
        popupStatus = 0;
    }
}

setPopupPosition() 으로 위치 설정.
loadPopup() 으로 보이기
disablePopup() 으로 숨기기

backgroundPopup 랑 dpCatListPopup 는 div의 id.

'프로그래밍 > Web' 카테고리의 다른 글

[jQuery] jQuery를 이용한 ajax  (0) 2009.12.16
[javascript] HTML DOM 지우기  (0) 2009.12.16
[json] json 사용법  (0) 2009.12.15
[html] html 특수기호  (3) 2009.09.08
[servlet] servlet  (0) 2009.09.04

[json] json 사용법

프로그래밍/Web 2009. 12. 15. 11:23 Posted by galad
출처: http://mogaji.springnote.com/pages/314716

{"payCodeList":
        [
            {"key":"PD00290","value":"무료"},
            {"key":"PD00292","value":"기간정액제"}
        ]
}

key:value 쌍만으로는 안될때는 이런 식으로...

아래는 위의 출처 내용을 보관을 위해 발췌했음.

JSON은 무엇인가?

  1. JSON은 무엇인가?
    • 경량의 데이타 교환 포맷이다.
      > XML과 비교한다.
    • 간단한 포맷
      > 사람들을 위해 읽고 쓰기가 쉽다.
      > 기계들을 위해 분석과 생성이 쉽다.
    • JSON은 텍스트 포맷이다.
      > 언어에 독립적으로 프로그래밍된다.
      > 프로그래머들에게 잘 알려진 C,C++,C#,Java,JavaScript,Perl,Pyton을 포함하는 C와 유사한 언어로 모여서 사용된다.

  2. XML을 넘어 왜 JSON인가?
    • on-the-wire(선을 통한) 데이타 포맷인 XML보다 가볍고 빠르다.
    • JSON 오브젝트는 XML 데이타가 타입이 없는데 비해 타입을 가진다.
      > JSON types : string, number, array, boolean
      > XML 데이타는 모두 String 이다.
    • JavaScript 코드를 위해 Native 코드포맷이다.
      > Data는 사용자의 JavaScript코드 안에서 JSON 객체에 접근이 쉽다.
      XML 데이타가 해석과 장황한 DOM API를 통해 변수에 접근하는 것을 필요로 하는데 비해
      > 회수한 값들은 사용자의 자바스크립트 안의 객체속성에서 읽기가 쉽다.

  3. JSON은 어디에서 사용되는가?
    • 구성정보를 나타낸다.
    • 통신 프로토콜을 실행한다.

JSON Object

  1. JSON 구조
    • name/value 쌍으로 구성된다.
      > 여러가지의 언어들에서 object, record, struct, dictionary, hashtable, 키를 가지는 리스트, 배열집합 처럼 얻어진다.
    • 값들이 리스트는 순서가 있다.
      > 대부분의 언어들에서 array, vector, list, sequence 처럼 얻어진다.
    • JSON은 대부분의 지금의 언어를 통해 일반적인 데이타구조들이 지원된다.

  2. JSON Object 표기법
    • JSON Object는 name/value 쌍의 set은 순서가 없다.
    • JSON Object는 { 로 시작하고 } 로 끝난다.
    • 각각의 이름은 : 와 ,로 구분된 name/value 쌍의 형식을 따른다.

  3. JSON과 JavaScript
    • JSON은 JavaScript의 객체 문자 표기의 부분집합이다.
      > JSON은 JavaScript안에서 혼란스럽거나 야단스럽지 않게 사용될 수 있다.

  4. JSON Object 예제
     
    var myJSONObject = {"bindings": [
    {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"},
    {"ircEvent": "PRIVMSG", "method": "deleteURI", "regex": "^delete.*"},
    {"ircEvent": "PRIVMSG", "method": "randomURI", "regex": "^random.*"}
    ]
    };
    • 위의 예에서, JSON JavaScript 객체는 세개의 객체를 포함한 배열을 갖고있는, 각각은 "ircEvent","method","regex" 멤버들을 포함한 하나의 멤버 "bindings"를 포함하여 생성된다.
    • 멤버들은 점(.) 이나 그아래 지시자들로 회수 할수 있다.
       
      myJSONObject.bindings[0].method // "newURI"
  5. JavaScript 코드안에서 Text를 Object로 변환하기
     
    var myObject = eval('(' + myJSONtext + ')');
    • eval() 함수를 사용하여, JSON text를 JSON 객체로 변환한다.
      > eval()은 JavaScript 컴파일러에서 실행한다.
      > JSON은 JavaScript의 서브셋으로 적합하다. 컴파일러는 text를 정확하게 변환하고, 객체 구조를 만든다.

  6. 보안 & JSON Parser
    // Include http://www.json.org/json.js
    var myObject = myJSONtext.parseJSON();
    • eval()은 컴파일 할 수 있고, 어떤 JavaScript 프로그램에서도 실행된다. 그래서 보안 이슈들(cross-site scripting)을 가질 수 있다.
      > 소스를 신뢰할 수 있을때, eval()을 사용해라.
    • 보안이 염려될 때 - 소스를 신뢰할 수 없을때 - JSON parser를 사용하는게 낫다.
      > JSON parser는 JSON text를 승인할 수 있다. 그래서 좀더 안전하다.

  7. Object를 Text로 변환하기
     
    var myJSONText = myObject.toJSONString();
    • 사용자는 JSON 객체를 JSON text로 변환할 수 있다.
    • JSON은 주기적 데이타 구조를 지원하지 않는다.

      > Do not give cyclical structures to the JSON stringifier
      > 주기적 구조들을 JSON stringfier로 줄수 없다

Java 안에서의 JSON

  1. 자바 개발자를 위한 JSON Tools
    • Parser
      > JSON text 파일들을 해석하고, 그들을 자바 모델로 변환한다.
    • Renderer
      > 자바를 text로 표현하게 한다.
    • Serializer
      > 알기쉬운 POJO clusters를 JSON 표현으로 나열한다.
    • Validator
      > JSON 스키마를 사용하여 JSON 파일의 내용을 유효한지 체크한다.

  2. JSONObject 자바 클래스
    • JSONObject의 name/value 쌍의 집합은 순서가 없다.
    • put 메소드는 객체로 name/value쌍을 add 한다.
    • text들은 JSON syntax rules을 정확히 따른 toString 메소드에 의해 만들어진다.
       
      myString = new JSONObject().put("JSON", "Hello, World!").toString();
      // myString is {"JSON": "Hello, World"}

클라이언트와 서버사이드 양쪽에서 JSON 데이타를 주고 받는 방법

  1. 서버사이드에서 JSON 데이타를 생성하고 보내는 방법
    • JSONObject 자바 객체를 생성한다.
    • put 메소드를 사용하여 name/value 쌍을 add한다.
    • toString 메소드를 사용하여 String 타입으로 변환한다.
      그리고 "text/xml" 또는 "text/plain" 처럼 content-type과 함께 클라이언트로 보낸다.
       
      myString = new JSONObject().put("JSON",toString();
      // myString is {"JSON": "Hello, World"}
  2. 클라이언트 사이드에서 JSON 데이타를 받는 방법
    • JSON 데이타는 String 처럼 반환된다.
    • JavaScript 코드안에서 JSON 객체를 만들수 있게 eval()을 호출한다.
      > var JSONdata = eval(req.response.Text);
    • 사용자는 한번 JSON 객체를 가질수 있고, 객체의 속성들에 접근하기 위해 . 을 사용할 수 있다.
       
      var name = JSONdata.name;
      var address = JSONdata.addresses[3];
      var streetname = JSONdata.addresses[3].street;
    • 클라이언트 사이드에서 JSON 데이타를 생성하고 보내는 방법
    • JSON 자바스크립트 객체를 생성한다.
    • XMLHttpRequest객체의 open 메소드 안에 "POST" HTTO 메소드를 사용한다.
    • XMLHttpRequest객체의 send 메소드안에서 JSON 자바스크립트 객체를 패스한다.
       
      var carAsJSON = JSON.stringify(car);
      var url = "JSONExample?timeStamp=" + new Date().getTime();
      createXMLHttpRequest();
      xmlHttp.open("POST", url, true);
      xmlHttp.onreadystatechange = handleStateChange;
      xmlHttp.setRequestHeader("Content-Type",
      "application/x-www-form-urlencoded");
      xmlHttp.send(carAsJSON);
  3. 서버사이드에서 JSON 데이타를 받는 방법
    • String 타입처럼 JSON데이타를 읽는다.
    • string으로부터 JSONObject 자바객체를 생성한다.
       
      String json = readJSONStringFromRequestBody(request);
      //Use the JSON-Java binding library to create a JSON object in Java
      JSONObject jsonObject = null;
      try {
      jsonObject = new JSONObject(json);
      }
      catch(ParseException pe) {
      }

리소스들

  1. JSON 리소스들
    • Introducing JSON
    > http://www.json.org/
    • JSON in JavaScript
    > http://www.json.org/js.html
    • JSON in Java
    > http://www.json.org/java/index.html

참고문헌

문서에 대하여

최초작성자 : 난다
최초작성일 : 2007년 4월 17일
버전 : 0.1
문서이력 :

  • 2007년 4월 17일 난다 문서 최초 생성

    [출처] JSON|작성자 agileman


'프로그래밍 > Web' 카테고리의 다른 글

[javascript] HTML DOM 지우기  (0) 2009.12.16
[jQuery] jQuery를 이용한 팝업. div, layer  (0) 2009.12.16
[html] html 특수기호  (3) 2009.09.08
[servlet] servlet  (0) 2009.09.04
[jQuery] jQuery 예제 02  (0) 2009.09.04

[java] thorws .....

프로그래밍/Java 2009. 12. 11. 16:53 Posted by galad
메소드 정의 시 throws 하면, 그 메소드 사용하는 부분에서 반드시 try-catch 해야한다.
메소드 구현 시에 exception을 던지든 말든지 말이지...

반대로 정의 시에 throws 안하면, 그 메소드 사용하는 부분에서 try-catch 안해도됨.
메소드에서 exception을 던지든 말든지 말이지...

기본기가 점점 사라지는 느낌.
공부 좀 하자꾸나...

[program] 프로파일러

프로그래밍/Library 2009. 12. 3. 10:22 Posted by galad

'프로그래밍 > Library' 카테고리의 다른 글

[eclipse] plug-ins  (0) 2010.08.17
[browser] MS Expension Web SuperView  (0) 2010.04.08
[Eclipse] Aptana Studio  (0) 2009.11.30
[Eclipse] 형상관리 plug-in  (0) 2009.11.30
[eclipse] 이클립스 + Mantis  (0) 2009.10.27

[Eclipse] Aptana Studio

프로그래밍/Library 2009. 11. 30. 17:00 Posted by galad
http://download.aptana.org/tools/studio/plugin/install/studio

Ajax and JavaScript Libraries

Get unrivaled support for popular libraries including jQuery, Prototype, YUI, dojo, Ext JS, MooTools, and others.

Ruby on Rails, Python and PHP

Add powerful plugins and ready-to-use runtimes for Ruby on Rails, Python and PHP. Eclipse users can easily add Studio as a plugin.

등등의 개발을 위한 이클립스 플러그인.


http://www.aptana.org/

'프로그래밍 > Library' 카테고리의 다른 글

[browser] MS Expension Web SuperView  (0) 2010.04.08
[program] 프로파일러  (0) 2009.12.03
[Eclipse] 형상관리 plug-in  (0) 2009.11.30
[eclipse] 이클립스 + Mantis  (0) 2009.10.27
[Utils] Paros 사용법  (0) 2009.09.06

[Eclipse] 형상관리 plug-in

프로그래밍/Library 2009. 11. 30. 13:16 Posted by galad
http://downloads.open.collab.net/eclipse/update-site/e3.4

Software Updates 에서 사용하자

'프로그래밍 > Library' 카테고리의 다른 글

[program] 프로파일러  (0) 2009.12.03
[Eclipse] Aptana Studio  (0) 2009.11.30
[eclipse] 이클립스 + Mantis  (0) 2009.10.27
[Utils] Paros 사용법  (0) 2009.09.06
[Subversion] 오리지널 서브버젼 이클립스 플러그인  (0) 2009.08.28
프로토콜을 준수한다는 것

- 프로토콜을 준수한다는 것, 즉 conform한다는 것은, 한 클래스나 객체가 그 프로토콜의 모든 method를 다 구현하고 있다는 것이다.
 > NOTE : Class가 protocol을 formal하게 채용하지 않아도, method로써 protocol method들을 구현하면 자동으로 그 protocol을 준수하게 된다.
  -> @interface ClassName : ItsSuperclass < protocol list > 이런 식으로 formal 하게 protocol을 채용하지 않더라도 class가 protocol의 method를 구현하면 준수하게 된다고?
  -> 아닌 듯... 안되는데?? 소스 참고.



[Objective C] Protocol Object

프로그래밍/iPhone Dev 2009. 11. 26. 16:41 Posted by galad
Protocol Object

- runtime시에 protocol이 어떻게 표현되는지에 대해서 알아보자. 클래스는 class object로, 함수는 selector로 runtime시에 나타나듯이, formal protocol은 Protocol 클래스로 나타난다. protocol을 다루는 코드는 Protocol 오브젝트를 참조해야만 한다.

- protocol 객체를 참조하는 방법은 @protocol() 디렉티브를 이용해서 한다.

Protocol *counter = @protocol(ReferenceCounting);

- class 이름과 다른 점은, protocol 이름은 @protoco()안에 있는 것을 제외하고는, 어떤 한 객체를 의미하지는 않는다.
  -> ReferenceCounting 만으로는 아무것도 가리키지 않는다는 듯. class일 경우엔 class 이름만으로 class object를 가리키지만.

- 컴파일러는 다음의 경우에만 protocol 객체를 만든다.
  > 클래스에 의해서 adopt 되었을 때,
  > 소스코드에서 다른 어딘가를 참조했을 때 ( @protoco()을 사용해서.. )
즉 선언은 되었지만 사용되지 않는 protocol은 runtime시에 protocol 객체로 나타나지 않는다.