JSP自定义标签

假设 向浏览器输出当前客户的IP地址 ,我们现在可以这样写

<%	//获取当前用户的IP地址
   		String ip=request.getRemoteHost();
   		out.print("当前用户的IP地址是:"+ip);
  %>

但我们现在为了要在jsp页面尽量减少java代码,这个时候我们可以向前面学标签一样,自己来定义一个标签,通过调用标签来达到实现显示客户端的ip地址。

首先第一步我们要创建一个普通的java类,继承SimpleTagSupport类,叫标签处理器类(用来处理我们的需求,比如这里,我们用它来做获取ip,同时打印的处理),代码如下

package com.gqx.a_tag;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspContext;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.SimpleTagSupport;

/**
 * 标签的处理器类
 * @author Administrator
 *(1)、继承SimpleTagSupport
 *(2)、覆盖doTag方法,doTag里没有request的方法,我们没有办法拿到ip地址;
 *	Class SimpleTagSupport  Implemented Interfaces: JspTag, SimpleTag,肯定要实现里面的方法
 *SimpleTag的方法里面有setJspContext(JspContext pc) 这个方法,传入了JspContext
 *但是Class JspContext extended by javax.servlet.jsp.JspContext Direct Known Subclasses:PageContext
 *即JspContext的子类是pageContext,可以通过多态去强转,一旦得到了pageContext,我们就等同于得到了jsp的其余八个内置对象
 */
public class ShowIpTag extends SimpleTagSupport{
	private JspContext jspContext;
	//实现setJspContext方法去获取pageContext对象
	public void setJspContext(JspContext pc) {
		this.jspContext=pc;
	}
		@Override
		public void doTag() throws JspException, IOException {
				//因为jspContext是pageContext的子类,所以可以将jspContext向上转型
			PageContext pageContext=(PageContext) jspContext;
			//通过pageContext去获取request(同样的道理,HttpServletRequest的子类是ServletRequest
			//Interface ServletReques All Known Subinterfaces: HttpServletRequest
			 HttpServletRequest request= (HttpServletRequest) pageContext.getRequest();
			String ip=request.getRemoteHost();
			JspWriter writer=pageContext.getOut();
			writer.write("使用自定义标签获取ip地址:"+ip);
		}
}

我们可以仿照系统jstl中已经有了的tag标签,参照其原有的代码,在web项目的web-INF目录下创建一个tld文件(我这里叫做gqxtag.tld文件)然后将其没用的地方都给删除掉,剩下的部分代码如下

<?xml version="1.0" encoding="UTF-8" ?>

<taglib xmlns="http://java.sun.com/xml/ns/javaee"
    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"
    version="2.1">
   <!-- 标签库的版本 -->
  <tlib-version>1.2</tlib-version>
  <!-- 标签库的前缀 -->
  <short-name>c</short-name>
  <!-- tld文件的唯一标记 -->
  <uri>http://www.gqxing.com</uri>
  <!-- 这是标签的声明 -->
  <tag>
    <!-- 标签的名称 -->
    <name>showIp</name>
    <!-- 标签处理器类的全名 -->
    <tag-class>com.gqx.a_tag.ShowIpTag</tag-class>
    <!-- 输出内容的格式 -->
    <body-content>scriptless</body-content>
  </tag>

</taglib>

在复制类标签的路径的时候,我们可以到相关类的在这里单击右键,选择Copy Qualified Name,即可得到相关类处理器的路径

接下来我们就可以在jsp页面中去使用它了,首先,和前面的jstl标签使用一样,我们通过taglib指令去声明

<%@taglib uri="http://www.gqxing.com" prefix="gqx" %>

然后就是直接在jsp的body中直接去调用标签了

 <gqx:showIp></gqx:showIp>

结果如图:

我们又去仔细看看SimpleTagSupport的源代码发现了和我们一样的代码,

private JspContext jspContext;
public void setJspContext(JspContext pc) {
		this.jspContext=pc;
	}
public JspContext getJspContext(JspContext pc) {
		return this.jspContext;
	}

这样我们就可以简化我们的代码了

