1. 程式人生 > >JSP自定義標籤

JSP自定義標籤

mvvm框架盛行的今天jsp視乎已經out了,但是由於歷史原因jsp使用範圍依舊十分廣泛。(本人 喜歡jsp ,在標籤開發的效率上,jsp要比vue低很多,並且前後端分離的開發模式,在除錯,部署,分工都要好很多。) 

第一步 : jsp標籤的描述,宣告

jsp標籤需要使用xml描述(這裡的檔案格式是tld,依舊認為這就是xml)

<?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>jsp Label</description>
    <!-- 版本 -->
    <tlib-version>1.0</tlib-version>
    <!-- 短名 -->
    <short-name>kgo</short-name>
    <!-- 指定標籤庫URI -->
    <uri>/WEB-INF/JSPLabel.tld</uri>
     <!--   佈局標籤   -->
    <tag>
        <description>Layout</description>
        <!-- 標籤庫名字 -->
        <name>Layout</name>
        <!-- 標籤處理類 -->
        <tag-class>com.telchina.label.ContainerLabel</tag-class>
        <!-- 標籤體內容 -->
        <body-content>scriptless</body-content>
        <!-- 標籤屬性:driver -->
        <attribute>
            <name>layHeight</name>
            <required>false</required>
            <fragment>true</fragment>
        </attribute>
         <attribute>
            <name>layClass</name>
            <required>true</required>
            <fragment>true</fragment>
        </attribute>
    </tag>   
    <!--   卡片標籤  -->
    <tag>
        <description>jsp卡片</description>
        <!-- 標籤庫名字 -->
        <name>Card</name>
        <!-- 標籤處理類 -->
        <tag-class>com.telchina.label.CardLabel</tag-class>
        <!-- 標籤體內容 -->
        <body-content>scriptless</body-content>
        <!-- 標籤屬性:driver -->
        <attribute>
            <name>title</name>
            <required>true</required>
            <fragment>true</fragment>
        </attribute>
    </tag>
     <!--   卡片標籤  -->
    <tag>
        <description>jsp輪播</description>
        <!-- 標籤庫名字 -->
        <name>carousel</name>
        <!-- 標籤處理類 -->
        <tag-class>com.telchina.label.CarouselLabel</tag-class>
        <!-- 標籤體內容 -->
        <body-content>scriptless</body-content>
        <!-- 標籤屬性 -->
        <attribute>
            <name>id</name>
            <required>true</required>
            <fragment>true</fragment>
        </attribute>
    </tag>
    
</taglib>

這裡講一下幾個重要的屬性:

1)body-content 有如下四個屬性 

tagdependent:標籤體內容直接被寫入BodyContent,由自定義標籤類來進行處理,而不被JSP容器解釋,

如下:

<test:myList>

select name,age from users

</test:myList>

JSP:接受所有JSP語法,如定製的或內部的tag、scripts、靜態HTML、指令碼元素、JSP指令和動作。如:

<my:test>

    <%=request.getProtocol()%>     

</my:test>

具體可參考後面附原始碼。

empty:空標記,即起始標記和結束標記之間沒有內容。

下面幾種寫法都是有效的,

<test:mytag />

<test:mytag uname="Tom" />

<test:mytag></test:mytag>

scriptless:接受文字、EL和JSP動作。如上述使用<body-content> scriptless </body-content>則報錯,具體可參考後面附原始碼。

注意:scriptless聲明後標籤內部不能為空。

2)required 引數是否必須 

第二步:書寫jsp標籤的實現類 

已上訴jsp標籤中的Card標籤為例

package com.kgo.label;

import java.io.IOException;
import java.io.StringWriter;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.SimpleTagSupport;

public class CardLabel extends SimpleTagSupport {
	private StringBuffer head_buffer = new StringBuffer();
	private StringBuffer foot_buffer = new StringBuffer();
	// 屬性
	private String title = "jsp卡片標籤";

	private StringWriter sw = new StringWriter();

	public void doTag() throws JspException, IOException {
		JspWriter out = getJspContext().getOut();
		printHead();
		out.println(head_buffer.toString());

		getJspBody().invoke(sw);
		getJspContext().getOut().println(sw.toString());
		printFoot();
		out.println(foot_buffer.toString());
	}

	private void printHead() {
		head_buffer.append(String.format("<div class=\"%s %s\">%n", "layui-card", "kgo-card"));
		head_buffer.append(String.format("	<div class=\"%s\">%s</div>", "layui-card-header", title));
		head_buffer.append(String.format("	<div class=\"%s %s\">%n", "layui-card-body", "kgo-card-body"));
	}

	private void printFoot() {
		foot_buffer.append(String.format("	</div>%n"));
		foot_buffer.append(String.format("</div>%n"));
		foot_buffer.append(String.format("<script>"));
		foot_buffer.append(String.format("layui.use(['element','jquery'], function(){%n"));
		foot_buffer.append(String.format(" 	 var element = layui.element; %n"));
		foot_buffer.append(String.format(" 	 var $ = layui.jquery;%n  "));

		foot_buffer.append(String.format(" });%n"));
		foot_buffer.append(String.format("</script>"));
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

}

實現基本是這樣:

屬性  在tld裡進行宣告,在實現類中宣告同名(必須同名)的私有變數,並新增set和get方法。

入口 我這裡繼承了SimpleTagSupport物件(jsp2.0以及以上版本才能使用該物件)入好函式則為 doTag() 方法。

列印 開始dom

JspWriter out = getJspContext().getOut();
out.println(head_buffer.toString());

這個標籤可以巢狀其他標記進行使用,因此這裡列印的是上半部分dom 

private void printHead() {
		head_buffer.append(String.format("<div class=\"%s %s\">%n", "layui-card", "kgo-card"));
		head_buffer.append(String.format("	<div class=\"%s\">%s</div>", "layui-card-header", title));
		head_buffer.append(String.format("	<div class=\"%s %s\">%n", "layui-card-body", "kgo-card-body"));
	}

這裡是在封裝layui標籤,使用了一下字串格式化,但是由於時間太匆忙未進行完善的封裝 

喚醒嵌入的dom(可以不是dom,可以是文字,其他jsp標籤都可以)

		getJspBody().invoke(sw);
		getJspContext().getOut().println(sw.toString());

這裡就是列印嵌入在標籤內部的dom結構。

列印 結束dom

printFoot();
		out.println(foot_buffer.toString());

列印的dom結構如下:

private void printFoot() {
		foot_buffer.append(String.format("	</div>%n"));
		foot_buffer.append(String.format("</div>%n"));
		foot_buffer.append(String.format("<script>"));
		foot_buffer.append(String.format("layui.use(['element','jquery'], function(){%n"));
		foot_buffer.append(String.format(" 	 var element = layui.element; %n"));
		foot_buffer.append(String.format(" 	 var $ = layui.jquery;%n  "));

		foot_buffer.append(String.format(" });%n"));
		foot_buffer.append(String.format("</script>"));
	}

第三步:webXML宣告 

<jsp-config>
	<taglib>
	        <taglib-uri>/WEB-INF/JSPLabel.tld</taglib-uri>
	        <taglib-location>/WEB-INF/JSPLabel.tld</taglib-location>
	</taglib>
</jsp-config>

tld標籤可以被打包進jar包,jstl標籤就是這樣的,這裡我還沒有做,日後補充。