自定义标签jstl

自定义标签jstl

1、作用:

替换JSP页面中的java脚本(<%%>)。(官方推荐:JSP2.0开始)

2、开发步骤:

a、编写一个类,直接或简介实现javax.servlet.jsp.tagext.SimpleTag,一般选择继承javax.servlet.jsp.tagext.SimpleTagSupport,覆盖掉doTag方法

自定义标签jstl_第1张图片

package com.heima.jstl;

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

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

//演示输出当前时间
public class ShowTime extends SimpleTagSupport{

	@Override
	public void doTag() throws JspException, IOException {
		//获得当前的时间
		Date d = new Date() ;
		//获得pageContext对象
		PageContext pagecontext = (PageContext)getJspContext() ;
		//获取输出流对象
		JspWriter out = pagecontext.getOut() ;
		//向页面输出 
		out.write(d.toLocaleString()) ;
	}
}

b、在WEB-INF目录下建立一个扩展名为tld的xml文件(标签配置)(注意:不能放在lib目录下)

可以到JavaEE5Library-----jstl-1.2jar------META-INF-----c-1_0-rt.tld复制再修改

自定义标签jstl_第2张图片




  

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

	
	
	    showTime
	    
	    com.heima.jstl.ShowTime
	    
	    empty
  	


c、在JSP中使用前,先通过taglib指令导入外部的标签库



<%@ taglib uri="http://java.sun.com/myjstl" prefix = "my"%>
prefix:在页面上的短名称,随便写

  
  	   
       
       
  

3、执行原理:

SimpleTag接口中的方法:

void doTag():由服务器调用。在JSP中遇到标签时调用。

JspTaggetParent():由程序员调用。获取该标签的父标签对象。没有返回null

 

以下三个方法的共同特点:由服务器调用,在调用doTag之前就调完了。

voidsetJspBody(JspFragment jspBody):由服务器调用。传入标签的内容。

voidsetJspContext(JspContext pc):由服务器调用。传入当前页面的pageContext对象

voidsetParent(JspTag parent):由服务器调用。传入你的爹。没爹传入null

自定义标签jstl_第3张图片

4、自定义标签的详细功能(基本功)

控制页面中某部分内容不显示

jsp:

 
  	    控制标签的部分内容不显示:

我喜欢芙蓉姐姐
java:

package com.heima.jstl;

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 {
	}
}
xml:


	    demo1
	    com.heima.jstl.Demo1
	    tagdependent
  	

控制结束标签后的JSP内容不执行

jsp:


  	    控制标签的部分内容不显示:

我喜欢芙蓉姐姐哈哈哈 !!!!

java:

package com.heima.jstl;


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() ;
		//第一种办法
//		//拿到pageContext对象
//		PageContext page = (PageContext) body.getJspContext() ;
//		//拿到输出流对象
//		JspWriter out = page.getOut() ;
//		//输出主体内容
//		body.invoke(out) ;
		//第二种办法
		body.invoke(null) ; //底层会自动与getOut关联
		//为了让标签后面的内容不执行,在执行完主体内容后选择抛出一个异常
		throw new SkipPageException() ;		
	}
}

xml:


	    demo2
	    com.heima.jstl.Demo2
	    tagdependent
  	
  	


控制主体内容重复执行:带属性的标签开发

jsp:


  	    控制标签的主体内容重复执行:



java:

package com.heima.jstl;

import java.io.IOException;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;
//控制主体内容重复执行
public class Demo3 extends SimpleTagSupport {
//页面上的每个标签
	//变量名字要个属性的一样
	private int count ;

	public void setCount(int count) {
		this.count = count;
	}
	
	@Override
	public void doTag() throws JspException, IOException {
		for (int i = 0; i < count; i++) {
			getJspBody().invoke(null) ;
		}  
	}
}

xml:


	    demo3
	    com.heima.jstl.Demo3
	    scriptless
	    
	        
	    	count
	    	
	    	true
	    	 
	    	true
	    
  	


获取标签主体内容,改变后再输出

jsp:

 
    控制标签的主体内容改变后输出

${"tttt" }abcde

java:

package com.heima.jstl;

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

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
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 sw = new StringWriter() ;
		//将数据写入缓冲流中
		body.invoke(sw) ;
		//从缓冲流中拿取数据
		String s = sw.toString() ;
		//改变数据
		s = s.toUpperCase() ;
		//获取输出流对象,将数据输出到页面上
		JspWriter out = body.getJspContext().getOut() ;
		out.write(s) ;
	}
}

