Recent Posts
Recent Comments
Link
11-21 14:38
Today
Total
관리 메뉴

삶 가운데 남긴 기록 AACII.TISTORY.COM

클래스 기반 커스텀 태그 JSP 1.2 본문

DEV&OPS/Java

클래스 기반 커스텀 태그 JSP 1.2

ALEPH.GEM 2022. 7. 5. 13:51

 

커스텀 태그

태그의 기능을 자바 클래스에서 구현한 다음 jsp 태그와 연결하여 사용할 수 있습니다.

클래스 기반 커스텀 태그를 사용하려면 아래와 같은 요소들이 필요합니다.

1. 태그 핸들러 클래스: 태그가 수행해야 하는 실행문을 구현한 클래스

2. 태그 라이브러리 디스크립터(TLD): xml파일로 확장자를 .tld 하여 클래스 파일과 커스텀 태그를 매칭

3. TLD파일 등록: jsp 컨테이너가 인식 할 수 있도록 web.xml이나 WEB-INF 폴더에 .tld 파일을 등록

4. taglib 지시자: jsp 페이지에서 커스텀 태그를 사용하기 위해서 taglib 지시자를 선언한 후 사용

 

태그 핸들러 클래스

javax.servlet.jsp.tagext 패키지에 태그 핸들러 클래스를 작성하기 위한 내용들이 있습니다.

  • Tag : 모든 태그 핸들러 클래스들이 상속받는 인터페이스
  • IteratonTag : 반복 수행하기 위한 메소드가 정의 된 인터페이스
  • BodyTag : jsp에서 몸체처리를 위한 메소드를 정의하고 있는 인터페이스
  • TagSupport : 태그 라이브러리를 쉽개 개발할 수 있게 만들어진 객체들
  • BodyTagSupport :  몸체가 있는 태그 라이브러리를 쉽게 개발하기 위해 만들어진 클래스
  • SimpleTag : JSP2.0이상. 커스텀 태그 작서으이 간편화를 위해 추가된 인터페이스
  • SimpleTagSupport : JSP2.0 이상. SimpleTag를 구현

 

TLD(Tag Library Descriptor)

TLD는 태그 핸들러 클래스와 태그 이름을 매핑해주는 환경 설정 파일 입니다. 

JSP2.0 이전 버전인경우 web.xml에 TLD파일을 등록해야합니다.

JSP2.0 이후 버전인경우 WEB-INF 폴더나 하위 폴더에 TLD파일을 넣어두면 web.xml에 등록하지 않고도 자동으로 인식합니다.

<%@ taglib prefix = " " uri = " " %>

처럼 jsp에서 taglib 지시자로 TLD 파일을 등록해야 커스텀 태그를 사용할 수 있습니다.

 

JSP 1.2 커스텀 태그 기본 예제

net.aacii.customTag 패키지를 새로 생성한 다음 MyCustomTag.java 클래스 파일을 생성합니다.

package net.aacii.customTag;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;

public class MyCustomTag extends TagSupport {
	@Override
	public int doStartTag() throws JspException {
		System.out.println("시작태그를 만나 호출됩니다.");
		return super.doStartTag();
	}

	@Override
	public int doEndTag() throws JspException {
		System.out.println("끝태그를 만나 호출됩니다.");
		return super.doEndTag();
	}

}

이제 WEB-INF 폴더에 myTag.tld 파일(xml)을 작성합니다. 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
<taglib>
	<tlib-version>1.0</tlib-version>
	<jsp-version>1.2</jsp-version>
	<short-name>myTags</short-name>
	<tag>
		<name>first</name>
		<tag-class>net.aacii.customTag.MyCustomTag</tag-class>
	</tag>
</taglib>

web.xml 에 tld 파일을 연결하는 정보를 추가합니다. (jsp1.2 기준이므로)

  <jsp-config>
  	<taglib>
  		<taglib-uri>http://myTags.com</taglib-uri>
  		<taglib-location>/WEB-INF/myTag.tld</taglib-location>
  	</taglib>
  </jsp-config>

새로운 jsp 파일을 작성합니다.

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="my" uri="http://myTags.com" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Custom Tag</title>
</head>
<body>
<my:first></my:first>

</body>
</html>

prefix는 태그 라이브러리에 이름을 지정해주는 것입니다.

uri는 web.xml에 등록했던 그 내용을 등록합니다.

<my:first> 태그에서 핸들러 클래스의 doStartTag()가 실행이 되며, </my:first>태그에서 핸들러 클래스의 doEndTag()가 실행됩니다.

실행해보면 콘솔 창에 java파일에서 작성했던 내용이 출력되는 것을 확인할 수 있습니다.

 

커스텀 태그 몸체 처리

