JavaWeb-12 (自定义标签库开发&JSTL标签库)

JavaWeb-12:自定义标签库开发&JSTL标签库

自定义标签库开发

一、自定义标签简介

自定义标签主要用于移除Jsp页面中的java代码。

使用自定义标签移除jsp页面中的java代码,只需要完成以下两个步骤:

1、编写一个实现Tag接口的Java类(标签处理器类)。
2、编写标签库描述符(tld)文件,在tld文件中把标

实验:项目架构如下:

JavaWeb-12 (自定义标签库开发&JSTL标签库)_第1张图片

a.tld




    1.0
    1.2
    myjstl
    http://java.sun.com/jstl/myjstl

    
        
        showTime
        
        com.heima.taglib.ShowTime
        
        empty
    

    
        
        demo1
        
        com.heima.taglib.Demo1
        
        tagdependent
    

    
        
        demo2
        
        com.heima.taglib.Demo2
        
        tagdependent
    

    
        
        demo3
        
        com.heima.taglib.Demo3
        
        tagdependent
        
            
            count
            true
            
            true
        
    

    
        
        demo4
        
        com.heima.taglib.Demo4
        
        scriptless
    


    
        
        if
        
        com.heima.mytaglib.IfTag
        
        scriptless
        
            
            test
            true
            
            true
        
    

    
        
        choose
        
        com.heima.mytaglib.ChooseTag
        
        scriptless

    

    
        
        when
        
        com.heima.mytaglib.WhenTag
        
        scriptless
        
            
            test
            true
            
            true
        
    

    
        
        otherwise
        
        com.heima.mytaglib.OtherwiseTag
        
        scriptless
    

    
        
        foreach
        
        com.heima.mytaglib.SimpleForEachTag
        
        scriptless
        
            
            items
            true
            
            true
        
        
            
            var
            true
            
            false
        
    

    
        
        foreach1
        
        com.heima.mytaglib.ComplexForEachTag
        
        scriptless
        
            
            items
            true
            
            true
        
        
            
            var
            true
            
            false
        
    

实验1:showTime.jsp/ShowTime.java

ShowTime.java

package com.heima.taglib;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.SimpleTagSupport;

//显示当前的时间
public class ShowTime extends SimpleTagSupport{

    public void doTag() throws JspException, IOException {
        //拿到当前的时间
        Date d = new Date() ;
        //格式化时间
        String time = d.toLocaleString() ;
        //拿到输出流对象
        PageContext pageContext = (PageContext)getJspContext() ;
        pageContext.getOut().write(time) ;
    }
}

showTime.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri = "http://java.sun.com/jstl/myjstl" prefix="my" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>



  
    

    My JSP '1.jsp' starting page

    
    
        
    
    
    

  

  
           
  

在浏览器输入:http://localhost:8080/day1200taglib/showTime.jsp,结果输入页面如下:

JavaWeb-12 (自定义标签库开发&JSTL标签库)_第2张图片

分析自定义标签的执行流程。

JavaWeb-12 (自定义标签库开发&JSTL标签库)_第3张图片

二、Tag接口的执行流程

JSP引擎将遇到自定义标签时,首先创建标签处理器类的实例对象,然后按照JSP规范定义的通信规则依次调用它的方法。

1、public void setPageContext(PageContext?pc), JSP引擎实例化标签处理器后,将调用setPageContext方法将JSP页面的pageContext对象传递给标签处理器,标签处理器以后可以通过这个pageContext对象与JSP页面进行通信。

2、public void setParent(Tag?t),setPageContext方法执行完后,WEB容器接着调用的setParent方法将当前标签的父标签传递给当前标签处理器,如果当前标签没有父标签,则传递给setParent方法的参数值为null。

3、public int doStartTag(),调用了setPageContext方法和setParent方法之后,WEB容器执行到自定义标签的开始标记时,就会调用标签处理器的doStartTag方法。

4、public int doEndTag(),WEB容器执行完自定义标签的标签体后,就会接着去执行自定义标签的结束标记,此时,WEB容器会去调用标签处理器的doEndTag方法。

5、public void release(),通常WEB容器执行完自定义标签后,标签处理器会驻留在内存中,为其它请求服务器,直至停止web应用时,web容器才会调用release方法。

JavaWeb-12 (自定义标签库开发&JSTL标签库)_第4张图片

三、自定义标签功能扩展

