티스토리 뷰
JSTL 태그를 통해 JSP 페이지에서 반복, 상태제어, 국제화(i18n), SQL 등을 사용할 수 있습니다. 하지만 때로는 이것들이 충분하지 않기 때문에 JSP페이지에서 약간의 작업을 수행하기 위해 자바스크립트를 쓰려는 유혹에 빠질 수 있습니다. 다행히도 JSP는 확장 가능하며 특정 작업을 수행할 수 있도록 고유한 사용자 지정 태그를 생성할 수 있습니다.
JSP 커스텀 태그 (JSP Custom Tag)
예를들어, 우리는 숫자가 콤마와 소수점 2번째 자리까지만 보여지도록 하고싶다고 가정합시다. 이는 숫자가 매우 길때 유용할 수 있습니다. 그래서 다음과 같은 커스텀 태그를 만들면 편하게 사용할 수 있을 것입니다.
<mytags:formatNumber number="100050.574" format="#,###.00"/>
위의 커스텀 태크를 통해 number에 입력된 숫자가 format 형식에 맞게 100,050.57
를 JSP 페이지에 출력하게끔 할 수 있습니다.
JSTL에서는 위와 같이 동작하는 태그를 지원하지 않으므로, 우리는 우리만의 커스텀 태그를 구현하여 JSP 페이지에 사용할 것입니다. 아래는 이 예시 프로젝트의 최종 구조입니다.
JSP 커스텀 태그 핸들러 (JSP Custom Tag Handler)
첫 번째 단계에서 JSP 커스텀 태그를 만들어볼 것입니다. javax.servlet.jsp.tagext.SimpleTagSupport
클래스를 상속받아 doTag() 메서드를 override를 하면됩니다.
중요한 점은 태그에 사용될 속성들의 setter 메서드를 만들어야 합니다. 그래서 setFormat(String format) 과 setNumber(String number) 두 개의 setter 메서드를 정의할 것입니다.
SimpleTagSupport
는 JspWriter 객체를 얻고 response에 값을 쓸 수 있는 방법을 제공합니다. DecimalFormat 클래스를 이용하여 형식화된 string을 생성하고 이를 response에 보낼 것입니다. 최종 구현은 다음과 같습니다.
NumberFormatterTag.java
package tk.itstory.jsp.customtags;
import java.io.IOException;
import java.text.DecimalFormat;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.SkipPageException;
import javax.servlet.jsp.tagext.SimpleTagSupport;
public class NumberFormatterTag extends SimpleTagSupport {
private String format;
private String number;
public NumberFormatterTag() {
}
public void setFormat(String format) {
this.format = format;
}
public void setNumber(String number) {
this.number = number;
}
@Override
public void doTag() throws JspException, IOException {
System.out.println("Number is:" + number);
System.out.println("Format is:" + format);
try {
double amount = Double.parseDouble(number);
DecimalFormat formatter = new DecimalFormat(format);
String formattedNumber = formatter.format(amount);
getJspContext().getOut().write(formattedNumber);
} catch (Exception e) {
e.printStackTrace();
// stop page from loading further by throwing SkipPageException
throw new SkipPageException("Exception in formatting " + number
+ " with format " + format);
}
}
}
try catch 구문에서 format() 메서드에서 던져진 예외를 잡아 JSP 페이지가 더 로딩되지 않게 SkipPageException을 던지도록 처리한 점을 살펴보세요.
JSP Custom Tag Library Descriptor (TLD) 생성
태그 핸들러 클래스를 구현했다면, 어플리케이션이 배포될 때 컨테이너가 해당 핸들러를 로드할 수 있도록 WEB-INF 디렉터리 하위에 TLD 파일을 정의할 필요가 있습니다.
numberformatter.tld
<?xml version="1.0" encoding="UTF-8" ?>
<taglib 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-jsptaglibrary_2_0.xsd"
version="2.0">
<description>Number Formatter Custom Tag</description>
<tlib-version>2.1</tlib-version>
<short-name>mytags</short-name>
<uri>http://itstory.tk/jsp/tlds/mytags</uri>
<tag>
<name>formatNumber</name>
<tag-class>tk.itstory.jsp.customtags.NumberFormatterTag</tag-class>
<body-content>empty</body-content>
<attribute>
<name>format</name>
<required>true</required>
</attribute>
<attribute>
<name>number</name>
<required>true</required>
</attribute>
</tag>
</taglib>
TLD 파일에 URI 요소를 정의해야합니다. 또한 format과 number 속성이 필수 속성임을 표시해야합니다(required: true). body-content의 empty는 태그가 body를 가지고 있지 않다는 것을 의미합니다.
JSP Custom Tag Deployment Descriptor 설정
우리는 아래의 예시처럼 jsp-config와 taglib 요소를 이용하여 jsp 커스텀 태그를 웹 어플리케이션에 포함시킬 것입니다.
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<display-name>JSPCustomTags</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<jsp-config>
<taglib>
<taglib-uri>http://itstory.tk/jsp/tlds/mytags</taglib-uri>
<taglib-location>/WEB-INF/numberformatter.tld</taglib-location>
</taglib>
</jsp-config>
</web-app>
taglib-uri 값은 TLD 파일에 정의된 것과 동일해야 합니다. 이로써 모든 설정이 완료되었고 이제 JSP 페이지에서 커스텀 태그를 사용할 수 있습니다.
JSP 페이지에서 JSP Custom Tag 사용하기
우리가 만든 number formatter 커스텀 태그를 JSP 페이지에 사용한 예제입니다.
index.jsp
<%@ page language="java" contentType="text/html; charset=US-ASCII"
pageEncoding="US-ASCII"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Custom Tag Example</title>
<%@ taglib uri="http://itstory.tk/jsp/tlds/mytags" prefix="mytags"%>
</head>
<body>
<h2>Number Formatting Example</h2>
<mytags:formatNumber number="100050.574" format="#,###.00"/><br><br>
<mytags:formatNumber number="1234.567" format="$# ###.00"/><br><br>
<p><strong>Thanks You!!</strong></p>
</body>
</html>
웹 어플리케이션을 실행시키면 JSP 페이지는 다음과 같은 화면을 보여줄 것 입니다.
JSP 응답 페이지에는 포맷된 숫자가 표시됩니다. 이와 유사하게, 더 많은 jsp 사용자 지정 태그 핸들러 클래스를 생성할 수 있습니다. 태그 라이브러리에 여러개의 태그를 정의할 수도 있습니다.
만약 커스텀 태그 핸들러가 매우 많거나 다른 사용자들에게 JAR 파일로 제공하길 원한다면, JAR 파일의 META-INF 디렉터리에 TLD 파일들을 포함시키고, JAR 파일을 웹 어플리케이션의 lib 디렉터리에 포함시키면 됩니다. JSP 컨테이너가 이들을 자동으로 로드하기 때문에 web.xml에 추가적으로 설정할 필요는 없습니다.
이것이 우리가 JSP 표준 태그(JSTL)을 사용할 때 web.xml에 따로 설정할 필요 없이 JSP에서 사용할 수 있는 이유입니다. 만약 믿지 못하겠다면, JSTL Tomcat stardard.jar 파일을 압축 해제하면 META-INF 디렉터리에 수많은 TLD 파일들이 있는 것을 확인하실 수 있을 것입니다.