public class ShowIpTag extends SimpleTagSupport{
		@Override
		public void doTag() throws JspException, IOException {
			 HttpServletRequest request= (HttpServletRequest) pageContext.getRequest();
			String ip=request.getRemoteHost();
			JspWriter writer=pageContext.getOut();
			writer.write("使用自定义标签获取ip地址:"+ip);
		}
}

自定义标签时如何执行的

首先当服务器启动的时候,开始加载每一个web应用,同时加载每一个web-info下面的所有文件,如web.xml,还有我刚才定义的一个usertag.tld文件。

(1)、服务器访问http://localhost:8080/JspDemo/usertag/demo1.jsp资源文件,将jsp文件翻译成java文件,同时继续编译成class文件,调用生命周期的jsp_Service()方法。

(2)检查jsp文件中通过taglib指令声明的tld文件,是否存在一个名为http://www.gqxing.com的tld文件,没有就报错,有就会去读取文件,,同时调入内存。

(3)、当jsp的字节码读到了<gqx:showIp>这个标签后,就会去上面的tld文件去查找,同时读取 <tag-class>com.gqx.a_tag.ShowIpTag</tag-class>,然后再去构造ShowIpTag的对象,再去调用里面的方法。


自定义标签处理器类的生命周期

刚才再写自定义标签的类的时候,继承了SimpleTag接口,现在可以看看该接口有什么方法。

以下介绍的顺序,就是SimpleTag的生命周期

void    setJspContext(JspContext pc) 
设置pageContext对象,传入pageContext(一定调用)通过getJspCotext()方法得到pageContext对象

void     setParent(JspTag parent) 设置父标签对象,传入父标签对象,如果没有父标签,则不调用此方法。通过getParent()方法得到父标签对象。
void     setXXX(值)  设置属性值
void   setJspBody(JspFragment jspBody)
设置标签体内容。标签体内容封装到JspFragment对像中,然后传入JspFragment对象。

通过getJspBody()方法得到标签体内容。如果没有标签体内容,则不会调用此方法

void         doTag()    执行标签时调用的方法。(一定调用)

为了更好的弄清楚,现在打开翻译了的demo1_jsp.java源文件,发现在jsp_service()的方法中除了jsp页面向外输出的方法外,发现了其中包含了一个方法

    .......//输出语句
    out.write("   \t ");
    if (_jspx_meth_gqx_005fshowIp_005f0(_jspx_page_context))
     return;
    out.write("\r\n");
  .......//输出语句

接着在该文件的最下方又会发现该方法的详细内容,如下

//传入pageContext,pageContext可以获取其余八个内置对象
  private boolean _jspx_meth_gqx_005fshowIp_005f0(PageContext _jspx_page_context)
          throws Throwable {
    PageContext pageContext = _jspx_page_context;
    JspWriter out = _jspx_page_context.getOut();
    //  gqx:showIp 实例化该对象(前面定义的类)
    com.gqx.a_tag.ShowIpTag _jspx_th_gqx_005fshowIp_005f0 = new com.gqx.a_tag.ShowIpTag();
    org.apache.jasper.runtime.AnnotationHelper.postConstruct(_jsp_annotationprocessor, _jspx_th_gqx_005fshowIp_005f0);
    //前面看到的在SimpleTag的方法里面就有一个setJspContext方法去封装,之后在其他方法中可以通过getJspContext方法去获取对象
    _jspx_th_gqx_005fshowIp_005f0.setJspContext(_jspx_page_context);
    //就是我们覆写的doTag方法
    _jspx_th_gqx_005fshowIp_005f0.doTag();
    org.apache.jasper.runtime.AnnotationHelper.preDestroy(_jsp_annotationprocessor, _jspx_th_gqx_005fshowIp_005f0);
    return false;
  }
}

上面代码我们没有用到setJspBody方法,这个时候,可以在原来的jsp页面去添加标签内容

<gqx:showIp>gqx</gqx:showIp>

我们会发现上面的代码就发生了变化,在其中加入了setJspBody方法

//标签内容通过help封装后,由setJspBody传入,同理,可以在后面可以通过get方法去获取,然后在类中去做相关的处理
    _jspx_th_gqx_005fshowIp_005f0.setJspBody(new demo1_jspHelper( 0, _jspx_page_context, _jspx_th_gqx_005fshowIp_005f0, null));

  