1、自定义标签除了可以移除jsp页面java代码外,它也可以实现以下功能。

开发人员在编写Jsp页面时,经常还需要在页面中引入一些逻辑,例如:
1、控制jsp页面某一部分内容是否执行。
2、控制结束标签后的JSP内容是否执行
3、控制jsp页面内容重复执行。
4、修改页面内容输出。

2、tld文件中的四种标签体类型

EMPTY、JSP、scriptless、tagdependent

介绍tld头里标签的含义


tag标签里包括:

    //name是自定义标签的名字

    //自定义标签相关联的类名,路径全称包括文件

    //是用来描述主体内容的类型,即在页面上写上自定义标签时,包括在中间所会出现的内容。我们一般empty

四、简单标签

由于传统标签使用三个标签接口来完成不同的功能,显得过于繁琐,不利于标签技术的推广, SUN公司为降低标签技术的学习难度,在JSP 2.0中定义了一个更为简单、便于编写和调用的SimpleTag接口来实现标签的功能。实现SimpleTag接口的标签通常称为简单标签。简单标签共定义了5个方法:

setJspContext方法:用于把JSP页面的pageContext对象传递给标签处理器对象 

setParent方法:用于把父标签处理器对象传递给当前标签处理器对象 

getParent方法:用于获得当前标签的父标签处理器对象 

setJspBody方法:用于把代表标签体的JspFragment对象传递给标签处理器对象 

doTag方法:用于完成所有的标签逻辑,包括输出、迭代、修改标签体内容等。在doTag方法中可以抛出javax.servlet.jsp.SkipPageException异常,用于通知WEB容器不再执行JSP页面中位于结束标记后面的内容,这等效于在传统标签的doEndTag方法中返回Tag.SKIP_PAGE常量的情况。 

五、SimpleTag接口方法的执行顺序

当web容器开始执行标签时,会调用如下方法完成标签的初始化:

1、WEB容器调用标签处理器对象的setJspContext方法,将代表JSP页面的pageContext对象传递给标签处理器对象。

2、WEB容器调用标签处理器对象的setParent方法,将父标签处理器对象传递给这个标签处理器对象。注意,只有在标签存在父标签的情况下,WEB容器才会调用这个方法。

3、如果调用标签时设置了属性,容器将调用每个属性对应的setter方法把属性值传递给标签处理器对象。如果标签的属性值是EL表达式或脚本表达式,则WEB容器首先计算表达式的值,然后把值传递给标签处理器对象。

4、如果简单标签有标签体,容器将调用setJspBody方法把代表标签体的JspFragment对象传递进来。

执行标签时:

容器调用标签处理器的doTag()方法,开发人员在方法体内通过操作JspFragment对象,就可以实现是否执行、迭代、修改标签体的目的。

六、JspFragment类(关键!!)

javax.servlet.jsp.tagext.JspFragment类是在JSP2.0中定义的,它的实例对象代表JSP页面中的一段符合JSP语法规范的JSP片段,这段JSP片段中不能包含JSP脚本元素。

WEB容器在处理简单标签的标签体时,会把标签体内容用一个JspFragment对象表示,并调用标签处理器对象的setJspBody方法把JspFragment对象传递给标签处理器对象。JspFragment类中只定义了两个方法,如下所示:

getJspContext方法:用于返回代表调用页面的JspContext对象.

public abstract void invoke(java.io.Writer?out) 

    用于执行JspFragment对象所代表的JSP代码片段,参数out用于指定将JspFragment对象的执行结果写入到哪个输出流对象中,如果传递给参数out的值为null,则将执行结果写入到JspContext.getOut()方法返回的输出流对象中。(简而言之,可以理解为写给浏览器)

七、invoke方法详解

JspFragment.invoke方法是JspFragment最重要的方法,利用这个方法可以控制是否执行和输出标签体的内容、是否迭代执行标签体的内容或对标签体的执行结果进行修改后再输出。例如:

a. 在标签处理器中如果没有调用JspFragment.invoke方法,其结果就相当于忽略标签体内容;

b. 在标签处理器中重复调用JspFragment.invoke方法,则标签体内容将会被重复执行;

c. 若想在标签处理器中修改标签体内容,只需在调用invoke方法时指定一个可取出结果数据的输出流对象(例如StringWriter),让标签体的执行结果输出到该输出流对象中,然后从该输出流对象中取出数据进行修改后再输出到目标设备,即可达到修改标签体的目的。