myTag.tld 파일에 <body-content>는 몸체 처리에 관한 내용을 기술합니다.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
<taglib>
	<tlib-version>1.0</tlib-version>
	<jsp-version>1.2</jsp-version>
	<short-name>myTags</short-name>
	<tag>
		<name>first</name>
		<tag-class>net.aacii.customTag.MyCustomTag</tag-class>
		<body-content>empty</body-content>
	</tag>
</taglib>

empty는 몸체 내용이 없음을 선언합니다.

ex23.jsp 에서 원래 태그를 주석 처리한 뒤 아래처럼 수정합니다.

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="my" uri="http://myTags.com" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Custom Tag</title>
</head>
<body>
<%-- <my:first></my:first> --%>
<my:first/>
</body>
</html>

tld 에서 <body-content>값을 empty로 지정했기 때문에 몸체가 없는 태그로 작성해야 합니다.

 

EVAL_BODY_INCLUDE

EVAL_BODY_INCLUDE는 메소드가 종료된 후 태그의 몸체를 처리합니다.

myTag.tld 파일을 수정합니다.

아래와 같이 <body-content> 의 값을 JSP로 바꿉니다.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
<taglib>
	<tlib-version>1.0</tlib-version>
	<jsp-version>1.2</jsp-version>
	<short-name>myTags</short-name>
	<tag>
		<name>first</name>
		<tag-class>net.aacii.customTag.MyCustomTag</tag-class>
		<body-content>JSP</body-content>
	</tag>
</taglib>

MyCustomTag.java 소스를 수정합니다.

package net.aacii.customTag;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;

public class MyCustomTag extends TagSupport {
	@Override
	public int doStartTag() throws JspException {
		System.out.println("시작태그를 만나 호출됩니다.");
		return EVAL_BODY_INCLUDE;
	}

	@Override
	public int doAfterBody() throws JspException {
		System.out.println("body(몸체)처리가 끝났습니다.");
		return super.doEndTag();
	}

}

doStartTag() 의 리턴값을 EVAL_BODY_INCLUDE로 지정했습니다.

tld 파일에서 <body-content>값을 JSP로 변경했으므로 태그의 몸체는 JSP코드로 처리됩니다.

doAfterBody()는 몸체 처리가 끝난 후 호출되는 메소드입니다.

ex23.jsp를 다음과 같이 수정합니다.

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="my" uri="http://myTags.com" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Custom Tag</title>
</head>
<body>
<%-- <my:first></my:first> --%>
<%-- <my:first/> --%>
<my:first><%=2+9 %></my:first>
</body>
</html>

 

SKIP_BODY

SKIP_BODY는 태그의 몸체를 처리하지 않고 스킵합니다.

MyCustomTag.java 파일의 doStartTag()의 리턴값을 SKIP_BODY로 지정하면 태그 몸체에 관련된 작업을 하지 않습니다.

 

EVAL_BODY_AGAIN

EVAL_BODY_AGAIN는 몸체를 다시 실행하는 리턴값입니다.

MyCustomTag.java 를 다시 아래처럼 수정합니다.

package net.aacii.customTag;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;

public class MyCustomTag extends TagSupport {
	int cnt = 1;
	
	@Override
	public int doStartTag() throws JspException {
		System.out.println("시작태그를 만나 호출됩니다.");
		return EVAL_BODY_INCLUDE;
	}

	@Override
	public int doAfterBody() throws JspException {
		System.out.println("body(몸체)처리가 끝났습니다 : "+cnt);
		if(cnt++ < 10) {
			return EVAL_BODY_AGAIN;
		}else {
			return SKIP_BODY;
		}
	}

	@Override
	public int doEndTag() throws JspException {
		System.out.println("끝태그를 만나 호출됩니다.");
		return super.doEndTag();
	}

}

ex23.jsp를 다시 실행하면 몸체 실행이 10번 반복되고 종료되는 것을 확인할 수 있습니다.

 

EVAL_PAGE

EVAL_PAGE는 doEndTag()가 종료된 후 계속해서 JSP 페이지가 실행됩니다.

만약 SKIP_PAGE로 수정한다면 doEndTag()가 종료된 후에도 아무 처리를 하지 않게 됩니다.

 

속성 정의

tld 파일에 <attribute>태그로 속성을 정의하고 태크 핸들러 클래스에서 속성과 같은 멤버 변수를 선언하고 getter와 setter를 선언하고 사용합니다.

MyCustomTag.java 파일을 수정합니다.

package net.aacii.customTag;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;

public class MyCustomTag extends TagSupport {
	int cnt = 1;
	
	private String color;
	
	public String getColor() {
		return color;
	}
	
	public void setColor(String color) {
		this.color = color;
	}
	
