JavaWeb-12 (自定义标签库开发&JSTL标签库)
来源:互联网 发布:文华震荡交易系统源码 编辑:程序博客网 时间:2024/05/29 07:28
JavaWeb-12:自定义标签库开发&JSTL标签库
自定义标签库开发
一、自定义标签简介
自定义标签主要用于移除Jsp页面中的java代码。
使用自定义标签移除jsp页面中的java代码,只需要完成以下两个步骤:
1、编写一个实现Tag接口的Java类(标签处理器类)。2、编写标签库描述符(tld)文件,在tld文件中把标
实验:项目架构如下:
a.tld
<?xml version="1.0" encoding="utf-8" ?><!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"><taglib> <tlib-version>1.0</tlib-version> <jsp-version>1.2</jsp-version> <short-name>myjstl</short-name> <uri>http://java.sun.com/jstl/myjstl</uri> <tag> <!-- name是自定义标签的名字 --> <name>showTime</name> <!--自定义标签相关联的类名--> <tag-class>com.heima.taglib.ShowTime</tag-class> <!-- body-content是用来描述主体内容的类型 --> <body-content>empty</body-content> </tag> <tag> <!-- name是自定义标签的名字 --> <name>demo1</name> <!--自定义标签相关联的类名--> <tag-class>com.heima.taglib.Demo1</tag-class> <!-- body-content是用来描述主体内容的类型 --> <body-content>tagdependent</body-content> </tag> <tag> <!-- name是自定义标签的名字 --> <name>demo2</name> <!--自定义标签相关联的类名--> <tag-class>com.heima.taglib.Demo2</tag-class> <!-- body-content是用来描述主体内容的类型 --> <body-content>tagdependent</body-content> </tag> <tag> <!-- name是自定义标签的名字 --> <name>demo3</name> <!--自定义标签相关联的类名--> <tag-class>com.heima.taglib.Demo3</tag-class> <!-- body-content是用来描述主体内容的类型 --> <body-content>tagdependent</body-content> <attribute> <!-- 属性的名字 --> <name>count</name> <required>true</required> <!-- rtexprvalue的含义是属性的值是否支持el表达式的写法 --> <rtexprvalue>true</rtexprvalue> </attribute> </tag> <tag> <!-- name是自定义标签的名字 --> <name>demo4</name> <!--自定义标签相关联的类名--> <tag-class>com.heima.taglib.Demo4</tag-class> <!-- body-content是用来描述主体内容的类型 --> <body-content>scriptless</body-content> </tag> <tag> <!-- name是自定义标签的名字 --> <name>if</name> <!--自定义标签相关联的类名--> <tag-class>com.heima.mytaglib.IfTag</tag-class> <!-- body-content是用来描述主体内容的类型 --> <body-content>scriptless</body-content> <attribute> <!-- 属性的名字 --> <name>test</name> <required>true</required> <!-- rtexprvalue的含义是属性的值是否支持el表达式的写法 --> <rtexprvalue>true</rtexprvalue> </attribute> </tag> <tag> <!-- name是自定义标签的名字 --> <name>choose</name> <!--自定义标签相关联的类名--> <tag-class>com.heima.mytaglib.ChooseTag</tag-class> <!-- body-content是用来描述主体内容的类型 --> <body-content>scriptless</body-content> </tag> <tag> <!-- name是自定义标签的名字 --> <name>when</name> <!--自定义标签相关联的类名--> <tag-class>com.heima.mytaglib.WhenTag</tag-class> <!-- body-content是用来描述主体内容的类型 --> <body-content>scriptless</body-content> <attribute> <!-- 属性的名字 --> <name>test</name> <required>true</required> <!-- rtexprvalue的含义是属性的值是否支持el表达式的写法 --> <rtexprvalue>true</rtexprvalue> </attribute> </tag> <tag> <!-- name是自定义标签的名字 --> <name>otherwise</name> <!--自定义标签相关联的类名--> <tag-class>com.heima.mytaglib.OtherwiseTag</tag-class> <!-- body-content是用来描述主体内容的类型 --> <body-content>scriptless</body-content> </tag> <tag> <!-- name是自定义标签的名字 --> <name>foreach</name> <!--自定义标签相关联的类名--> <tag-class>com.heima.mytaglib.SimpleForEachTag</tag-class> <!-- body-content是用来描述主体内容的类型 --> <body-content>scriptless</body-content> <attribute> <!-- 属性的名字 --> <name>items</name> <required>true</required> <!-- rtexprvalue的含义是属性的值是否支持el表达式的写法 --> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <!-- 属性的名字 --> <name>var</name> <required>true</required> <!-- rtexprvalue的含义是属性的值是否支持el表达式的写法 --> <rtexprvalue>false</rtexprvalue> </attribute> </tag> <tag> <!-- name是自定义标签的名字 --> <name>foreach1</name> <!--自定义标签相关联的类名--> <tag-class>com.heima.mytaglib.ComplexForEachTag</tag-class> <!-- body-content是用来描述主体内容的类型 --> <body-content>scriptless</body-content> <attribute> <!-- 属性的名字 --> <name>items</name> <required>true</required> <!-- rtexprvalue的含义是属性的值是否支持el表达式的写法 --> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <!-- 属性的名字 --> <name>var</name> <required>true</required> <!-- rtexprvalue的含义是属性的值是否支持el表达式的写法 --> <rtexprvalue>false</rtexprvalue> </attribute> </tag></taglib>
实验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+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html> <head> <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>"> <title>My JSP '1.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css"> --> </head> <body> <my:showTime /> </body></html>
在浏览器输入:http://localhost:8080/day1200taglib/showTime.jsp,结果输入页面如下:
分析自定义标签的执行流程。
二、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方法。
三、自定义标签功能扩展
1、自定义标签除了可以移除jsp页面java代码外,它也可以实现以下功能。
开发人员在编写Jsp页面时,经常还需要在页面中引入一些逻辑,例如:1、控制jsp页面某一部分内容是否执行。2、控制结束标签后的JSP内容是否执行3、控制jsp页面内容重复执行。4、修改页面内容输出。
2、tld文件中的四种标签体类型
EMPTY、JSP、scriptless、tagdependent介绍tld头里标签的含义<tag></tag>tag标签里包括: <name>//name是自定义标签的名字 <tag-class>//自定义标签相关联的类名,路径全称包括文件 <body-content>//是用来描述主体内容的类型,即在页面上写上自定义标签时,包括在中间所会出现的内容。我们一般<body-content>empty</body-content>
四、简单标签
由于传统标签使用三个标签接口来完成不同的功能,显得过于繁琐,不利于标签技术的推广, 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+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html> <head> <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>"> <title>My JSP 'index.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css"> --> </head> <body> <!-- 控制部分内容不显示 --> 我<my:demo1>喜欢芙蓉姐姐</my:demo1><br> </body></html>
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("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\r\n"); out.write("<html>\r\n"); out.write(" <head>\r\n"); out.write(" <base href=\""); out.print(basePath); out.write("\">\r\n"); out.write(" \r\n"); out.write(" <title>My JSP 'index.jsp' starting page</title>\r\n"); out.write("\t<meta http-equiv=\"pragma\" content=\"no-cache\">\r\n"); out.write("\t<meta http-equiv=\"cache-control\" content=\"no-cache\">\r\n"); out.write("\t<meta http-equiv=\"expires\" content=\"0\"> \r\n"); out.write("\t<meta http-equiv=\"keywords\" content=\"keyword1,keyword2,keyword3\">\r\n"); out.write("\t<meta http-equiv=\"description\" content=\"This is my page\">\r\n"); out.write("\t<!--\r\n"); out.write("\t<link rel=\"stylesheet\" type=\"text/css\" href=\"styles.css\">\r\n"); out.write("\t-->\r\n"); out.write(" </head>\r\n"); out.write(" \r\n"); out.write(" <body>\r\n"); out.write(" <!-- 控制部分内容不显示 -->\r\n"); out.write(" 我"); if (_jspx_meth_my_005fdemo1_005f0(_jspx_page_context)) return; out.write("<br>\r\n"); out.write("\r\n"); out.write(" \r\n"); out.write(" </body>\r\n"); out.write("</html>\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,输出如下页面
发现实验中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+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html> <head> <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>"> <title>My JSP 'index.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css"> --> </head> <body> 我<my:demo2>喜欢</my:demo2>芙蓉姐姐 </body></html>
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("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\r\n"); out.write("<html>\r\n"); out.write(" <head>\r\n"); out.write(" <base href=\""); out.print(basePath); out.write("\">\r\n"); out.write(" \r\n"); out.write(" <title>My JSP 'index.jsp' starting page</title>\r\n"); out.write("\t<meta http-equiv=\"pragma\" content=\"no-cache\">\r\n"); out.write("\t<meta http-equiv=\"cache-control\" content=\"no-cache\">\r\n"); out.write("\t<meta http-equiv=\"expires\" content=\"0\"> \r\n"); out.write("\t<meta http-equiv=\"keywords\" content=\"keyword1,keyword2,keyword3\">\r\n"); out.write("\t<meta http-equiv=\"description\" content=\"This is my page\">\r\n"); out.write("\t<!--\r\n"); out.write("\t<link rel=\"stylesheet\" type=\"text/css\" href=\"styles.css\">\r\n"); out.write("\t-->\r\n"); out.write(" </head>\r\n"); out.write(" \r\n"); out.write(" <body>\r\n"); out.write(" 我"); if (_jspx_meth_my_005fdemo2_005f0(_jspx_page_context)) return; out.write("芙蓉姐姐\r\n"); out.write(" \r\n"); out.write(" </body>\r\n"); out.write("</html>\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+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html> <head> <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>"> <title>My JSP 'index.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css"> --> </head> <body> <!-- 控制主体内容重复执行 --> <my:demo3 count = "5"> <hr> </my:demo3> </body></html>
通过博客顶置的a.tld文档关联后,在浏览器输入http://localhost:8080/day1200taglib/3.jsp,输出如下页面
实验: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+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html> <head> <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>"> <title>My JSP 'index.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css"> --> </head> <body> <!-- 改变主体内容后输出 --> <my:demo4>abcde</my:demo4> </body></html>
通过博客顶置的a.tld文档关联后,在浏览器输入http://localhost:8080/day1200taglib/4.jsp,输出如下页面
九、在TLD文件中描述标签属性
tag标签子元素的attribute标签子元素用于描述自定义标签的一个属性,自定义标签所具有的每个属性都要对应一个attribute标签元素 。
<attribute> <description>description</description> <name>aaaa</name> <required>true</required> <rtexprvalue>true</rtexprvalue> <type>ObjectType</type></attribute>
案例,使用标签控制页面逻辑案例:
- 开发<c:if>标签
实验: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+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html> <head> <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>"> <title>My JSP 'index.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css"> --> </head> <body> <!-- 实现if功能 --> <my:if test = "${10>5 }"> ${"abc"} </my:if> </body></html>
通过博客顶置的a.tld文档关联后,在浏览器输入http://localhost:8080/day1200taglib/5.jsp,输出如下页面
- 开发<c:when><c:otherwise>标签
实验: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+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html> <head> <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>"> <title>My JSP 'index.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css"> --> </head> <body> <!-- 实现if功能 --> <my:choose> <my:when test = "${10<5 }"> abc </my:when> <my:otherwise> 123 </my:otherwise> </my:choose> </body></html>
通过博客顶置的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+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html> <head> <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>"> <title>My JSP 'index.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css"> --> </head> <body> <!-- 实现循环功能 --> <% List<User> list = new ArrayList<User>() ; 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的对象 %> <my:foreach items = "${list}" var = "t"><!--然后获取到了对象之后再传到foreach的属性里 --> ${t.username} : ${t.age}<br> </my:foreach> </body></html>
通过博客顶置的a.tld文档关联后,在浏览器输入http://localhost:8080/day1200taglib/7.jsp,输出如下页面
实验:实现复杂循环功能: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+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html> <head> <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>"> <title>My JSP 'index.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css"> --> </head> <body> <!-- 实现循环功能 --> <% List<User> list = new ArrayList<User>() ; 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<String,User> map = new HashMap<String,User>() ; 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<String> set = new HashSet<String>() ; set.add("aaaaaaaa") ; set.add("bbbbbbb") ; set.add("cccccccccc") ; request.setAttribute("set", set) ; %> <my:foreach1 items = "${map}" var = "t"><!--更改el表达式里的集合名,切换来实验! -->> ${t.key} : ${t.value.username}<br> </my:foreach1> </body></html>
通过博客顶置的a.tld文档关联后,在浏览器输入http://localhost:8080/day1200taglib/8.jsp,输出如下页面
JSTL标签库
一、JSTL标签库:
1、核心标签库 c:if c:forEach
2、国际化标签 国际化相关类和原理
3、数据库标签
4、XML标签
5、JSTL函数(EL函数);
实验:1.jsp
架构:
<%@ 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+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html> <head> <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>"> <title>My JSP 'index.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css"> --> </head> <body> <!-- 输出数据 --> <c:out value="<font color = red>abcd</font>" default="张三" escapeXml="true"></c:out><br> <!-- 条件语句 --> <% List<String> list = new ArrayList<String>() ; list.add("aaaaaaa") ; list.add("bbbbbbbbb") ; list.add("cccccccccc") ; list.add("dddddddddddd") ; list.add("eeeeeeeeeee") ; request.setAttribute("list", list) ; %> <c:if test="${not empty list}"> <c:out value="不为空"></c:out> </c:if> <br> <c:choose> <c:when test="${ not empty list}"> <c:out value="不为空"></c:out> </c:when> <c:otherwise> <c:out value="为空"></c:out> </c:otherwise> </c:choose> <br> <c:forEach items="${list }" var="p" begin="1" end="3" step="2" varStatus="t"> ${p }:${t.index }:${t.count}<br> </c:forEach> <hr> <!-- 定义变量 --> <c:set var="name" value="张三丰" scope="session" /> ${name } <!-- 请求重定向 --> <%--<c:redirect url="2.jsp"></c:redirect>--%> <hr> <!-- 拆分字符串,循环 --> <c:forTokens items="a,b,c,d,e" delims="," var="p"> ${p }<br> </c:forTokens> </body></html>
在浏览器输入http://localhost:8080/day1201jstl/1.jsp,输出如下页面:
实验: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+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html> <head> <base href="http://blog.163.com/faith_yee/blog/<%=basePath%>"> <title>My JSP 'index.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/styles.css"> --> </head> <body> ${name } <% Date d = new Date() ; request.setAttribute("d", d) ; %> <fmt:formatDate value="${d}" dateStyle="long"/><br> <fmt:formatNumber value="12345.12" pattern="###,###.##" /> </body></html>
在浏览器输入http://localhost:8080/day1201jstl/2.jsp,输出如下页面:
资源下载
- JavaWeb-12 (自定义标签库开发&JSTL标签库)
- 开发自定义 jstl标签库
- JavaWeb学习篇之----自定义标签&&JSTL标签库详解
- JavaWeb学习篇之----自定义标签&&JSTL标签库详解
- JavaWeb学习篇之----自定义标签&&JSTL标签库详解
- JavaWeb学习篇之----自定义标签&&JSTL标签库详解
- JavaWeb学习篇之----自定义标签&&JSTL标签库详解
- JSTL标签库,自定义标签
- javaweb之jstl标签库
- JavaWeb之JSTL标签库
- JavaWeb---JSTL标签库(core标签库)
- 自定义jstl标签库
- 自定义jstl标签库
- 自定义 JSTL标签库
- web day13 JSTL标签库(c标签,自定义标签),MVC设计模式,JavaWeb经典三层框架
- JavaWeb开发第8章标准标签库(JSTL)之一
- JAVAWEB开发之JSTL标签库的使用、 自定义EL函数、自定义标签(带属性的、带标签体的)
- JAVAWEB开发之JSTL标签库的使用、 自定义EL函数、自定义标签(带属性的、带标签体的)
- 简析android:installLocation
- Android通讯录管理二之通话记录获取
- 41个响应式HTML5免费网站模板
- 在Ubuntu中安装MySQL
- JavaScript Tween算法及缓动效果
- JavaWeb-12 (自定义标签库开发&JSTL标签库)
- WebSocket客户端
- 初探Object-c 3 :多态,动态类型,动态绑定
- ubuntu 下minicom安装及配置
- Android网络请求缓存,本地数据缓存流程图
- 添加本地的Jar文件到Maven库
- 素数回文 HDU 1431
- 朴素贝叶斯分类
- 敌兵布阵(线段树)