实验:Demo1.java+1.jsp+servlet源码

Demo1.java

package com.heima.taglib;

import java.io.IOException;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;

//控制主体内容不显示
public class Demo1 extends SimpleTagSupport {

    @Override
    public void doTag() throws JspException, IOException {
        return ;
    }
}

1.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri = "http://java.sun.com/jstl/myjstl" prefix="my" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>



  
    

    My JSP 'index.jsp' starting page
    
    
        
    
    
    
  

  
   喜欢芙蓉姐姐

servlet源码1jsp.java如下:

package org.apache.jsp;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import java.util.*;

public final class _1_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent {

  private static final JspFactory _jspxFactory = JspFactory.getDefaultFactory();

  private static java.util.List _jspx_dependants;

  static {
    _jspx_dependants = new java.util.ArrayList(1);
    _jspx_dependants.add("/WEB-INF/a.tld");
  }

  private javax.el.ExpressionFactory _el_expressionfactory;
  private org.apache.AnnotationProcessor _jsp_annotationprocessor;

  public Object getDependants() {
    return _jspx_dependants;
  }

  public void _jspInit() {
    _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
    _jsp_annotationprocessor = (org.apache.AnnotationProcessor) getServletConfig().getServletContext().getAttribute(org.apache.AnnotationProcessor.class.getName());
  }

  public void _jspDestroy() {
  }

