커스텀 태그(Custom Tag) : JSP 문서에서 스크립트 요소 대신 사용하기 위해 프로그래머가 직접 만든 태그
태그 클래스 : JSP 문서에서 커스텀 태그를 사용할 경우 호출될 메소드가 선언된 클래스
TagSupport 클래스, BodyTagSupport 클래스, SimpleTagSupport 클래스 중 하나를 상속받아 작성
커스텀 태그 사용시 호출되는 메소드는 부모클래스의 메소드를 오버라이드 선언하여 작성
기본생성자 : JSP 문서에서 커스텀 태그를 최초로 사용할 경우 태그 클래스 객체를 생성하기 위해 한번만 호출
doStartTag 오버라이드 : JSP 문서에서 커스텀 태그의 시작태그를 사용할 때마다 자동 호출되는 메소드
pageContext.getOut().println("<div>안녕하세요.</div>");
doAfterBody : JSP 문서에서 커스텀 태그의 태그내용을 사용할 때마다 자동 호출되는 메소드
doEndTag : JSP 문서에서 커스텀 태그의 종료태그를 사용할 때마다 자동 호출되는 메소드
태그 속성과 태그 내용이 없는 커스텀 태그의 클래스
package xyz.itwill.custom;
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;
//태그 속성과 태그 내용이 없는 커스텀 태그의 클래스
public class HelloTag extends TagSupport {
private static final long serialVersionUID = 1L;
//JSP 문서에서 커스텀 태그를 최초로 사용할 경우 태그 클래스 객체를 생성하기 위해 한번만 호출
public HelloTag() {
//System.out.println("HelloTag 클래스의 기본 생성자 호출 - 객체 생성");
}
//JSP 문서에서 커스텀 태그의 시작태그를 사용할 때마다 자동 호출되는 메소드
@Override
public int doStartTag() throws JspException {
//System.out.println("HelloTag 클래스의 doStartTag() 메소드 호출");
try {
//부모클래스(TagSupport)에게 제공받은 PageContext 객체(pageContext 변수에 저장)를
//이용하여 웹프로그램 실행에 필요한 객체를 반환받아 명령 작성
//PageContext.getOut() : 응답결과를 생성하기 위한 출력스트림(JspWriter 객체)을 반환하는 메소드
pageContext.getOut().println("<div>안녕하세요.</div>");
} catch (IOException e) {
e.printStackTrace();
}
//doStartTag() 태그의 반환값(정수값) : 부모클래스(TagSupport)에서 제공되는 상수 사용
// => SKIP_BODY, EVAL_BODY_IMCLUDE, EVAL_BODY_AGAIN 중 하나를 선택하여 반환
// => SKIP_BODY : 태그내용을 클라이언트에게 전달하지 않을 경우 사용하는 상수 - 기본값
// => EVAL_BODY_INCLUDE : 태그내용을 클라이언트에게 전달할 경우 사용하는 상수
// => EVAL_BODY_AGAIN : 태그내용을 클라이언트에게 다시 한번 전달할 경우 사용하는 상수
return SKIP_BODY;
}
//JSP 문서에서 커스텀 태그의 태그내용을 사용할 때마다 자동 호출되는 메소드
@Override
public int doAfterBody() throws JspException {
//System.out.println("HelloTag 클래스의 doAfterBody() 메소드 호출");
//doAfterBody() 태그의 반환값(정수값) : doStartTag() 태그의 반환값과 동일
return super.doAfterBody();
}
//JSP 문서에서 커스텀 태그의 종료태그를 사용할 때마다 자동 호출되는 메소드
@Override
public int doEndTag() throws JspException {
//System.out.println("HelloTag 클래스의 doEndTag() 메소드 호출");
//doEndTag() 태그의 반환값(정수값) : 부모클래스(TagSupport)에서 제공되는 상수 사용
// => SKIP_PAGE, EVAL_PAGE 중 하나를 선택하여 반환
//SKIP_PAGE : 종료태그 실행 후 JSP 문서를 강제로 종료할 때 사용하는 상수
//EVAL_PAGE : 종료태그 실행 후 JSP 문서를 계속 실행할 때 사용하는 상수 - 기본값
return EVAL_PAGE;
}
}
tag : 커스텀 태그를 등록하기 위한 엘리먼트
attribute : 태그 속성을 등록하기 위한 엘리먼트
<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.1" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xml="http://www.w3.org/XML/1998/namespace" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd ">
<description>단순한 형태의 커스텀 태그 구현</description>
<tlib-version>1.0</tlib-version>
<short-name>simple</short-name>
<uri>http://www.itwill.xyz/mvc/custom</uri>
<!-- tag : 커스텀 태그를 등록하기 위한 엘리먼트 -->
<tag>
<!-- name : 커스텀 태그의 이름을 등록하기 위한 엘리먼트 -->
<name>hello</name>
<!-- tag-class : 커스텀 태그 사용시 생성될 객체의 태그 클래스를 설정하기 위한 엘리먼트 -->
<tag-class>xyz.itwill.custom.HelloTag</tag-class>
<!-- body-content : 커스텀 태그에서 사용 가능한 태그내용을 설정하기 위한 엘리먼트 -->
<!-- => empty : 태그내용이 없는 커스텀 태그를 설정하기 위한 엘리먼트 값 -->
<body-content>empty</body-content>
</tag>
<tag>
<name>helloMessage</name>
<tag-class>xyz.itwill.custom.HelloMessageTag</tag-class>
<body-content>empty</body-content>
<!-- attribute : 태그 속성을 등록하기 위한 엘리먼트 -->
<attribute>
<!-- name : 태그 속성명을 설정하는 엘리먼트 - 태그 클래스의 필드명과 같은 이름으로 작성 -->
<name>name</name>
<!-- required : 커스텀 태그의 속성에 대한 필수 여부를 설정하기 위한 엘리먼트 -->
<!-- => false : 선택 속성(기본) , true : 필수 속성 -->
<required>true</required>
</attribute>
</tag>
<tag>
<name>helloBody</name>
<tag-class>xyz.itwill.custom.HelloBodyTag</tag-class>
<!-- body-content 엘리먼트 값으로 [JSP]를 설정하면 태그내용으로 JSP 명령 사용 가능 -->
<body-content>JSP</body-content>
<attribute>
<name>test</name>
<required>true</required>
<!-- rtexprvalue : 태그 속성값으로 JSP Expression 또는 EL 사용 여부를 설정하기 위한 엘리먼트 -->
<!-- => false : 사용 불가능(기본), true : 사용 가능 -->
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>
taglib 디렉티브를 사용하여 TLD 파일을 제공받아야 JSP 문서에서 커스텀 태그를 사용 가능
custom tag 작성 <prefix name:tag name/>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%-- taglib 디렉티브를 사용하여 TLD 파일을 제공받아야 JSP 문서에서 커스텀 태그를 사용 가능 --%>
<%@taglib prefix="simple" uri="http://www.itwill.xyz/mvc/custom"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>MVC</title>
</head>
<body>
<h1>Custom Tag - NoAttribute And NoBody</h1>
<hr>
<%-- 태그내용이 있는 경우 시작태그와 종료태그를 따로 작성 --%>
<%-- <simple:hello></simple:hello> --%>
<%-- 태그내용이 없는 경우 시작태그와 종료태그를 같이 작성 --%>
<simple:hello/>
<simple:hello/>
<simple:hello/>
<simple:hello/>
<simple:hello/>
</body>
</html>
태그 속성이 있으며 태그 내용이 없는 커스텀 태그의 클래스
태그 속성값을 저장하기 위한 필드 선언 (태그의 속성명과 같은 이름으로 필드 선언)
생성자에서는 객체 생성에 필요한 초기화 작업에 대한 명령 작성 (필드 초기값 설정)
커스텀 태그에서 태그의 속성을 사용하여 속성값을 설정할 경우 Setter 메소드 자동 호출
package xyz.itwill.custom;
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;
//태그 속성이 있으며 태그 내용이 없는 커스텀 태그의 클래스
public class HelloMessageTag extends TagSupport {
private static final long serialVersionUID = 1L;
//태그 속성값을 저장하기 위한 필드 선언 - 태그의 속성명과 같은 이름으로 필드 선언
private String name;
//생성자에서는 객체 생성에 필요한 초기화 작업에 대한 명령 작성 - 필드 초기값 설정
public HelloMessageTag() {
//커스텀 태그에서 속성을 생략할 경우 기본적으로 사용될 속성값을 필드에 자동 저장하기 위해 작성
// => 태그 속성이 필수인 경우 필드 기본값 설정 생략
name="홍길동";
}
public String getName() {
return name;
}
//커스텀 태그에서 태그의 속성을 사용하여 속성값을 설정할 경우 Setter 메소드 자동 호출
// => 매개변수로 속성값을 제공받아 필드값 변경
public void setName(String name) {
this.name = name;
}
//커스텀 태그 사용시 실행될 명령이 있는 경우에만 메소드를 오버라이드 선언하여 작성
// => 메소드를 오버라이드 선언하지 않으면 자동으로 부모클래스의 명령이 없는 메소드 호출
@Override
public int doStartTag() throws JspException {
try {
if(name.equals("홍길동")) {
pageContext.getOut().println("<h3>관리자님, 안녕하세요.</h3>");
} else {
pageContext.getOut().println("<h3>"+name+"님, 안녕하세요.</h3>");
}
} catch (IOException e) {
throw new JspException(e.getMessage());
}
return super.doStartTag();
}
}
커스텀 태그의 속성을 생략한 경우 태그 클래스의 생성자에서 설정한 기본값을 속성값으로 사용
커스텀 태그의 속성을 사용하여 속성값을 설정한 경우 태그 클래스의 필드에 대한 Setter 메소드를 자동 호출하여 속성값을 전달받아 필드명 변경
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="simple" uri="http://www.itwill.xyz/mvc/custom" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>MVC</title>
</head>
<body>
<h1>Custom Tag - AnyAttribute And NoBody</h1>
<hr>
<%-- 커스텀 태그의 속성을 생략한 경우 태그 클래스의 생성자에서 설정한 기본값을 속성값으로 사용 --%>
<%-- => 커스텀 태그의 속성이 필수로 설정된 경우 속성을 생략하면 에러 발생 --%>
<%-- <simple:helloMessage/> --%>
<%-- 커스텀 태그의 속성이 필수로 설정된 경우 태그 사용시 속성 자동 완성 --%>
<simple:helloMessage name="홍길동"/>
<%-- 커스텀 태그의 속성을 사용하여 속성값을 설정한 경우 태그 클래스의 필드에 대한 Setter
메소드를 자동 호출하여 속성값을 전달받아 필드명 변경 --%>
<%-- => 태그 클래스에 필드에 대한 Setter 메소드가 없는 경우 500 에러 발생 --%>
<simple:helloMessage name="임꺽정"/>
</body>
</html>
태그 속성과 태그 내용이 있는 커스텀 태그의 클래스
커스텀 태그의 속성값을 저장하기 위한 필드
package xyz.itwill.custom;
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;
public class HelloBodyTag extends TagSupport {
private static final long serialVersionUID = 1L;
//커스텀 태그의 속성값을 저장하기 위한 필드
// => 태그 속성이 필수인 경우 생성자를 이용하여 필드 초기화 작업 생략
private boolean test;
public boolean isTest() {
return test;
}
public void setTest(boolean test) {
this.test = test;
}
@Override
public int doStartTag() throws JspException {
try {
if(test) {
pageContext.getOut().println("<h3>");
} else {
pageContext.getOut().println("<p>");
}
} catch (IOException e) {
throw new JspException(e.getMessage());
}
return EVAL_BODY_INCLUDE;
}
@Override
public int doEndTag() throws JspException {
try {
if(test) {
pageContext.getOut().println("님, 안녕하세요.</h3>");
} else {
pageContext.getOut().println("님, 반갑습니다.</p>");
}
} catch (IOException e) {
throw new JspException(e.getMessage());
}
return EVAL_PAGE;
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="simple" uri="http://www.itwill.xyz/mvc/custom" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>MVC</title>
</head>
<body>
<h1>Custom Tag - AnyAttribute And AnyBody</h1>
<hr>
<simple:helloBody test="true">홍길동</simple:helloBody>
<simple:helloBody test="false">임꺽정</simple:helloBody>
<hr>
<%
String name="전우치";
request.setAttribute("name", "일지매");
%>
<simple:helloBody test="true"><%=name %></simple:helloBody>
<simple:helloBody test="false">${name }</simple:helloBody>
<hr>
<%
boolean sw=true;
request.setAttribute("sw", false);
%>
<simple:helloBody test="<%=sw %>">장길산</simple:helloBody>
<simple:helloBody test="${sw }">홍경래</simple:helloBody>
</body>
</html>