Servlet笔记 (七) tag

来源:互联网 发布:网络约车平台 编辑:程序博客网 时间:2024/04/29 03:10
一、EL调用普通类的静态方法
EL表达式对字符串的连接不支持
EL表达式只能调用Java类中的“静态”方法
 
1、编写一个类,提供静态方法
package com.itheima.el;
public class StringUtil {
    public static String toUpperCase(String data){
        return data.toUpperCase();
    }
}
 
2、在WEB-INF目录下,建立myfn.tld的文件(建立xml的文件,但扩展名为tld)
<?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.0</tlib-version><!-- 版本号,一般从1.0开始 -->
    <short-name>myfn</short-name><!-- 引用的短名称,最好和文件名一致,方便查找 -->
    <uri>http://www.itheima.com/jsp/el/functions</uri><!-- 名称空间,没有实际意义 -->
    <function>
        <name>toUpperCase</name><!-- 随便起,标签的名字 -->
        <function-class>com.itheima.el.StringUtil</function-class><!-- 标签处理类的全名 -->
        <!-- (方法的签名)返回的类型    方法名(参数类型) -->
        <function-signature>java.lang.String toUpperCase( java.lang.String )</function-signature>
    </function>
</taglib>
 
3、可选,(把tld文件放在WEB-INF目录,这一步可以省略)修改web.xml,增加tld文件和tld文件中的uri的对应关系。
<jsp-config>
    <taglib>
        <taglib-uri>http://www.itheima.com/jsp/el/functions</taglib-uri>
        <taglib-location>/WEB-INF/myfn.tld</taglib-location>
    </taglib>
</jsp-config>
 
4、在jsp中使用自定义的EL函数,注意要引入
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<%@ taglib uri="http://www.itheima.com/jsp/el/functions" prefix="myfn" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>EL调用普通类的静态方法</title>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
  </head>
  <body>
  <%
  request.setAttribute("data""abcd");
  request.setAttribute("d1""<hr/>");
  %>
  ${myfn:toUpperCase(data)}<br/>
  ${fn:contains(data,"a") }<br/>
  ${fn: escapeXml(d1) }
  </body>
</html>
 
二、JSTL中常用EL函数
JSTL由5部分组成:
1,core:核心标签库
2,fmt:格式化标签库
3,sql:操作数据库的标签库
4,xml:操作xml的标签库(之前有其他方式去取)
 
三、自定标签的作用:移除掉jsp中的Java脚本
 
四、自定义标签的开发步骤(与一一致)
 
标签调用过程:setParent中的爹是标签自定义的爹,没有自定义的爹就是null
注意:tld文件中,tag标签中子标签的意义:
body-content:指示标签主体内容的类型
   可选值:
        empty:没有主体内容。传统简单都适用
        JSP:有主体内容。为传统服务
        scriptless:有主体内容。为简单服务(主体内容不能出现java脚本)
        tagdependent:指示标签主体内容原封不动的传给标签处理类。
  attribute:定义标签的属性
        name:属性名称。
        required:该属性是否是必须的。true
        rtexprvalue:是否支持表达式
 
传统标签
1,编写一个标签处理类(直接实现或间接实现javax.servlet.jsp.tagext.Tag接口)
建立ShowRemoteTag.java,实现了TagSupport类,它是Tag接口的孙子
doEndTag  是结束标签,Tomcat调用这个方法
public class ShowRemoteIpTag extends TagSupport {
    public int doStartTag() throws JspException {
        //Tomcat会直接调用setPageContext()这个方法,pagContext就已经有了
        String ip = pageContext.getRequest().getRemoteAddr();
        try {//把获取的IP地址打印出来
            pageContext.getOut().write(ip);
        } catch (IOException e) {
            e.printStackTrace();
        }//return是覆盖这个方法时默认的,没有修改.
        return super.doStartTag();
    }
}
 
2,建立itheima.tld(Demo后面的设置没有写)
<?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.0</tlib-version>
    <short-name>itheima</short-name>
    <uri>http://www.itheima.com/jsp/taglib</uri>
    <tag>
        <name>showRemoteIp</name>
        <tag-class>com.itheima.jsp.tag.ShowRemoteIpTag</tag-class>
        <body-content>empty</body-content>
    </tag>
    <tag>
        <name>demo3</name>
        <tag-class>com.itheima.jsp.tag.Demo3Tag</tag-class>
        <body-content>JSP</body-content><!-- JSP中能有啥,主体内容中就可以出现啥 -->
    </tag>