  public void _jspService(HttpServletRequest request, HttpServletResponse response)
        throws java.io.IOException, ServletException {

    PageContext pageContext = null;
    HttpSession session = null;
    ServletContext application = null;
    ServletConfig config = null;
    JspWriter out = null;
    Object page = this;
    JspWriter _jspx_out = null;
    PageContext _jspx_page_context = null;


    try {
      response.setContentType("text/html;charset=UTF-8");
      pageContext = _jspxFactory.getPageContext(this, request, response,
                null, true, 8192, true);
      _jspx_page_context = pageContext;
      application = pageContext.getServletContext();
      config = pageContext.getServletConfig();
      session = pageContext.getSession();
      out = pageContext.getOut();
      _jspx_out = out;

      out.write("\r\n");
      out.write("\r\n");

String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

      out.write("\r\n");
      out.write("\r\n");
      out.write("\r\n");
      out.write("\r\n");
      out.write("  \r\n");
      out.write("    \r\n");
      out.write("    \r\n");
      out.write("    My JSP 'index.jsp' starting page\r\n");
      out.write("\t\r\n");
      out.write("\t\r\n");
      out.write("\t    \r\n");
      out.write("\t\r\n");
      out.write("\t\r\n");
      out.write("\t\r\n");
      out.write("  \r\n");
      out.write("  \r\n");
      out.write("  \r\n");
      out.write("   \r\n");
      out.write("      我");
      if (_jspx_meth_my_005fdemo1_005f0(_jspx_page_context))
        return;
      out.write("
\r\n"); out.write("\r\n"); out.write(" \r\n"); out.write(" \r\n"); out.write("\r\n"); } catch (Throwable t) { if (!(t instanceof SkipPageException)){ out = _jspx_out; if (out != null && out.getBufferSize() != 0) try { out.clearBuffer(); } catch (java.io.IOException e) {} if (_jspx_page_context != null) _jspx_page_context.handlePageException(t); else log(t.getMessage(), t); } } finally { _jspxFactory.releasePageContext(_jspx_page_context); } } private boolean _jspx_meth_my_005fdemo1_005f0(PageContext _jspx_page_context) throws Throwable { PageContext pageContext = _jspx_page_context; JspWriter out = _jspx_page_context.getOut(); // my:demo1 com.heima.taglib.Demo1 _jspx_th_my_005fdemo1_005f0 = new com.heima.taglib.Demo1(); org.apache.jasper.runtime.AnnotationHelper.postConstruct(_jsp_annotationprocessor, _jspx_th_my_005fdemo1_005f0); _jspx_th_my_005fdemo1_005f0.setJspContext(_jspx_page_context); _jspx_th_my_005fdemo1_005f0.setJspBody(new Helper( 0, _jspx_page_context, _jspx_th_my_005fdemo1_005f0, null)); _jspx_th_my_005fdemo1_005f0.doTag(); org.apache.jasper.runtime.AnnotationHelper.preDestroy(_jsp_annotationprocessor, _jspx_th_my_005fdemo1_005f0); return false; } private class Helper extends org.apache.jasper.runtime.JspFragmentHelper { private javax.servlet.jsp.tagext.JspTag _jspx_parent; private int[] _jspx_push_body_count; public Helper( int discriminator, JspContext jspContext, javax.servlet.jsp.tagext.JspTag _jspx_parent, int[] _jspx_push_body_count ) { super( discriminator, jspContext, _jspx_parent ); this._jspx_parent = _jspx_parent; this._jspx_push_body_count = _jspx_push_body_count; } public boolean invoke0( JspWriter out ) throws Throwable { out.write("喜欢芙蓉姐姐"); return false; } public void invoke( java.io.Writer writer ) throws JspException { JspWriter out = null; if( writer != null ) { out = this.jspContext.pushBody(writer); } else { out = this.jspContext.getOut(); } try { this.jspContext.getELContext().putContext(JspContext.class,this.jspContext); switch( this.discriminator ) { case 0: invoke0( out ); break; } } catch( Throwable e ) { if (e instanceof SkipPageException) throw (SkipPageException) e; throw new JspException( e ); } finally { if( writer != null ) { this.jspContext.popBody(); } } } } }

通过博客顶置的a.tld文档关联后,在浏览器输入http://localhost:8080/day1200taglib/1.jsp,输出如下页面

JavaWeb-12 (自定义标签库开发&JSTL标签库)_第5张图片

发现实验中servlet的源码也没显示出被自定义标签所隐藏了的数据!

实验:控制内容不输出方法2:Demo2.java+2.jsp

Demo2.java

package com.heima.taglib;

import java.io.IOException;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.SkipPageException;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.SimpleTagSupport;

//控制结束标签后的内容不执行
public class Demo2 extends SimpleTagSupport {

    @Override
    public void doTag() throws JspException, IOException {
        //主体是要输出的
        JspFragment body = getJspBody() ;
        //第一种方式
//      //拿到out对象
//      JspWriter out = ((PageContext)getJspContext()).getOut() ;
//      //输出主体内容
//      body.invoke(out) ;

        //第二种方式
        body.invoke(null) ;

        //抛出异常
        throw new SkipPageException() ;
    }
}

2.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri = "http://java.sun.com/jstl/myjstl" prefix="my" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>



  
    

    My JSP 'index.jsp' starting page
    
    
        
    
    
    喜欢芙蓉姐姐

  

servlet源码2jsp.java如下:

package org.apache.jsp;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import java.util.*;

public final class _2_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent {

  private static final JspFactory _jspxFactory = JspFactory.getDefaultFactory();

  private static java.util.List _jspx_dependants;

  static {
    _jspx_dependants = new java.util.ArrayList(1);
    _jspx_dependants.add("/WEB-INF/a.tld");
  }

  private javax.el.ExpressionFactory _el_expressionfactory;
  private org.apache.AnnotationProcessor _jsp_annotationprocessor;

  public Object getDependants() {
    return _jspx_dependants;
  }

  public void _jspInit() {
    _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
    _jsp_annotationprocessor = (org.apache.AnnotationProcessor) getServletConfig().getServletContext().getAttribute(org.apache.AnnotationProcessor.class.getName());
  }

  public void _jspDestroy() {
  }

  public void _jspService(HttpServletRequest request, HttpServletResponse response)
        throws java.io.IOException, ServletException {

    PageContext pageContext = null;
    HttpSession session = null;
    ServletContext application = null;
    ServletConfig config = null;
    JspWriter out = null;
    Object page = this;
    JspWriter _jspx_out = null;
    PageContext _jspx_page_context = null;


    try {
      response.setContentType("text/html;charset=UTF-8");
      pageContext = _jspxFactory.getPageContext(this, request, response,
                null, true, 8192, true);
      _jspx_page_context = pageContext;
      application = pageContext.getServletContext();
      config = pageContext.getServletConfig();
      session = pageContext.getSession();
      out = pageContext.getOut();
      _jspx_out = out;

      out.write("\r\n");
      out.write("\r\n");

String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

      out.write("\r\n");
      out.write("\r\n");
      out.write("\r\n");
      out.write("\r\n");
      out.write("  \r\n");
      out.write("    \r\n");
      out.write("    \r\n");
      out.write("    My JSP 'index.jsp' starting page\r\n");
      out.write("\t\r\n");
      out.write("\t\r\n");
      out.write("\t    \r\n");
      out.write("\t\r\n");
      out.write("\t\r\n");
      out.write("\t\r\n");
      out.write("  \r\n");
      out.write("  \r\n");
      out.write("  \r\n");
      out.write("      我");
      if (_jspx_meth_my_005fdemo2_005f0(_jspx_page_context))
        return;
      out.write("芙蓉姐姐\r\n");
      out.write("      \r\n");
      out.write("  \r\n");
      out.write("\r\n");
    } catch (Throwable t) {
      if (!(t instanceof SkipPageException)){
        out = _jspx_out;
        if (out != null && out.getBufferSize() != 0)
          try { out.clearBuffer(); } catch (java.io.IOException e) {}
        if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
        else log(t.getMessage(), t);
      }
    } finally {
      _jspxFactory.releasePageContext(_jspx_page_context);
    }
  }

  private boolean _jspx_meth_my_005fdemo2_005f0(PageContext _jspx_page_context)
          throws Throwable {
    PageContext pageContext = _jspx_page_context;
    JspWriter out = _jspx_page_context.getOut();
    //  my:demo2
    com.heima.taglib.Demo2 _jspx_th_my_005fdemo2_005f0 = new com.heima.taglib.Demo2();
    org.apache.jasper.runtime.AnnotationHelper.postConstruct(_jsp_annotationprocessor, _jspx_th_my_005fdemo2_005f0);
    _jspx_th_my_005fdemo2_005f0.setJspContext(_jspx_page_context);
    _jspx_th_my_005fdemo2_005f0.setJspBody(new Helper( 0, _jspx_page_context, _jspx_th_my_005fdemo2_005f0, null));
    _jspx_th_my_005fdemo2_005f0.doTag();
    org.apache.jasper.runtime.AnnotationHelper.preDestroy(_jsp_annotationprocessor, _jspx_th_my_005fdemo2_005f0);
    return false;
  }

  private class Helper
      extends org.apache.jasper.runtime.JspFragmentHelper
  {
    private javax.servlet.jsp.tagext.JspTag _jspx_parent;
    private int[] _jspx_push_body_count;

    public Helper( int discriminator, JspContext jspContext, javax.servlet.jsp.tagext.JspTag _jspx_parent, int[] _jspx_push_body_count ) {
      super( discriminator, jspContext, _jspx_parent );
      this._jspx_parent = _jspx_parent;
      this._jspx_push_body_count = _jspx_push_body_count;
    }
    public boolean invoke0( JspWriter out ) 
      throws Throwable
    {
      out.write('喜');
      out.write('欢');
      return false;
    }
    public void invoke( java.io.Writer writer )
      throws JspException
    {
      JspWriter out = null;
      if( writer != null ) {
        out = this.jspContext.pushBody(writer);
      } else {
        out = this.jspContext.getOut();
      }
      try {
        this.jspContext.getELContext().putContext(JspContext.class,this.jspContext);
        switch( this.discriminator ) {
          case 0:
            invoke0( out );
            break;
        }
      }
      catch( Throwable e ) {
        if (e instanceof SkipPageException)
            throw (SkipPageException) e;
        throw new JspException( e );
      }
      finally {
        if( writer != null ) {
          this.jspContext.popBody();
        }
      }
    }
  }
}

通过博客顶置的a.tld文档关联后,在浏览器输入http://localhost:8080/day1200taglib/2.jsp,输出如下页面


记住该例子,关于jstl怎么输出的问题!

八、开发带属性的标签

自定义标签可以定义一个或多个属性,这样,在JSP页面中应用自定义标签时就可以设置这些属性的值,通过这些属性为标签处理器传递参数信息,从而提高标签的灵活性和复用性。

要想让一个自定义标签具有属性,通常需要完成两个任务:

1、在标签处理器中编写每个属性对应的setter方法

2、在TLD文件中描术标签的属性

为自定义标签定义属性时,每个属性都必须按照JavaBean的属性命名方式,在标签处理器中定义属性名对应的setter方法,用来接收JSP页面调用自定义标签时传递进来的属性值。 例如属性url,在标签处理器类中就要定义相应的setUrl(String url)方法。

在标签处理器中定义相应的set方法后,JSP引擎在解析执行开始标签前,也就是调用doStartTag方法前,会调用set属性方法,为标签设置属性。

实验:Demo3.java+3.jsp

Demo3.java

package com.heima.taglib;

import java.io.IOException;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.SkipPageException;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.SimpleTagSupport;

//控制主体内容重复执行
public class Demo3 extends SimpleTagSupport {

    private String count ;

    //将由服务器调用
    public void setCount(String count) {
        this.count = count;
    }

    @Override
    public void doTag() throws JspException, IOException {
        //将count转换为整形
        int length = Integer.parseInt(count) ;
        for (int i = 0; i < length; i++) {
            getJspBody().invoke(null) ;
        }
    }
}

3.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri = "http://java.sun.com/jstl/myjstl" prefix="my" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>



  
    

    My JSP 'index.jsp' starting page
    
    
        
    
    
    
  

  
   
      
            

通过博客顶置的a.tld文档关联后,在浏览器输入http://localhost:8080/day1200taglib/3.jsp,输出如下页面

JavaWeb-12 (自定义标签库开发&JSTL标签库)_第6张图片

实验:Demo4.java+4.jsp

Demo4.java

package com.heima.taglib;

import java.io.IOException;
import java.io.StringWriter;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.SkipPageException;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.SimpleTagSupport;

//改变主体内容后输出
public class Demo4 extends SimpleTagSupport {

    @Override
    public void doTag() throws JspException, IOException {
        //获取主体内容
        JspFragment body = getJspBody() ;
        //创建一个StringWriter(可以从缓冲区中拿取)
        StringWriter sw = new StringWriter() ;
        //将数据写入sw
        body.invoke(sw) ;
        //从sw里面拿出数据
        String s = sw.toString() ;
        //将数据变成大写后输出
        getJspContext().getOut().write(s.toUpperCase()) ;
    }
}

4.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri = "http://java.sun.com/jstl/myjstl" prefix="my" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>



  
    

    My JSP 'index.jsp' starting page
    
    
        
    
    
    
  

  
   
      abcde

  

通过博客顶置的a.tld文档关联后,在浏览器输入http://localhost:8080/day1200taglib/4.jsp,输出如下页面

JavaWeb-12 (自定义标签库开发&JSTL标签库)_第7张图片

九、在TLD文件中描述标签属性

tag标签子元素的attribute标签子元素用于描述自定义标签的一个属性,自定义标签所具有的每个属性都要对应一个attribute标签元素 。


    description
    aaaa
    true
    true
    ObjectType

JavaWeb-12 (自定义标签库开发&JSTL标签库)_第8张图片

案例,使用标签控制页面逻辑案例:

  • 开发标签

实验:5.jsp+IfTag.java

IfTag.java

package com.heima.mytaglib;

import java.io.IOException;
import java.io.StringWriter;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.SkipPageException;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.SimpleTagSupport;

//实现if功能
public class IfTag extends SimpleTagSupport {

    private boolean test ;

    public void setTest(boolean test) {
        this.test = test;
    }

    @Override
    public void doTag() throws JspException, IOException {
        if(test)
            //执行主体内容
            getJspBody().invoke(null) ;
    }
}

5.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri = "http://java.sun.com/jstl/myjstl" prefix="my" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>



  
    

    My JSP 'index.jsp' starting page
    
    
        
    
    
    
  

  
   
      
            ${"abc"}
      

  

通过博客顶置的a.tld文档关联后,在浏览器输入http://localhost:8080/day1200taglib/5.jsp,输出如下页面


  • 开发标签

实验:chooseTag.java+WhenTag.java+OtherwiseTag.java+6.jsp

ChooseTag.java

package com.heima.mytaglib;

import java.io.IOException;
import java.io.StringWriter;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.SkipPageException;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.SimpleTagSupport;

//实现if..else功能
public class ChooseTag extends SimpleTagSupport {

    private boolean flag = true ;


    public boolean isFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }



    @Override
    public void doTag() throws JspException, IOException {
        getJspBody().invoke(null) ;
    }
}

WhenTag.java

package com.heima.mytaglib;

import java.io.IOException;
import java.io.StringWriter;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.SkipPageException;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.SimpleTagSupport;

//实现if..else功能
public class WhenTag extends SimpleTagSupport {

    private boolean test ;

    public void setTest(boolean test) {
        this.test = test;
    }

    @Override
    public void doTag() throws JspException, IOException {
        if(test){
            getJspBody().invoke(null) ;
            //设置父标签中的变量flag设置为false
            //拿到父标签
            ChooseTag choose = (ChooseTag)getParent() ;
            choose.setFlag(false) ;
        }
    }
}

OtherwiseTag.java

package com.heima.mytaglib;

import java.io.IOException;
import java.io.StringWriter;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.SkipPageException;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.SimpleTagSupport;

//实现if..else功能
public class OtherwiseTag extends SimpleTagSupport {


    @Override
    public void doTag() throws JspException, IOException {
        //拿到父标签的flag属性,根据flag属性的值决定是否执行主体内容
        //拿到父标签
        ChooseTag choose = (ChooseTag)getParent() ;
        if(choose.isFlag())
            getJspBody().invoke(null) ;
    }
}

6.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri = "http://java.sun.com/jstl/myjstl" prefix="my" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>



  
    

    My JSP 'index.jsp' starting page
    
    
        
    
    
    
  

  
   
       
             
                   abc
              
              
                   123
            
       

  

通过博客顶置的a.tld文档关联后,在浏览器输入http://localhost:8080/day1200taglib/6.jsp,输出如下页面


注意:在WhenTag.java里ChooseTag choose = (ChooseTag)getParent() ;原因是该servlet继承了SimpleTagSupport类(不是接口),而该接口里有方法getParent(),返回的是JspTag类型,而JspTag是一个接口,而且查文档知道该接口被SimpleTagSupport类实现了,而ChooseTag也实现了SimpleTagSupport类,所以有以上代码,意思就是把符标签的类获取到并使用类中的方法,在该例子中ChooseTag充当了一个公共类的角色。

  • 开发迭代标签:实现简单循环功能/实现复杂循环功能

实验:实现简单循环功能插入,7.jsp+SimpleForEachTag.java,该例子有其传入对象类型的局限性

SimpleForEachTag.java

package com.heima.mytaglib;

import java.io.IOException;
import java.util.ArrayList;

import javax.servlet.ServletRequest;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.SimpleTagSupport;

//实现简单循环功能
public class SimpleForEachTag extends SimpleTagSupport {

    private ArrayList items ;

    private String var ;

    public void setVar(String var) {
        this.var = var;
    }

    public void setItems(ArrayList items) {
        this.items = items;
    }

    @Override
    public void doTag() throws JspException, IOException {
        int length = items.size() ;

        for (int i = 0; i < length; i++) {
            Object obj = items.get(i) ;
            //将此值存入一个域对象中
            ServletRequest request = ((PageContext)getJspContext()).getRequest() ;
            //想数据放入reqeust
            request.setAttribute(var, obj) ;

            //执行主体内容
            getJspBody().invoke(null) ;
        }
    }
}

7.jsp

<%@ page language="java" import="java.util.*,com.heima.mytaglib.*" pageEncoding="UTF-8"%>
<%@ taglib uri = "http://java.sun.com/jstl/myjstl" prefix="my" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>



  
    

    My JSP 'index.jsp' starting page
    
    
        
    
    
    
  

  
   
        <%
            List list = new ArrayList() ;
            list.add(new User("1","张无忌",20)) ;
            list.add(new User("2","乔峰",25)) ;
            list.add(new User("3","郭靖",30)) ;

            //list.add("aaaaaaa") ;
            //list.add("bbbbbbbbb") ;
            //list.add("cccccccccc") ;
            //list.add("dddddddddddd") ;

            request.setAttribute("list", list) ;//该句为了让下面的el表达式利用导航原理获取list的对象
             %>
       
            ${t.username} : ${t.age}

通过博客顶置的a.tld文档关联后,在浏览器输入http://localhost:8080/day1200taglib/7.jsp,输出如下页面

JavaWeb-12 (自定义标签库开发&JSTL标签库)_第9张图片

实验:实现复杂循环功能:8.jsp+ComplexForEachTag.java+User.java,难点!!要记住

User.java

package com.heima.mytaglib;

public class User {

    private String id ;

    private String username ;

    private int age ;

    public User() {
    }

    public User(String id, String username, int age) {
        super();
        this.id = id;
        this.username = username;
        this.age = age;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }


    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

}

ComplexForEachTag.java

package com.heima.mytaglib;

import java.io.IOException;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.SimpleTagSupport;

//实现简单循环功能
public class ComplexForEachTag extends SimpleTagSupport {

    private Object items ;

    private String var ;

    public void setVar(String var) {
        this.var = var;
    }

    public void setItems(Object items) {
        this.items = items;
    }

    @Override
    public void doTag() throws JspException, IOException {
        //定义一个集合(目的是将items中的数据放入coll中)
        Collection coll = null ;
        //判断items的具体类型,做相应操作
        if(items == null)
            return ;
        if(items instanceof List)
            coll = (List)items ;
        else if(items instanceof Map)
            coll = ((Map)items).entrySet() ;
        else if(items.getClass().isArray()){
            coll = new ArrayList() ;
            //将数组中的数据拷贝到coll中
            for (int i = 0; i < Array.getLength(items); i++) {
                coll.add(Array.get(items, i)) ;
            }
        }else{
            throw new RuntimeException("不支持的数据类型") ;
        }

        //拿到pageContext对象
        PageContext pc = (PageContext)getJspContext() ;
        for (Object object : coll) {
            pc.setAttribute(var, object) ;
            //执行主体内容
            getJspBody().invoke(null) ;
        }
    }
}

8.jsp

<%@ page language="java" import="java.util.*,com.heima.mytaglib.*" pageEncoding="UTF-8"%>
<%@ taglib uri = "http://java.sun.com/jstl/myjstl" prefix="my" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>



  
    

    My JSP 'index.jsp' starting page
    
    
        
    
    
    
  

  
   
        <%
            List list = new ArrayList() ;
            list.add(new User("1","张无忌",20)) ;
            list.add(new User("2","乔峰",25)) ;
            list.add(new User("3","郭靖",30)) ;

            //list.add("aaaaaaa") ;
            //list.add("bbbbbbbbb") ;
            //list.add("cccccccccc") ;
            //list.add("dddddddddddd") ;

            request.setAttribute("list", list) ;

            Map map = new HashMap() ;
            map.put("a", new User("1","张无忌",20)) ;
            map.put("b", new User("2","乔峰",25)) ;
            map.put("c", new User("3","郭靖",30)) ;

            request.setAttribute("map", map) ;

            String[] s = {"aaaaaaaa","bbbbbbbbbb","ccccccccc"} ;

            request.setAttribute("s", s) ;

            Set set = new HashSet() ;
            set.add("aaaaaaaa") ;
            set.add("bbbbbbb") ;
            set.add("cccccccccc") ;

            request.setAttribute("set", set) ;
             %>
       >
            ${t.key} : ${t.value.username}

通过博客顶置的a.tld文档关联后,在浏览器输入http://localhost:8080/day1200taglib/8.jsp,输出如下页面

JavaWeb-12 (自定义标签库开发&JSTL标签库)_第10张图片

JSTL标签库

一、JSTL标签库:

1、核心标签库 c:if c:forEach

2、国际化标签 国际化相关类和原理

3、数据库标签

4、XML标签

5、JSTL函数(EL函数);

实验:1.jsp

架构:

JavaWeb-12 (自定义标签库开发&JSTL标签库)_第11张图片

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri = "http://java.sun.com/jstl/core_rt" prefix = "c" %>

<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>



  
    

    My JSP 'index.jsp' starting page
    
    
        
    
    
    
  

  
       
       
<% List list = new ArrayList() ; list.add("aaaaaaa") ; list.add("bbbbbbbbb") ; list.add("cccccccccc") ; list.add("dddddddddddd") ; list.add("eeeeeeeeeee") ; request.setAttribute("list", list) ; %>

${p }:${t.index }:${t.count}

${name } <%----%>
${p }

在浏览器输入http://localhost:8080/day1201jstl/1.jsp,输出如下页面:

JavaWeb-12 (自定义标签库开发&JSTL标签库)_第12张图片

实验:2.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri = "http://java.sun.com/jstl/core_rt" prefix = "c" %>
<%@ taglib uri = "http://java.sun.com/jstl/fmt_rt" prefix = "fmt" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>



  
    

    My JSP 'index.jsp' starting page
    
    
        
    
    
    
  

       
       ${name }
       <%
            Date d = new Date() ;
            request.setAttribute("d", d) ;
       %>
       

在浏览器输入http://localhost:8080/day1201jstl/2.jsp,输出如下页面:



资源下载

你可能感兴趣的:(JavaWeb)