java_第一年_JavaWeb(11)
自定义标签:主要是用来移除JSP页面中的java代码。
先从一个简单的案例了解其怎么移除代码:
一个正常的jsp页面:
<%@ page language="java" pageEncoding="UTF-8"%>
<!DOCTYPE HTML>
<html>
<head>
<title>输出客户端的IP</title>
</head> <body>
你的IP地址是(使用java代码获取输出):
<%
//在jsp页面中使用java代码获取客户端IP地址
String ip = request.getRemoteAddr();
out.write(ip);
%> </body>
</html>
要想将其中的代码通过自定义标签引入需要通过@taglib指令进行声明,如:
<%@ page language="java" pageEncoding="UTF-8"%>
<%@taglib uri="/xxx" prefix="ttt"%>
<!DOCTYPE HTML>
<html>
<head>
<title>输出客户端的IP</title>
</head> <body>
你的IP地址是(使用自定义标签获取输出):
<%--使用自定义标签tagname --%>
<ttt:tagname/>
</body>
</html>
其中uri是标签库的uri,prefix是jsp进行引用时的前缀,tagname是标签库中的一个标签名,用来区分不同的标签;因此,我们需定义一个标签库,用来连接JSP页面和java类(标签处理器类),如自定义一个tag.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://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
version="2.0">
<!-- 标签库的描述 -->
<description>小兆的自定义标签库测试</description>
<!--标签库的版本号 -->
<tlib-version>1.0</tlib-version>
<short-name>LzjLibrary</short-name>
<!--
为自定义标签库设置一个uri,uri以/开头,/后面的内容可以随便写,如这里的/xxx ;
在Jsp页面中引用标签库时,需要通过uri找到标签库
-->
<uri>/xxx</uri>
<!-- 一个tag标记对应一个自定义标签 -->
<tag>
<description>这个标签的作用是用来输出客户端的IP地址</description>
<!--
为标签处理器类配一个标签名,在Jsp页面中使用标签时是通过标签名来找到要调用的标签处理器类的
通过tagname就能找到对应的lzj.learn.tag.ViewIPTag类
-->
<name>tagname</name>
<!-- 标签对应的处理器类-->
<tag-class>lzj.learn.tag.ViewIPTag</tag-class>
<body-content>empty</body-content>
</tag> </taglib>
最后的一步就是编写java类了,这在开发中其实是要第一步,只是这里为了了解其流程我放到了最后一步,前面的标签库中的<tag-class>其路径要与java类相对应;如下java类(标签处理器类):
package lzj.learn.tag; import java.io.IOException; import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.Tag; public class ViewIPTag implements Tag { //接收传递进来的PageContext对象
private PageContext pageContext; @Override
public int doEndTag() throws JspException {
System.out.println("调用doEndTag()方法");
return ;
} @Override
public int doStartTag() throws JspException {
System.out.println("调用doStartTag()方法");
HttpServletRequest request =(HttpServletRequest) pageContext.getRequest();
JspWriter out = pageContext.getOut();
String ip = request.getRemoteAddr();
try {
//这里输出的时候会抛出IOException异常
out.write(ip);
} catch (IOException e) {
//捕获IOException异常后继续抛出
throw new RuntimeException(e);
}
return ;
} @Override
public Tag getParent() {
return null;
} @Override
public void release() {
System.out.println("调用release()方法");
} @Override
public void setPageContext(PageContext pageContext) {
System.out.println("setPageContext(PageContext pageContext)");
this.pageContext = pageContext;
} @Override
public void setParent(Tag arg0) { } }
- 在JSP引擎实例化标签处理器后,其处理流程是先调用setPageContext方法将JSP 页面的pageContext对象传给标签处理器,标签处理器通过pageContext对象实现和JSP的通信;
- Web容器调用setParent方法标签的父标签传给当前的标签处理器,如无父标签,则传递的参数值为null;
- 之后开始执行doStartTag方法,输出ip
- 执行完后web容器会调用doEndTag方法,至此,自定义标签执行结束;不过其标签处理器会驻留在内存中,直至停止web应用,web容器才会调用release方法;
看到这,相信你已经对自定义标签的作用和处理流程有了一定的了解,接下来是更加详细的介绍;
JspTag是所有自定义标签的父接口;没有任何属性和方法,JSP2.0后有两个子接口:Tag和SimpleTag;
Tag接口
Tag接口定义了2个重要方法(doStartTag和doEndTag)以及四个常量(EVAL_BODY_INCLUDE、SKIP_BODY(位于doStartTag方法中,决定是否要忽略自定义标签的标签体)以及EVAL_PAGE、SKIP_PAGE(位于doEndTag方法中,决定位于结束标记后面的内容是否执行));
进一步地,有IterationTag接口继承Tag接口,增加了doAfterBody方法和EVAL_BODY_AGAIN常量,执行完自定义标签的标签体后会执行doAfterBody方法,返回常量EVAL_BODY_AGAIN或SKIP_BODY,如果返回EVAL_BODY_AGAIN,标签体内容会重复执行一次,直到返回SKIP_BODY;
再进一步,有BodyTag接口继承了IterationTag接口,又多了两个方法(setBodyContent和doInitBody)和一个常量EVAL_BODY_BUFFERED;其作用是可以对标签体的运行结果进行修改,具体的流程是在执行完doStartTag方法后还可以返回这个EVAL_BODY_BUFFERED常量,这样web容器就会创建一个捕获标签体运行结果的BodyContent对象,并调用这个setBodyContent方法将其传递给标签处理器,标签处理器就可以调用特有的方法对这个BodyContent对象进行修改并控制其输出;
对应地,在JSP API中也提供了BodyTag接口的实现类BodyTagSupport,因此在编写标签处理类时可以继承和扩展BodyTagSupport类,简化开发工作;
这里给一个修改标签体运行结果的范例,其余的返回方法及返回常量大家有时间也可以实践实践:
package lzj.learn.tag; import java.io.IOException; import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyContent;
import javax.servlet.jsp.tagext.BodyTag;
import javax.servlet.jsp.tagext.BodyTagSupport;
import javax.servlet.jsp.tagext.Tag; public class TagDemo extends BodyTagSupport { /* 控制doStartTag()方法返回EVAL_BODY_BUFFERED
* @see javax.servlet.jsp.tagext.BodyTagSupport#doStartTag()
*/
@Override
public int doStartTag() throws JspException {
return BodyTag.EVAL_BODY_BUFFERED;
} @Override
public int doEndTag() throws JspException { //this.getBodyContent()得到代表标签体的bodyContent对象
BodyContent bodyContent = this.getBodyContent();
//拿到标签体
String content = bodyContent.getString();
//修改标签体里面的内容,将标签体的内容转换成大写
String result = content.toUpperCase();
try {
//输出修改后的内容
this.pageContext.getOut().write(result);
} catch (IOException e) {
throw new RuntimeException(e);
} return Tag.EVAL_PAGE;
}
}
以上介绍的Tag接口这一分支被称为传统标签,很少用来开发了,(ノ`Д)ノ!不过过程流程还是要熟悉的,有助对自定义标签的理解,用的比较多的是下面的简单标签SimpleTag!
突然发现这节写得有点多了,所以简单标签的开发还是放到下节讲解啦!!
java_第一年_JavaWeb(11)的更多相关文章
- java_第一年_JavaWeb(14)
EL :EL表达式主要用于获取数据.执行运算.获取对象.调用java方法: 获取数据 语法:"${标识符}" 会调用pageContext.findAttribute方法,从pag ...
- java_第一年_JavaWeb(13)
JSTL标签库——核心标签库 为了弥补html标签的不足,为了更加方便地在jsp页面中使用java逻辑代码,JSTL标签库因运而生,而其中的佼佼者,被恩宠最多的就是核心标签库了: 核心标签库从功能上可 ...
- java_第一年_JavaWeb(15)
Filter过滤器,Servlet API 中提供了一个Filter接口,用于实现用户在访问某个目标资源前对其进行拦截: 拦截原理:web服务器通过Filter接口调用doFilter方法,会传递一个 ...
- java_第一年_JavaWeb(12)
SimpleTag标签 定义了五个方法:setJspContext.setJspBody.setParent和getParent以及最重要的doTag方法(完成了所有的业务逻辑): setJspCon ...
- java_第一年_JavaWeb(10)
JavaWeb的两种开发模式 JSP+JavaBean框架:JavaBean负责封装数据.提供方法,JSP负责处理用户请求和显示数据:只能开发较为简单的业务: JSP+JavaBean+Servlet ...
- java_第一年_JavaWeb(9)
JavaBean是一个遵循某种特定写法的Java类,有以下特点: 必需具有一个无参的构造函数 属性必需私有化 私有化的属性必需通过public类型的方法暴露给其它程序,其方法命名也有一定的规范 范例: ...
- java_第一年_JavaWeb(8)
前面说到,JSP在运行时会被编译成Servlet源代码,通过_jspServlet方法处理请求,此时该方法会传递和提供9个与web开发相关的对象进行使用,开发人员在JSP页面通过对这些变量即可引用这9 ...
- java_第一年_JavaWeb(7)
JSP执行过程 客户端发出请求访问JSP文件 JSP Container将要访问的JSP文件转译为Servlet的源代码(转译时期),并将其编译成.class文件(编译时期): 执行编译后的.clas ...
- java_第一年_JavaWeb(6)
会话 会话:浏览器从打开一个进程访问服务器到该浏览器关闭,我们称之为一个会话: 在浏览器和服务器交互期间,会不可避免地产生一些数据,而为了为每个用户保存其对应的数据,可使用两种技术:Cookie和Se ...
随机推荐
- 前端每日实战:12# 视频演示如何用纯 CSS 创作一种文字断开的交互特效
效果预览 按下右侧的"点击预览"按钮在当前页面预览,点击链接全屏预览. https://codepen.io/zhang-ou/pen/LmjNgL 可交互视频教程 此视频是可以交 ...
- 关于mysql(Navicat premium软件中) 外键设置中“删除”和“更新”选项详解
ON DELETE restrict(约束):当在父表(即外键的来源表)中删除对应记录时,首先检查该记录是否有对应外键,如果有则不允许删除. no action:意思同restrict.即如果存在从数 ...
- HBase过滤器(转载)
HBase为筛选数据提供了一组过滤器,通过这个过滤器可以在HBase中的数据的多个维度(行,列,数据版本)上进行对数据的筛选操作,也就是说过滤器最终能够筛选的数据能够细化到具体的一个存储单元格上(由行 ...
- php shuffle()函数 语法
php shuffle()函数 语法 作用:把数组中的元素按随机顺序重新排序:富瑞华 语法:shuffle(array) 参数: 参数 描述 array 必需.规定要使用的数组. 说明:若成功则返回 ...
- Java——常用类(StringBuffer)
[StringBuffer] <1>java.lang.StringBuffer代表可变的字符序列. <2>StringBuffer和String类似,但是StringBu ...
- Codeforces 864E - Fire(dp)
原题连接:http://codeforces.com/problemset/problem/864/E 题意:一个人想从大火中带走一些东西.每次他只能带一个,耗时ti ,价值为pi, 当总时间超过di ...
- Minimum Cut
Minimum Cut Time Limit: 3000/2000 MS (Java/Others) Memory Limit: 65535/102400 K (Java/Others)Tota ...
- 第三方框架:EventBus
1 研发背景 案例:我们在主页点收藏按钮,未登录状态,跳登录界面,在登录界面跳注册页面,注册成功,关闭注册页面,关闭登录页面,回到主页,刷新item列表和登录状态. 我们一般会用到发送广播和接收广播来 ...
- Retina 屏幕与二倍图
分辨率 屏幕分辨率:指屏幕可显示的像素的个数 图像分辨率:位图图像包含的像素的个数 对于 Retina 屏它的分辨率是传统屏的两倍,而屏幕大小没有变化,所以它需要的图片的分辨率应该是传统屏幕的两倍(甚 ...
- flex embed 使用
Flex 软件中经常需要使用一些外部的资源,如图片.声音.SWF或字体,虽然你也可以在软件运行的时候引入和载入,但是也可能经常需要直接将这些资源编译(Compile)到软件中,也就是直接嵌入资源(Em ...