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标签就是这样的,这里我还没有做,日后补充。
上一篇: wxWidgets教程(15)——wxListCtrl用法
下一篇: 前端秋招笔试(5)- 58同城