xml:


	    demo4
	    com.heima.jstl.Demo4
	    scriptless
  

5、tld文件中的一些配置


body-content:的取值内容

JSP:不要考虑。(给传统标签处理类用的)

empty:传统和简单标签都能用的。开始标签和结束标签没有主体内容时用。

scriptless:给简单标签用的。开始标签和结束标签有主体内容时用。但是内容不能有<%(即主体内容写的是el表达式时用)

tagdependent:给简单标签用的。告诉标签处理类,主体内容是普通的文本

 

6、开发属于自己的标签库

6.1实现if功能的标签(控制主体内容是否输出)

java:

package com.heima.jstl;

import java.io.IOException;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;
//演示模拟if语句的功能
public class IFTagDemo 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) ;
		}
	}
}

jsp:


    	控制标签的主体内容是否输出(模拟if语句功能)

${"真的" }

tld:


	    if
	    com.heima.jstl.IFTagDemo
	    scriptless
	    
	    	test
	    	true
	    	true
	    
  	

6.2实现if else功能的标签(嵌套标签案例)

jsp:

 
    	控制标签的主体内容是否输出输出(模拟ifelse语句功能)

${"真的" } ${"假的" }

java:

ChooseTagDemo:

package com.heima.jstl;

import java.io.IOException;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;
//模拟执行if else功能
public class ChooseTagDemo extends SimpleTagSupport{
	private boolean flag = true ;  //通过此变量的值来决定是否执行else部分

	public boolean isFlag() {
		return flag;
	}

	public void setFlag(boolean flag) {
		this.flag = flag;
	}
	
	@Override
	public void doTag() throws JspException, IOException {
		getJspBody().invoke(null) ;
	}
	
}

OtherwiseTagDemo:

package com.heima.jstl;

import java.io.IOException;

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

public class OtherwiseTagDemo extends SimpleTagSupport{

	@Override
	public void doTag() throws JspException, IOException {
		//拿到父标签中的变量,判断变量的值决定是否执行主体内容
		ChooseTagDemo choose = (ChooseTagDemo)getParent() ;
		if(choose.isFlag()){
			//执行else部分的主体内容
			getJspBody().invoke(null) ;
		}
	}
}

WhenTagDemo:

package com.heima.jstl;

import java.io.IOException;

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

public class WhenTagDemo extends SimpleTagSupport {

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

	@Override
	public void doTag() throws JspException, IOException {
		if(test){
			//条件为真:做两件事,1,执行主体内容  2.修改父标签中的变量的值
			getJspBody().invoke(null) ;
			//修改父标签中的变量
			ChooseTagDemo choose = (ChooseTagDemo)getParent() ;
			choose.setFlag(false) ;
		}
	}
}

tld:


	    choose
	    com.heima.jstl.ChooseTagDemo
	    scriptless
  	
  	
  	
	    when
	    com.heima.jstl.WhenTagDemo
	    scriptless
	    
	    	test
	    	true
	    	true
	    
  	
  	
  	
	    otherwise
	    com.heima.jstl.OtherwiseTagDemo
	    scriptless
  	


6.3实现for功能的标签(重复执行主体内容)

简单版:

jsp:


    	循环输出list集合中的数据

<% List list = new ArrayList() ; list.add(new User("郭靖",20)) ; list.add(new User("令狐冲",18)) ; list.add(new User("乔峰",24)) ; list.add(new User("杨过",21)) ; request.setAttribute("list", list) ; List list1 = new ArrayList() ; list1.add("aaaaaaaaa") ; list1.add("bbbbbbbb") ; list1.add("cccccccc") ; list1.add("dddddddddddd") ; list1.add("eeeeeeeeee") ; request.setAttribute("list1", list1) ; %> ${t.username } : ${t.age }

${t }

tld:


	    simpleforeach
	    com.heima.jstl.SimpleForeach
	    scriptless
	    
	    	items
	    	true
	    	true
	    
	    
	    	var
	    	true
	    	false
	    
  	

java:

package com.heima.jstl;

import java.io.IOException;
import java.util.List;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.SimpleTagSupport;
//演示模拟简单的循环(只针对list)
public class SimpleForeach extends SimpleTagSupport {

	private List items ;
	
	private String var ;   //因为var属性是充当一个键来使用的
	
	
	public List getItems() {
		return items;
	}

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