</taglib>
 
3,建立2.jsp文件
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="http://www.itheima.com/jsp/tag" prefix="itheima"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>输出客户端的IP地址</title>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
  </head>
  <body>
      您的IP地址是:
      <itheima:showRemoteIp/>
  </body>
</html>
 
五、自定义标签的其他附加功能
Demo3:忽略标签中的内容
public class Demo3 extends TagSupport {
//    Tag.EVAL_BODY_INCLUDE;不忽略主体内容
//    Tag.SKIP_BODY;忽略主体内容
    public int doStartTag() throws JspException {
        return Tag.SKIP_BODY;
    }
}
 <itheima:Demo3>撒旦法</itheima:Demo3>daf
 
Demo4:忽略标签后的内容
public class Demo4 extends TagSupport {
    //Tag.EVAL_PAGE:不忽略结束标签后的JSP内容
    //Tag.SKIP_PAGE:忽略结束标签后的JSP内容
    public int doEndTag() throws JspException {
        return Tag.SKIP_PAGE;
    }//忽略的是此标签后的所有内容,包括</html>结束标签
}
<itheima:Demo4/>
Demo5:控制jsp页面重复执行    流程图:
 
public class Demo5 extends TagSupport{
    //定义一个全局变量,设定循环几次
    int num = 5;
    public int doStartTag() throws JspException {
        return Tag.EVAL_BODY_INCLUDE;
    }
    public int doAfterBody() throws JspException {
        if(num-->1){//标签会先执行一次,然后再进入循环,所以需要少循环一次
            return IterationTag.EVAL_BODY_AGAIN;
        }else{//因为普通标签运行一次就驻留内存,所以循环完毕后需要重新初始化
            num = 5;
            return Tag.SKIP_BODY;
        }
    }
}
<itheima:Demo5><hr/><br/></itheima:Demo5>
 
Demo6:修改标签中的内容(BodyTag)
 
