今天将开始jsp自定义标签的学习!!
自定义标签
为什么要使用自定义标签,一般我们是不予许在一个jsp页面呢或者html中有过多的java代码,这样会影响后期维护的效力。
定义自定义标签
- 先建立自己的标签类,在类中实现自己的java代码。
- 在web-inf目录下,建立后缀名为tld的文件,在其中进行自定义标签的注册。
具体代码如下:
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;
public class DateTag extends TagSupport{
@Override
public int doStartTag() throws JspException {
// TODO Auto-generated method stub
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM--dd HH:mm:ss");
try {
pageContext.getOut().print(sdf.format(new Date()));//给个输出流
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return super.doStartTag();
}
}
<?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">
<tlib-version>1.1</tlib-version>
<short-name>c1</short-name>
<uri>/test-tag</uri>
<tag>
<name>date</name>
<tag-class>com.example.tag.DateTag</tag-class>
<body-content>empty</body-content>
</tag>
</taglib>
注意点:
- 创建tld,不会出现上面那些配置信息,在使用的时候,最好从其他地方就行复制。
- 在上述复制结束之后,需要进行一些配置的修改。<uri>必须是/开始,后面的信息,你自己随便定义,,在jsp使用的时候,填写的uri必须一致。<tag>标签下的是标签库的描述类,<tag-classs>是配置标签类的位置。<name>是配置标签使用的名称,方便jsp中的使用。
使用自定义标签
<%@ taglib prefix="tag" uri="/test-tag" %>
<tag:date/>
如何控制标签体内容的执行
还是正常写一个标签,在标签的dostarttag方法中,需要就行逻辑处理。
在配置的时候,<body-content>这个标签下,有4个属性值,其中empty表示这个标签下没有内容;scriptless表示这个标签体下可以有 文本,el 表达式,jsp动作;jsp表示这个标签体下,可以出现jsp的脚本,就是java代码; tagdependent表示 标签的内容写入body-content,由自定义的标签体类处理,而不被jsp容器去解析。
具体代码如下:
public int doStartTag() throws JspException {
// TODO Auto-generated method stub
String name = pageContext.getRequest().getParameter("name");//获取请求参数的值
if(name!=null&&name.equals("laoqiang")){
return EVAL_BODY_INCLUDE;//这个常量是执行标签体内容
}else{
return SKIP_BODY;//这个常量是跳过标签体内容
<tag:ControlSkilTagContent>//携带内容的标签体
sdasdadddddddd
</tag:ControlSkilTagContent>
http://localhost:8080/TagTest/MyJsp.jsp?name=laoqiang
//请求网址
该代码可以实现类似,不同的用户,展示不同部分的页面。
如何实现标签结束控制
主要用途:判断用户是否从超链接和表单提交到本站点。
主要实现方法:
@Override
public int doStartTag() throws JspException {
// TODO Auto-generated method stub
HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
String refer = request.getHeader("referer");//通过获取请求头的,来判断用户是从哪个地方连接过来,只有超练接和浏览器表单提交才可以。
String url = "http://"+request.getServerName(); //获取本站点的url。
System.out.println(url+"ggggggggggggg");
if(refer!=null&&refer.startsWith(url)){
return EVAL_PAGE;
}else{
try {
pageContext.getOut().print("不能访问");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return SKIP_PAGE;
}
}
注意在本标签使用的时候,为了阻止该页面的显示,标签一定要放在前面。
自定义标签属性
主要实现的方法就是通过在标签类中定义所需要的属性的set、get方法。在配置标签的时候,通过attribute进行配置。具体代码例子如下:
public class DbConnectionTag extends TagSupport {
private String driver;
private String passward;
private String username;
private String url;
private String sql;
public String getSql() {
return sql;
}
public void setSql(String sql) {
this.sql = sql;
}
public String getDriver() {
return driver;
}
public void setDriver(String driver) {
this.driver = driver;
}
public String getPassward() {
return passward;
}
public void setPassward(String passward) {
this.passward = passward;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
@Override
public int doEndTag() throws JspException {
Connection conn = null;
Statement stat = null;
ResultSet res = null;
// TODO Auto-generated method stub
try {
Class.forName(this.driver);
conn = DriverManager.getConnection(this.url, this.username, this.passward);
stat = conn.createStatement();
res = stat.executeQuery(this.sql);
if(res!=null){
while(res.next()){
pageContext.getOut().println((res.getString("userNo")));
}
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if(res!=null){
try {
res.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(stat!=null){
try {
stat.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return super.doEndTag();
}
}
标签配置
<tag>
<name>DbConnectionTag</name>
<tag-class>com.example.tag.DbConnectionTag</tag-class>
<body-content>empty</body-content>
<attribute>
<name>driver</name>
<required>true</required>
</attribute>
<attribute>
<name>passward</name>//属性的名称
<required>true</required>//属性是否必须显示使用
<rtexprvalue>true</rtexprvalue>//这个标签是属性值可以是表达式
</attribute>
<attribute>
<name>username</name>
<required>true</required>
</attribute>
<attribute>
<name>url</name>
<required>true</required>
</attribute>
<attribute>
<name>sql</name>
<required>true</required>
</attribute>
</tag>
自定义标签的遍历
主要是通过doAfterBody方法来实现的,下面不多说,直接上代码:
public class IterationTag extends TagSupport {
private String[] array;
private int i = 1;
private String var;
public String getVar() {
return var;
}
public void setVar(String var) {
this.var = var;
}
public String[] getArray() {
return array;
}
public void setArray(String[] array) {
this.array = array;
}
@Override
public int doStartTag() throws JspException {
// TODO Auto-generated method stub
if(array!=null&&array.length>0){
pageContext.setAttribute(this.var, array[0]);
return EVAL_BODY_INCLUDE;
}else{
return SKIP_BODY;
}
}
@Override
public int doAfterBody() throws JspException {
// TODO Auto-generated method stub
if(i<array.length){
pageContext.setAttribute(this.var,array[i]);
i++;
return EVAL_BODY_AGAIN;
}else{
return SKIP_BODY;
}
}
}
利用这种标签遍历,会受到tomcat的缓存影响,第一次遍历出来,刷新后只有第0个位置元素。
修改标签体的内容
主要是通过定义标签处理类来继承BodyTagSupport,通过bodycontennt来获取标签体的内容。
public class ModifyBodyTag extends BodyTagSupport{
private BodyContent bodyContent;
@Override
public int doEndTag() throws JspException {
// TODO Auto-generated method stub
String s = bodyContent.getString();//获取标签体的内容
String newcontent ="我是修改后的内容";
JspWriter js = bodyContent.gtEnclosingWriter();//获取输出流
try {
js.write(newcontent);//将修改后的内容输出到jsp
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return EVAL_PAGE;
}
@Override
public void setBodyContent(BodyContent b) {
// TODO Auto-generated method stub
super.setBodyContent(b);
bodyContent = b;
}
}
重点啦!!!
通过上面的代码,我们已经初步对自定义标签有所了解,但是上述的自定义标签方法,在使用的时候还是不是太方面,所以引入simpletag、simpletagsupport,但是在实际开发中,我们还是主要使用标签库2.0的simpletagsupport。下面介绍simpletagsupport的方法:
- dotag 是核心方法,处理标签逻辑。
- setparent 将父标签处理器对象传递给标签处理器。
- getparent 获取当前标签的父标签。
- setjspcontext 方法将jsp页面的pagecontext对象传递给标签处理器对象。
- setjspbody 将代表当前标签体的jspfragment对象给标签处理器对象。
- getjspcontext 返回jsp页面pagecontext。
- getjspbody 返回标签体的内容。
使用2.0标签,在配置的时候 :
<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">
</taglib>
tld文件的版本必须是2.0。
将之前几个例子通过simpletagsupport实现,代码如下:
@Override
public void doTag() throws JspException, IOException {
// TODO Auto-generated method stub
super.doTag();
// TODO Auto-generated method stub
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM--dd HH:mm:ss");
JspWriter js = getJspContext().getOut();//通过获取jsp的上下文,然后拿到输出流
js.write(sdf.format(new Date()));//将内容写入到jsp。
}
public class ControlSkilTagContent extends SimpleTagSupport {
@Override
public void doTag() throws JspException, IOException {
// TODO Auto-generated method stub
super.doTag();
PageContext pageContext = (PageContext) getJspContext();//获取pagecontext
String name = pageContext.getRequest().getParameter("name");
if(name!=null&&name.equals("liujinxin")){
getJspBody().invoke(null);//getJspBody()得到Jspfragment,将内容作为标签体内容显示出来
}
}
public void doTag() throws JspException, IOException {
// TODO Auto-generated method stub
super.doTag();
PageContext pageContext = (PageContext) getJspContext();
HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
String refer = request.getHeader("referer");//判断请求是否是从超链接
if(refer==null){
throw new SkipPageException();//跳过jsp页面,不显示。
}
}
private String[] array;
private String var;
public String getVar() {
return var;
}
public void setVar(String var) {
this.var = var;
}
public String[] getArray() {
return array;
}
public void setArray(String[] array) {
this.array = array;
}
@Override
public void doTag() throws JspException, IOException {
// TODO Auto-generated method stub
super.doTag();
PageContext pageContext = (PageContext) getJspContext();
if(array!=null&&array.length>0){
pageContext.setAttribute(this.var, array[0]);
getJspBody().invoke(null);//将遍历出来的内容,作为标签体的内容输出出来。
}
}
@Override
public void doTag() throws JspException, IOException {
// TODO Auto-generated method stub
super.doTag();
StringWriter sw = new StringWriter();//构建一个缓冲区.
JspFragment jf = getJspBody();//获取标签体的内容
jf.invoke(sw);//将标签体写到缓冲区中
String content = sw.toString();//从缓冲区得到内容
getJspContext().getOut().write(content);//将内容写到jsp页面上
}
复合标签组合
<tag:choose>
<tag:when grade="$(grade)==100">
very good
</tag:when>
<tag:otherwise>
加油吧,骚年!!!!!!!
</tag:otherwise>
</tag:choose>
private boolean grade;
public boolean isGrade() {
return grade;
}
public void setGrade(boolean grade) {
this.grade = grade;
}
@Override
public void doTag() throws JspException, IOException {
// TODO Auto-generated method stub
super.doTag();
if(grade){
getJspBody().invoke(null);
ChooseTag ct = (ChooseTag)getParent();//获取该标签的父类标签
ct.setFlag(true);//设置标志位
}
}
小伙伴们,jsp自定义标签已经学习完毕啦!