	public String getVar() {
		return var;
	}

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

	@Override
	public void doTag() throws JspException, IOException {
		//把var存入域对象中,也可以存入page中
		for (int i = 0; i < items.size(); i++) {
			//拿出来每一个对象,并把对象存储到某个域对象中
			Object obj = items.get(i) ;
			//存入域对象中
			PageContext page = (PageContext)getJspContext() ;
			page.setAttribute(var, obj) ;
			
			//立刻执行主体内容
			getJspBody().invoke(null) ;
		}
	}
}
复杂版:

jsp:

 
    	循环输出任意集合中的数据

<% List list = new ArrayList() ; list.add(new User("郭靖",20)) ; list.add(new User("令狐冲",18)) ; list.add(new User("乔峰",24)) ; list.add(new User("杨过",21)) ; request.setAttribute("list", list) ; List list1 = new ArrayList() ; list1.add("aaaaaaaaa") ; list1.add("bbbbbbbb") ; list1.add("cccccccc") ; list1.add("dddddddddddd") ; list1.add("eeeeeeeeee") ; request.setAttribute("list1", list1) ; Map map = new HashMap() ; map.put("a", new User("郭靖",20)) ; map.put("b", new User("乔峰",24)) ; map.put("c", new User("杨过",21)) ; request.setAttribute("map", map) ; String[] s = new String[]{ "aaaaaaaaaaa", "bbbbbbbb", "ccccccccc", "ddddddddddddd" } ; request.setAttribute("s", s) ; request.setAttribute("set", new HashSet()) ; request.setAttribute("name", "杨过") ; %> 测试list集合

${t.username } : ${t.age }

测试map集合

${p.key } :${p.value.username } :${p.value.age }
测试数组

${str }
测试set集合

<%-- ${str }
--%> 测试字符串类型

<%-- ${str }
--%>

tld:


	    foreach
	    com.heima.jstl.ComplexForEachTagDemo
	    scriptless
	    
	    	items
	    	true
	    	true
	    
	    
	    	var
	    	true
	    	false
	    
  	

java:

package com.heima.jstl;

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

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.SimpleTagSupport;
//演示复杂的循环(针对任意集合类型)
public class ComplexForEachTagDemo extends SimpleTagSupport {
	
	private Object items ;
	
	private String var ;
	
	public Object getItems() {
		return items;
	}

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

	public String getVar() {
		return var;
	}

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

	@Override
	public void doTag() throws JspException, IOException {
		//把所有集合中的数据都放入list里面,最终只需对list进行循环
		Collection list = null ;
		
		//判断items的具体类型,然后拷贝数据到list中
		if(items instanceof List){
			list = new ArrayList((List)items) ;
		}else if(items instanceof Map){
			list = new ArrayList() ;
			//强转为map
			Map map = (Map)items ;
			for (Object obj : map.entrySet()) {
				list.add(obj) ;
			}
		}else if(items.getClass().isArray()){
			list = new ArrayList() ;
			//从数组中拷贝数据到list中
			for (int i = 0; i < Array.getLength(items); i++) {
				list.add(Array.get(items, i)) ;
			}
		}else if(items instanceof Set){
			throw new RuntimeException("不支持set类型") ;
		}else{
			throw new RuntimeException("不支持的数据类型,应当传入集合类型") ;
		}
		Iterator itr = list.iterator() ;
		PageContext page = (PageContext)getJspContext() ;
		while(itr.hasNext()){
			Object obj = itr.next() ;
			//将数据存入域对象
			page.setAttribute(var, obj) ;
			//执行主体内容
			getJspBody().invoke(null) ;
		}
	}
}

JSTL中的(核心)标签

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

<%@ taglib uri = "http://java.sun.com/jstl/core_rt" prefix="c"%>

6.jsp:

 
  	   <%
  	   	   request.setAttribute("name", "张无忌") ;
  	   
  	   	   List list = new ArrayList() ;
  	   	   list.add("aaaaaaaaaa") ;
  	   	   list.add("bbbbbbbbbbbb") ;
  	   	   list.add("ccccccc") ;
  	   	   list.add("ddddddddddd") ;
  	   	   list.add("eeeeeeeeeee") ;
  	   	   
  	   	   request.setAttribute("list", list) ;
  	   %>
       
       


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

不要求掌握:
${p }
${name }

7.jsp:


		${param.name }       
  


你可能感兴趣的:(JavaWeb)