时间: 2024-10-17 21:10:19

JSP自定义标签的相关文章

JSP自定义标签渲染时报Illegal to flush错误

javax.servlet.ServletException:Illegal to flush within a custom tag 此错误是因为在JSP页面中的某一个自定义标签的doStartTag或doEndTag中用了out.flush,而其他的自定义标签没有导致.可以去掉out.flush. JSP自定义标签渲染时报Illegal to flush错误,布布扣,bubuko.com

JSP 自定义标签 生命周期

1. 2. JSP 自定义标签 生命周期,布布扣,bubuko.com

JSP自定义标签开发入门《转》

JSP自定义标签开发入门 一般情况下开发jsp自定义标签需要引用以下两个包 import javax.servlet.jsp.*; import javax.servlet.jsp.tagext.*; 首先我们需要大致了解开发自定义标签所涉及到的接口与类的层次结构(其中SimpleTag接口与SimpleTagSupport类是JSP2.0中新引入的). 目标1:自定义一个用表格显示用户信息的简单标签 效果图: 在jsp页面使用此自定义标签: 假设我们有一个UserInfo的javabean,那

整理一份jsp自定义标签以及权限控制标签

jsp自定义标签使用场景因地制宜,可以实现自定义的标签输出功能也可以实现权限的管理 1:先定义标签类 1-1:页面输出标签 package com.suyin.web.jspsectag; import java.io.IOException; import javax.servlet.jsp.JspTagException; import javax.servlet.jsp.PageContext; import javax.servlet.jsp.tagext.Tag; public cla

一个简单的jsp自定义标签

学到了一个简单的jsp自定义标签,后面有更多的例子,会更新出来: 例子1: 步骤: 1.编写标签实现类: 继承javax.servlet.jsp.tagext.SimpleTagSupport; 重写doTag,实现在网页上输出: 2.在web-inf目录或其子目录下,建立helloword.tld文件,即自定义标签的说明文件 注意:标签处理类必须放在包中,不能是裸体类:不需要修改web.xml: //tld: tag lib description 标签库描述 java代码: package

JSP自定义标签配置

JSP自定义标签 <taglib> <taglib-uri>/WEB-INF/you.tld</taglib-uri> <taglib-location>/WEB-INF/you.tld</taglib-location> </taglib> 由这个配置可知,JSP自定义标签配置文件不是放在lib目录下,也不是放在classes文件夹中,更不是放在WebRoot目录下,而是放在WEB-INF目录下

JSP自定义标签开发入门

一般情况下开发jsp自定义标签需要引用以下两个包 import javax.servlet.jsp.*; import javax.servlet.jsp.tagext.*; 首先我们需要大致了解开发自定义标签所涉及到的接口与类的层次结构(其中SimpleTag接口与SimpleTagSupport类是JSP2.0中新引入的). 目标1:自定义一个用表格显示用户信息的简单标签 效果图: 在jsp页面使用此自定义标签: 假设我们有一个UserInfo的javabean,那么在JSP页面使用此标签只

基于JSP 自定义标签使用实例介绍

添加JSP自定义标签: 先添加一个tld文件到WEB-INF文件夹中<?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://

jsp自定义标签tag EL函数

原文:jsp自定义标签tagEL函数 源代码下载地址:http://www.zuidaima.com/share/1550463459052544.htm 简单易懂的自定义EL函数 tag.java </pre><p> </p><pre name="code" class="java">package com.zuidaima.tag; import java.io.IOException; import javax.

【Jsp】JSP自定义标签与MODEL1、MODEL2标准

在JSP2.0之后支持自定义标签,现在一般都是jsp2.4的版本了,所以无须考虑版本的问题.直接使用就可以了.虽然一般开发的过程中,很少会自己定义JSP标签,但是通过一个JSP自定义标签的学习,可以从一定程度上理解struts等框架把好好的JSP标签改得面目全非的机理.正如Jquery本质是Javascript一样,SSH实际上Jsp.其实也没有什么,一个简单的例子就能够完全说明如何在JSP中自定义的标签. 通过自定义标签就能够达到所谓的MODEL2标准,在展示层VIEW给别人看的网页中不得出现