`
cqh520llr
  • 浏览: 510264 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
文章分类
社区版块
存档分类
最新评论

jstl自定义标签-转载

 
阅读更多
开发自定义标记需要有两个组件:
1、一个是描述标记特征的标记库描述文件(TLD文件)
2、另一个是Java类,也称为标记处理器,为了完成标记的行为,JSP容器要执行标记处理器。
自定义标签实现过程:
 1、写标签处理器类:TestTag.java。
 2、写tld文档:用来指定标签的名字,标签库等。
 3、用JSP来测试(指定标签库的位置tld,指定前缀名,使用标签)。

首先编写标签处理器类,标签处理器类需要继承javax.servlet.jsp.tagext.TagSupport或者javax.servlet.jsp.tagext.BodyTagSupport,二者区别暂时不知道,如果有高手知道,请给与指导,谢谢先。一般实现doStartTag和doEndTag方法,例如:

public class ExampleTag extends TagSupport{
                 public int doStartTag(){
                    //当处理开始标记的时候调用该方法
                }
               public int doEndTag(){
                       //当处理结束标记的时候调用该方法
               }
}

doStartTag方法和doEndTag方法的返回值说明:

SKIP_BODY:跳过自定义标签间的代码;
       SKIP_PAGE:跳过在此之后的所有页面内容;
       EVAL_BODY_INCLUDE:执行自定义标签间内容;
       EVAL_BODY_AGAIN:再次执行自定义标签间内容;
       EVAL_PAGE:执行标签后页面内容;

常用的返回值为:EVAL_BODY_INCLUDE。

常用的属性有pageContex。

例如:

package com.test;
       import java.io.IOException;
       import javax.servlet.jsp.tagext.BodyTagSupport;
       public class TestAttributeTag extends BodyTagSupport {

//自定义标签支持带参数
      private String name;
      public String getName() {
                return name;
      }
      public void setName(String name) {
                this.name = name;
      }
      public int doStartTag(){
                try {
                              pageContext.getOut().print("Hello "+name);
                } catch (IOException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                }
                return EVAL_BODY_INCLUDE;
     }
     public int doEndTag(){
                return  EVAL_BODY_INCLUDE;
      }
}

然后讨论一下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>  //标签依赖jsp的版本
 <short-name>zl</short-name>  //默认前缀名称
 <uri>http://www.test.com</uri>  //指定标签库德uri
 <tag>
  <name>testtag</name>         //标签名称
  <tag-class>com.test.TestAttributeTag</tag-class>    //标签处理器类
  <body-content>JSP</body-content>                      //标签主体内容,一般选择JSP
  <attribute>                                                           //标签的参数name
   <name>name</name>
   <required>true</required>                                //参数是否必须,true表示必须,false反之
   <rtexprvalue>true</rtexprvalue>                       //是否支持EL表达式
   <type>java.lang.String</type>                         //参数类型
   <description>用户名称</description>             //参数描述
  </attribute>
 </tag>
</taglib>

最后用jsp页面测试自定义标签,例如:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="zl" uri="http://www.test.com" %>
<%
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="<%=basePath%>">   
    <title>My JSP 'ZidingyiTag.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="styles.css">
 -->
  </head> 
  <body>
    This is my JSP page. <br>   
    <zl:testtagname="test"></zl:testtag>  
  </body>
</html>

例子比较简单,有什么不对地方,欢迎大家批评!



仅仅是个人的经验
不过希望对大家有帮助
先解释一下自定义标签的用法
网上粘来一段

自定义函数库步骤:
1.定义类和方法(方法必须是public static)
public class MyFunctions {
public static String testMyfn(String str) {
return "i am " + str;
}
}
2.编写自定义tld文件,并且将此文件放到WEB-INF目录下或WEB-INF任意子目录下
<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
version="2.0">
<description>myfn 1.1 functions library</description>
<display-name>myfn functions</display-name>
<tlib-version>1.0</tlib-version>
<short-name>myfn</short-name>
<uri>http://hi.baidu.com/2008_pc/functions</uri>
<function>
<name>testMyfn</name>
<function-class>com.struts.functions.MyFunctions</function-class>
<function-signature>java.lang.String testMyfn(java.lang.String)</function-signature>
</function>
</taglib>
3.在页面中采用taglib指令引入自定义函数库
<%@ taglib prefix="myfn" uri="http://hi.baidu.com/2008_pc/functions" %>
4.在struts的JstlFnAction里面设置值
request.setAttribute("name", "shiyuhao");
5.调用
${myfn:testMyfn(name) }
输出结果:i am shiyuhao

好了也就是说我们写了一个类 类里有个方法为static就行了ok
简单但是也有其他的情况
A:
jstl有这样一个特性 即 某对象instance存在一个getSomeThings()的方法 那么只要调用${instance.someThings}就行了
那么 调用自定义函数的时机就很明确了
假设 我现在某对象中需要获取一个List的长度,这个很麻烦,因为List类型没有提供给我们getSize方法
那么 我们可以调用fn 也可以自己写自定义函数
但是在这种情况下没必要 因为 我们如过能获取对象的引用 那么 只需在对象中加入 getListSzie()方法就行了
那么总结出jstl的自定义函数的特性
即在需要传参后才能确定返回值的情况下 我们只好使用自定义函数 如果不要传入参数 那么 写一个getter就可以了
B:
自定义函数情况下 我们肯传入一个List<String>或者 List<自定义类>
那么看看配置文件
假设一个方法 getMax() 获取List<String>中的最小值
传入一个List<String> 返回一个最大的String
其中一句
<function-signature>java.lang.String getMax(java.util.List<java.lang.String>)</function-signature>
好吧 如果你使用eclipse 那么一个大红叉叉已经呈现在眼前了
因为<>会在xml中解释成为一个标示符
简单的跳过去就行
写成
<function-signature>java.lang.String getMax(java.util.List)</function-signature>
然后在方法里去强制转换 这就没问题了
C:
我们经常出表的时候要去计算和
当然 有人说 加和最好在sql里写好
……我记得我一跳sql本来30行就ok了 为了在sql计算 合计 小记 累计 平均 加权平均
写到了快200行
复杂的中国式表我们不去讨论 客户的要求一定得满足
那么我们怎么办
其实页面上累加是非常简单的,如果你不用jstl的话轻松点
但是代码很难看 难看的代码 我们写了干嘛
假设 我需要列出一个表中的列累加
设 行row 列col
这个表就复杂
简化为两种情况
划一下看看
12
首先 构造我们的vo 从dao里出来以后,我们的数据室这样一个对象的List
class Inner{
private String row1;
private String row2;
private double value;//这个double不对 下面再说O(∩_∩)O
}
第一种情况下 我们只要设置一个变量 去累加就行了
第二种情况很麻烦,因为合计在数据最上头 那我们数据还没列出来呢 怎么累加
我们在仅仅讨论jstl的情况下
情况1可以用<c:set >这个标签来做累加
页面中用<c:forEach>去循环 每次<c:set  value=${var+新的值 } var='var'/>
情况2 我们可以……还是用<c:forEach>去循环 每次<c:set  value=${var+新的值 } var='var'/>
然后下面条条 在循环一次就好了
不过这样到底好么 页面中如果有多个累加 就必须增加多个<c:set>这样使得页面相当不整洁
考虑效率方面 反正是循环整个list去累加
因此 使用自定义函数取累加 效率上一样的 再加上迭代器比较好写 嘿嘿 写个自定义函数 不是更好嘛
D:
实际上 上面个两个表中 还存在精度问题
如同上例
class Inner{
private String row1;
private String row2;
private double value;//就是这个
}
jstl和java一样 实际上jsp中有自定义标签的说法,我是说jsp去写一个标签的意思
(有的教程上没,那么 推荐headfirst的jsp&servlet)
java本身对数据处理很糟搞,浮点型 或者double的精度都不能满足实际数据的需求
用<c:set>就相当于request.setAttribute
这样的累加无异于
double a = 0;
double b = 1;
a = a+b;
数据精度绝对会错
先讨论jstl的简单做法,我们知道
有一个<fmt:formatNumber value= pattern=/>这个value是一个字符串,所以个人建议在页面要输出的全部值都用String类型 这个类改一下
class Inner{
private String row1;
private String row2;
private Stringvalue;
}
相加的时候 <c:set value=<fmt:formatNumber>inner.value+var</fmt:formatNumber> var=‘var’/>
这里需要注意一下 fmt的四舍五入
因为默认情况下是4舍6入5奇偶
"4舍6入5奇偶":
<fmt:formatNumber  value="${1170.5}"  pattern="#,###,###,###"/>
"4舍5入":
<fmt:formatNumber  value="${1170.5 + 0.0001}"  pattern="#,###,###,###"/>
还得加个量才行
E:
那么实际上依然存在数据的精度问题,因为累加的时候去设置大量的<c:set>使页面不整洁
除此之外,为了显示出一个四舍五入的数,需要引入大量标签
因此个人建议的方法是 使用自定义标签
BigDecimal是个好东西,可以通过一个字符串来构造一个精确的数(实际上 也只有字符串是精确的)
而自定义函传入的参数恰恰又是字符串,这样 定义自己的累加函数
假设一个稍微复杂的例子
有多个班级 1 2 3
假设列出每个班级的人数 和学费的数目
做成如下表格

这个是典型的中国是报表
我们舍去dao部分
如下代码
vo:
import java.util.ArrayList;
import java.util.List;
public class StudentList {
private List<Inner> list = new ArrayList<Inner>();
public class Inner{
private String classNumber;//班级编号
private String personNumber;//班级人数
private String price;//钱数
public String getClassNumber() {
return classNumber;
}
public void setClassNumber(String classNumber) {
this.classNumber = classNumber;
}
public String getPersonNumber() {
return personNumber;
}
public void setPersonNumber(String personNumber) {
this.personNumber = personNumber;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
}
public List<Inner> getList() {
return list;
}
public void setList(List<Inner> list) {
this.list = list;
}
}
request.setAttribute("vo",list);
扔到了页面后 第一行需要显示合计
写一个自定义函数
class JSTLUtils{
public static String getPersonNumberSum(List list){
List<StudentList.Inner> innerList = (List<StudentList.Inner>)list;
Iterator<StudentList.Inner> iterator = innerList.iterator();
BigDecimal resultBigDecimal = new BigDecimal(0);
while(iterator.hasNext()){
StudentList.Inner inner = iterator.next();
BigDecimal innerBigDecimal = new BigDecimal(inner.getPersonNumber());
resultBigDecimal = resultBigDecimal.add(innerBigDecimal);
}
return resultBigDecimal.toString();
}
public static String getPriceSum(List list){
List<StudentList.Inner> innerList = (List<StudentList.Inner>)list;
Iterator<StudentList.Inner> iterator = innerList.iterator();
BigDecimal resultBigDecimal = new BigDecimal(0);
while(iterator.hasNext()){
StudentList.Inner inner = iterator.next();
BigDecimal innerBigDecimal = new BigDecimal(inner.getPrice());
resultBigDecimal = resultBigDecimal.add(innerBigDecimal);
}
return resultBigDecimal.toString();
}
}
这里基本上都用了BigDecimal这个类来进行加
然后配置一下
<?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.1</tlib-version>
<short-name>jstlUtils</short-name>
<uri>http://com.tool.JSTLFunctionUtils</uri>
<function>
<description>人数和</description>
<name>getPersonNumberSum</name>
<function-class>com.tool.JSTLFunctionUtils.JSTLUtils</function-class>
<function-signature>
java.lang.String getPersonNumberSum(java.util.List)
</function-signature>
</function>
    <function>
<description>钱数和</description>
<name>getPriceSum</name>
<function-class>com.tool.JSTLFunctionUtils.JSTLUtils</function-class>
<function-signature>
java.lang.String getPriceSum(java.util.List)
</function-signature>
</function>
</taglib>
页面上调用就${jstlUtils:getPersonNumberSum(vo.list)}就ok了
之后的循环 调用 <c:forEach items="${vo.list}" var="var">
去循环就好了
实际上 是解决了数据的准确性问题
那么 对于合计在最下方的情况下,为了数据的准确还是使用自定义函数比较好,因为 对于管理系统中,钱这个东西绝对不能错而jstl的fmt具体怎么加的,与其我们花一天去看源代码 不如自己写的又快又好又准确
(我没看fmt的源代码 没找到……不过 感觉上时java.text.Format的那几个,上一篇已经提过了 即使使用了FormatNumber也不是很准确的)
F:
这么多情况后 还有最后一个比较垃圾的问题,就是数据0的问题
客户的情况很多,但是对于数据0无外乎两种
一 0就别显示出来
二 没有就显示0
但是jstl就是很烦人,因为没有的情况下,我们取到的是null jstl不会将null的显示出来这样就空了
第一种情况个人建议是改写vo和自定义函数
如果返回的是0就返回“”
对于第二种情况
只能去判断了 jstl或者自定义函数 感觉上没啥区别 (个人认为)

ok 罗嗦了这么多 第一 是为了对大家有点帮助 第二 是为了自己不忘
为了您的安全,请只打开来源可靠的网址

打开网站    取消
来自: http://hi.baidu.com/zhangxia6110/blog/item/a4e2aa0093e60a93e850cd61.html 
分享到:
评论

相关推荐

    jstl-api-1.2和jstl-impl-1.2

    jstl-api-1.2和jstl-impl-1.2,jstl-api-1.2和jstl-impl-1.2,jstl-api-1.2和jstl-impl-1.2,jstl-api-1.2和jstl-impl-1.2

    jstl-api-1.2.jar、jstl-impl-1.2.jar

    **jstl-api-1.2.jar** 包含了JSTL的接口定义,定义了各种标签的API,比如`&lt;c:forEach&gt;`、`&lt;fmt:formatDate&gt;`等。这个jar文件通常被添加到项目的编译类路径(classpath)中,这样编译器就可以识别JSTL相关的代码,并...

    jstl标签jar包(jstl-api-1.2和jstl-impl-1.2)

    1. **jstl-api-1.2.jar**:这是JSTL的API接口定义,包含了所有JSTL标签库的接口和抽象类。开发人员在编写JSP页面时需要导入这个包,以便使用JSTL提供的各种标签。这个包不包含实际的实现,而是为编译时类型检查和...

    jstl-impl-1.2.jar和jstl-api-1.2.jar

    总结一下,"jstl-impl-1.2.jar"和"jstl-api-1.2.jar"是Java Web开发中的重要组件,它们为JSP页面提供了强大的标签库支持,帮助开发者编写更简洁、更易于维护的代码。在部署和运行JSP应用时,确保这两个jar文件正确...

    jstl-impl-1.2.jar

    jstl-api-1.2、jstl-impl-1.2.jar标签包,两份。

    jstl-1.2.jar、jstl-api-1.2.jar、jstl-impl-1.2.jar三个包

    java.lang.NoClassDefFoundError: javax/servlet/jsp/jstl/core/Config,以上错误可以使用以下策略试试,tomcat的lib文件夹下加入:jstl-1.2.jar、jstl-api-1.2.jar、jstl-impl-1.2.jar三个包。

    JSTL自定义标签实例解析

    **JSTL自定义标签实例解析** JavaServer Pages Standard Tag Library (JSTL) 是一套标准的标签库,用于简化JSP开发。JSTL允许开发者使用预定义的标签来处理常见任务,如迭代、条件判断、XML处理等。本文将深入讲解...

    jstl-impl-1.2.jar.rar_ jstl-impl-1.2.jar _jstl-impl-1.2_jstl-imp

    标签中的"_jstl-impl-1.2.jar_ jstl-impl-1.2 jstl-impl-1.2.jar jstl.impl jstl.jar"进一步强调了JSTL的实现版本1.2,"impl"通常表示这是实现层,而非API接口。"jstl.jar"可能是指JSTL的核心库,不包含具体实现,而...

    jstl-api-1.2.jar jstl-impl-1.2.jar

    在提供的文件中,`jstl-api-1.2.jar` 和 `jstl-impl-1.2.jar` 是JSTL 1.2版本的两个关键组件: 1. **jstl-api-1.2.jar**:这个文件包含了JSTL的API接口定义。它定义了所有JSTL标签的接口和类,是开发者在编写JSP...

    jstl-impl-1.2.2.jar

    jstl-impl-1.2.2.jar!

    jstl-api-1.2.jar

    总结,`jstl-api-1.2.jar`是JSTL 1.2版本的API接口,它提供了丰富的标签库,帮助开发者构建高效、可维护的JSP应用程序。理解和掌握JSTL的使用是提高JSP开发效率的关键,同时,它也是Java Web开发中一个重要的基石。

    jakarta.servlet.jsp.jstl-api-2.0.0.jar

    标题中的"jakarta.servlet.jsp.jstl-api-2.0.0.jar"是一个重要的Java Web开发组件,它属于JavaServer Pages(JSP)标准标签库(JSTL)的一部分,用于提供一套标准的标签来简化HTML或XML文档的生成。JSTL的主要目标是...

    javax.servlet.jsp.jstl-api-1.2.1.jar

    javax.servlet.jsp.jstl-api-1.2.1.jar

    包含jstl-api-1.2.1.jar,jstl-1.2.jar,jstl-impl-1.2.jar,standard-1.1.2.jar

    1. jstl-api-1.2.1.jar:这是JSTL的API接口定义,包含了JSTL的所有标签和EL表达式的接口定义。开发者在编写代码时主要引用这个jar包,通过这些接口可以调用JSTL提供的功能。 2. jstl-1.2.jar:这是JSTL的核心实现库...

    jstl-api-1.2.jar、jstl-impl-1.2.jar、mysql-connector-java-5.1.10-bin.jar

    总结起来,`jstl-api-1.2.jar`和`jstl-impl-1.2.jar`组合用于实现JSP页面的JSTL标签,提升代码的可维护性,而`mysql-connector-java-5.1.10-bin.jar`则作为连接MySQL数据库的关键组件,使得Java应用能够方便地访问和...

    jstl 自定义标签

    JSTL自定义标签允许开发者扩展标准标签库的功能,满足特定需求。自定义标签由三部分组成:标签库描述符(TLD),标签处理类(Tag Handler Class)以及标签体(Tag Body)。 1. **标签库描述符(TLD)**:这是一个XML...

    standard-1.1.2.jar,jstl-api-1.2.jar,jstl-impl-1.2.jar,jstl-1.2.jar

    Tomcat启动报错 java.lang.ClassNotFoundException: org.apache.jsp.index_jsp,检查你的项目中是否存在jsp-api.jar,jstl-api.jar,servlet-api.jar。

    jst-1.2、jstl-api-1.2、jstl-impl-1.2的jar包

    **jstl-api-1.2.jar** 文件是JSTL的API接口定义,其中包含所有JSTL标签库的接口和类。这个库提供了用于编译JSP页面时的类型安全引用,允许开发者在编译时检查JSTL标签的使用是否正确。它不包含任何实际的实现代码,...

    [jstl-1.2.jar]和[jstl-api-1.2.jar、standard.jar]两个版本.zip

    包含了两个版本jstl文件,standard.jar和jstl-api-1.2.jar是一个版本,导入时需要将两个都导入,jstl-1.2.jar是高版本的,是将低版本的两个文件合成一个了,故只需要导入一个文件即可,导入的同时在jsp文件首行写入 ...

Global site tag (gtag.js) - Google Analytics