	@Override
	public int doStartTag() throws JspException {
		System.out.println("시작태그를 만나 호출됩니다.");
		System.out.println("color 속성 값:"+color);
		return EVAL_BODY_INCLUDE;
	}

	@Override
	public int doAfterBody() throws JspException {
		System.out.println("body(몸체)처리가 끝났습니다 : "+cnt);
		if(cnt++ < 10) {
			return EVAL_BODY_AGAIN;
		}else {
			return SKIP_BODY;
		}
	}

	@Override
	public int doEndTag() throws JspException {
		System.out.println("끝태그를 만나 호출됩니다.");
		return super.doEndTag();
	}

}

myTag.tld 파일을 수정합니다.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
<taglib>
	<tlib-version>1.0</tlib-version>
	<jsp-version>1.2</jsp-version>
	<short-name>myTags</short-name>
	<tag>
		<name>first</name>
		<tag-class>net.aacii.customTag.MyCustomTag</tag-class>
		<body-content>JSP</body-content>
		<attribute>
			<name>color</name>
			<required>true</required>
			<rtexprvalue>true</rtexprvalue>
		</attribute>
	</tag>
</taglib>

ex23.jsp 를 아래와 같이 수정합니다.

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="my" uri="http://myTags.com" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Custom Tag</title>
</head>
<body>
<%-- <my:first></my:first> --%>
<%-- <my:first/> --%>
<%-- <my:first><%=2+9 %></my:first> --%>
<my:first color="red"><%= 1+2 %></my:first>
<br>
Custom Tag Test!
</body>
</html>

 

TEI (Tag Extra Infomation) 객체

TEI객체는 TLD 파일에 지정하지 않은 커스텀 태그의 내용을 동적으로 변경하여 복잡성을 없애려고 할 때 사용합니다.

TagExtraInfo 객체를 상속한 후 커스텀 태그에 관한 부가적인 처리 내용을 구현합니다.

그다음에는 TLD 파일을 통해 TEI와 Tag Handler 객체를 연결합니다.

그러면 jsp 페이지 에서 커스텀 태그가 사용되어 Tag Handler 객체가 실행되면서 TEI객체도 자동 실행됩니다.

그러면서 setTagInfo() -> isValid() -> getVariableInfo() 메소드가 순서대로 호출됩니다.

 

예제를 통해 isValid() 메소드를 활용해보겠습니다.

net.aacii.customTag 패키지에 MyCustomTagTEI.java 로 새로 생성합니다.

package net.aacii.customTag;

import javax.servlet.jsp.tagext.TagData;
import javax.servlet.jsp.tagext.TagExtraInfo;

public class MyCustomTagTEI extends TagExtraInfo {

	@Override
	public boolean isValid(TagData data) {
		String color = data.getAttributeString("color");
		if(color.equals("blue")) {
			return true;
		}else {
			return false;
		}
	}	

}

isValid() 메소드를 재정의해서 커스텀 태그의 유효성 체크를 합니다. 

리턴값이 true이면 커스텀 태그가 올바르게 사용된 것이고 false이면 태그 사용에 문제가 있는 것입니다.

위 예제는 color 속성값을 blue로 강제하고 있는 것입니다.

myTag.tld 파일을 아래처럼 수정합니다.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
<taglib>
	<tlib-version>1.0</tlib-version>
	<jsp-version>1.2</jsp-version>
	<short-name>myTags</short-name>
	<tag>
		<name>first</name>
		<tag-class>net.aacii.customTag.MyCustomTag</tag-class>
		<tei-class>net.aacii.customTag.MyCustomTagTEI</tei-class>
		<body-content>JSP</body-content>
		<attribute>
			<name>color</name>
			<required>true</required>
			<rtexprvalue>true</rtexprvalue>
		</attribute>
	</tag>
</taglib>

그러면 ex23.jsp가 오류가 나게되는데 color 속성이 red로 되어 있기 때문입니다.

태그 속성을 blue로 바꾸면 오류가 사라집니다.

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="my" uri="http://myTags.com" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Custom Tag</title>
</head>
<body>
<%-- <my:first></my:first> --%>
<%-- <my:first/> --%>
<%-- <my:first><%=2+9 %></my:first> --%>
<%-- <my:first color="red"><%= 1+2 %></my:first> --%>
<my:first color="blue"><%= 1+2 %></my:first>
<br>
Custom Tag Test!
</body>
</html>

 

 

 

 

728x90

'DEV&OPS > Java' 카테고리의 다른 글

태그 기반 커스텀 태그  (0) 2022.07.06
클래스 기반 커스텀 태그 JSP 2.1  (0) 2022.07.06
EL (Expression Language)  (0) 2022.07.01
JDBC 프로그래밍  (0) 2022.06.30
표준 액션 태그 jsp java beans  (0) 2022.06.22