public class Demo6 extends BodyTagSupport {
//    public int doStartTag() throws JspException {
//        //只有返回这个,Tomcat才会调用bodycontent,把主体内容存到缓存
//        return BodyTag.EVAL_BODY_BUFFERED;
//    }//好像BodyTagSupport类会自动完成这一步
    public int doEndTag() throws JspException {
        //先获取标签中的主体内容
        String content = bodyContent.getString();
        try {//拿到主体内容后,需要自己输出
            pageContext.getOut().write(content.toUpperCase());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return super.doEndTag();
    }
}
  <!-- 标签主体内容一定要有值,否则会报空指针异常 -->
  <itheima:Demo6>d</itheima:Demo6>d<hr/>
 
六、JSP中标签核心接口
传统标签很复杂,简单标签比较好
传统标签兼容性抢,简单标签必须要jsp2.0以上才可以
 
 
七、简单标签
简单标签没有start和end两个方法
简单标签没有release方法,也不会驻留内存
sitheima.tld,配置文件
    <tlib-version>1.0</tlib-version><!-- 版本号,一般从1.0开始 -->
    <short-name>sitheima</short-name><!-- 随便起,最好和文件名一致,方便查找 -->
    <uri>http://www.itheima.com/jsp/sitheima</uri><!-- 名称空间 随便起 -->
    <tag>
        <name>Demo2SimpleTag</name>
        <tag-class>com.itheima.jsp.stag.Demo2SimpleTag</tag-class>
        <body-content>empty</body-content>
    </tag>
 
Demo2:打印ip地址
public class Demo2SimpleTag extends SimpleTagSupport {
    public void doTag() throws JspException, IOException {
        //获取页面范围域对象,是本身的方法this可以省略
        PageContext pc = (PageContext) this.getJspContext();
        //获取ip地址
        String ip = pc.getRequest().getRemoteAddr();
        //需要自己输入内容
        pc.getOut().write(ip);
    }
}
<sitheima:Demo2SimpleTag/>
 
Demo3:控制jsp一部分内容是否执行
public class Demo3SimpleTag extends SimpleTagSupport {
    //什么都不执行,就代表什么都不做,包括不输入
    public void doTag() throws JspException, IOException {
    }
}
<sitheima:Demo3SimpleTag>daf</sitheima:Demo3SimpleTag>ad
 
Demo4:控制结束标签之后的jsp内容是否执行
public class Demo4SimpleTag extends SimpleTagSupport {
    public void doTag() throws JspException, IOException {
        //抛出这个“跳出页面异常”,那么这个标签之后的内容都不会执行,包括</html>
        throw new SkipPageException();
    }
}
<sitheima:Demo4SimpleTag/>
 
Demo5:页面中的内容重复执行
    <tag><!-- 配置文件 -->
        <name>Demo5SimpleTag</name>
        <tag-class>com.itheima.jsp.stag.Demo5SimpleTag</tag-class>
        <body-content>scriptless</body-content>
        <attribute>
            <name>count</name><!-- 属性名称 -->
            <required>true</required><!-- 改属性是否必须,true代表必须 -->
            <rtexprvalue>true</rtexprvalue><!-- 是否支持表达式 -->
            <!-- rt:RunTime   expr:Expression value:value 是否支持表达式:EL或Java都行 -->
        </attribute>
    </tag>
public class Demo5SimpleTag extends SimpleTagSupport {
    //定义一个变量计数。变量类型可以自动转换,但是仅限基本类型
    private int count ;
    //标签中的count属性与此方法对应,Tomcat会自动调用
    public void setCount(int count){
        this.count = count;
    }
    public void doTag() throws JspException, IOException {
//        PageContext pc = (PageContext) getJspContext();
//        JspWriter out = pc.getOut();
//        //得到主体内容
//        JspFragment jf = getJspBody();
//        jf.invoke(out);
        for(int x=0;x<count;x++){
            //与上面代码功能完全一样,主体内容依旧默认输出
            getJspBody().invoke(null);
        }
    }
}
<sitheima:Demo5SimpleTag count="5">dfa<hr/></sitheima:Demo5SimpleTag>
 
Demo6:修改页面输出
StringWriter ,有缓存,也有输出方法
public class Demo6SimpleTag extends SimpleTagSupport {
    public void doTag() throws JspException, IOException {
        //构造一个带有缓存的字符串输出流
        StringWriter sw = new StringWriter();
        JspFragment jf = getJspBody();
        jf.invoke(sw);//把主体内容关联到sw流上,进行使用
        //得到主体内容
        String content = sw.getBuffer().toString();
        //把主体内容修改toUpperCase后,输出
        PageContext pc = (PageContext) getJspContext();
        pc.getOut().write(content.toUpperCase());
    }
}
<sitheima:Demo6SimpleTag>xuziyi</sitheima:Demo6SimpleTag>xuziyi
 
八、简单标签实用案例:
开发防盗链标签
referer:上一次链接的地址(没成功)
加上标签<eitheima:referer site=http://192.168.1.250 adPage="/examples/ad.jsp"/>
建立ad.jsp(广告页面)
建立RefererSimpleTag类
 
注意,以斜线开头,就是代表当前应用路径,不以斜线开头,就是相对路径
第一种方式就是以ad.jsp开头
..代表上一级目录
.代表当前目录
 
 
开发<c:if>标签
    <tag><!-- 配置文件 -->
        <name>if</name>
        <tag-class>com.itheima.jsp.etag.IfSimpleTag</tag-class>
        <body-content>scriptless</body-content>
        <attribute>
            <name>test</name><!-- 属性名称 -->
            <required>true</required><!-- 改属性是否必须,true代表必须 -->
            <rtexprvalue>true</rtexprvalue><!-- 是否支持表达式 -->
        </attribute>
    </tag>
public class IfSimpleTag extends SimpleTagSupport {
    private boolean test;
    public void setTest(boolean test) {
        this.test = test;
    }
    public void doTag() throws JspException, IOException {
        if(test){
            //如果为真,则内容正常输出,否则主体内容不输出
            getJspBody().invoke(null);
        }
    }
}
 <%
  List cart = new ArrayList();
  cart.add("aaa");
  request.setAttribute("cart", cart);
  %>
  <eitheima:if test="${empty cart }">
      您没有购买任何商品
  </eitheima:if>
  <eitheima:if test="${!empty cart }">
      您购买的商品如下
  </eitheima:if>
 
开发<c:when><c:other>标签
每个标签都是独立的,需要在标签之间要进行数据通信,先建立一个父类标签。
<tag><!-- 配置文件 -->
        <name>ChooseSimpleTag</name>
        <tag-class>com.itheima.jsp.etag.ChooseSimpleTag</tag-class>
        <body-content>scriptless</body-content>
    </tag>
    <tag><!-- 配置文件 -->
        <name>other</name>
        <tag-class>com.itheima.jsp.etag.OtherwiseSimpleTag</tag-class>
        <body-content>scriptless</body-content>
    </tag>
    <tag><!-- 配置文件 -->
        <name>When</name>
        <tag-class>com.itheima.jsp.etag.WhenSimpleTag</tag-class>
        <body-content>scriptless</body-content>
        <attribute>
            <name>test</name><!-- 属性名称 -->
            <required>true</required><!-- 改属性是否必须,true代表必须 -->
            <rtexprvalue>true</rtexprvalue><!-- 是否支持表达式 -->
        </attribute>
    </tag>
public class ChooseSimpleTag extends SimpleTagSupport {
    //定义一个标记
    private boolean flag;
    public boolean isFlag(){
        return flag;
    }
    public void setFlag(boolean flag) {
        this.flag = flag;
    }
    public void doTag() throws JspException, IOException {
        //写出主体内容
        getJspBody().invoke(null);
    }
}
public class OtherwiseSimpleTag extends SimpleTagSupport {
    public void doTag() throws JspException, IOException {
        //为了实现标签之间的通讯,需要获取父类
        ChooseSimpleTag c = (ChooseSimpleTag) getParent();
        //通过父类的标记,来决定是否显示其主体内容
        if(!c.isFlag()){
            getJspBody().invoke(null);
        }
    }
}
public class WhenSimpleTag extends SimpleTagSupport {
    private boolean test;
    //建立方法,让Tomcat能传进参数值
    public void setTest(boolean test) {
        this.test = test;
    }
    public void doTag() throws JspException, IOException {
        if(test){
            getJspBody().invoke(null);//执行主体内容
            ChooseSimpleTag c = (ChooseSimpleTag) getParent();
            c.setFlag(test);//修改附标签的标记符号
        }
    }
}<body>
  <%
  request.setAttribute("grade""A");
  %>
  <eitheima:ChooseSimpleTag>
  <eitheima:When test="${grade=='A'}">
          成绩优秀
  </eitheima:When>
  <eitheima:other>
          还需努力
  </eitheima:other>
    </eitheima:ChooseSimpleTag>
  </body>  
 
开发迭代标签forEach1
    <tag><!-- 配置文件 -->
        <name>ForEach1</name>
        <tag-class>com.itheima.jsp.etag.ForEach1SimpleTag</tag-class>
        <body-content>scriptless</body-content>
        <attribute>
            <name>items</name><!-- 属性名称 -->
            <required>true</required><!-- 改属性是否必须,true代表必须 -->
            <rtexprvalue>true</rtexprvalue><!-- 是否支持表达式 -->
        </attribute>
        <attribute>
            <name>var</name><!-- 属性名称 -->
            <required>false</required><!-- 改属性是否必须,true代表必须 -->
            <rtexprvalue>false</rtexprvalue><!-- 是否支持表达式 -->
        </attribute>
    </tag>
public class ForEach1SimpleTag extends SimpleTagSupport {
    private List items;//注意,此变量名需与自定义标签的属性名一致
    private String var;//注意,此变量名需与自定义标签的属性名一致
    public void setItems(List items) {
        this.items = items;
    }
    public void setVar(String var) {
        this.var = var;
    }
    public void doTag() throws JspException, IOException {
        //先得到域对象,好得到值
        PageContext pc = (PageContext) getJspContext();
        for(Object e:items){
            pc.setAttribute(var, e);
            getJspBody().invoke(null);
        }
    }
}
  <body>
    <%
    List list = new ArrayList();
    list.add("aaa");
    list.add("bbb");
    list.add("ccc");
    request.setAttribute("list", list);
    %>
    <eitheima:ForEach1 items="${list}" var="v">
    ${v }<br/>
    </eitheima:ForEach1>
  </body>
 
 
建立forEach2.jsp(未做)
建立相关类
使用反射的isArray方法,判断是否为一个数组
 
 
开发html转义标签打包标签库
建立bbs.jsp
建立result.jsp
就是怎么写的,就怎么显示
 
拿到主体内容,就开始修改内容,再转发
 
 
十、JSTL中Core剩余标签
 
建立JstlCore.jsp
tablib导入
属性:default  默认输出    escapeXml,是否支持转义,支持表达式
 
tld中的,name的值:所有var都不支持表达式,value支持表达式
<c:remove var=""/>会把所有域范围内的这个值都删掉
 
<c:url   />  自动重写地址   增加session
默认情况禁用的,引用别人的上下文 context   但是没用
 
建立StringTokenizerDemo类
演示截断字符串
 
<c:forTokens >  标签一样,截断
会查  PPT里面的第八章
 
0 0
原创粉丝点击