Ognl_JSTL_学习笔记

时间:2022-03-09 14:46:10

控制标签

使用Struts2标签必须先导入标签库,在页面使用如下代码导入Struts2标签:
<%@taglib prefix="s" uri="/struts-tags"%>

if/elseif/else标签:

<s:set name="age" value="29">
<s:if test="#age>60">
老年人
</s:if>
<s:elseif test="#age>35">
中年人
</s:elseif>
<s:elseif test="#age>15">
青年人
</s:elseif>
<s:else>
少年儿童
</s:else>

Action提示信息

actionerror和actionmessage标签:

这两个标签都是用来输出Action实例里封装的信息,actionerror负责输出Action实例的getActionErrors()方法的返回值。actionmessage负责返回Action实例的getActionMessages()方法的返回值。

Action代码:

public Class TestAction{
  public String execute(){
    addActionError("出错了!");  
    addActionMessage("请联系系统管理员!"); 
  }
}

在页面中使用标签输出:

<s:actionerror/>
<s:actionmessage/>

表单标签

Struts2提供了很多表单标签,大部分表单标签和HTML表单标签之间有一一对应的关系,这里只介绍一些比较特殊的表单标签。对于表单标签而言,name和value存在一个特殊的关系,每个表单元素会被映射成Action属性。

使用Struts2标签必须先导入标签库,在页面使用如下代码导入Struts2标签:
<%@taglib prefix="s" uri="/struts-tags"%>

textfield标签:
<s:textfield name="person.firstName"/>

checkboxlist标签:

使用简单集合来生成多个复选框 
<s:checkboxlist name="a" lable="请选择你喜欢的图书" labelposition="top" list="{'Java编程思想','J2EE企业应用实战'}"/>

使用简单Map对象来生成多个复选框
<s:checkboxlist name="b" label="请选择你喜欢的图书" labelposition="top" list="{'Java编程思想':'2012年8月','J2EE企业应用实战':'2012年9月'}" listKey="key" listValue="value"/>

使用创建的放有多个对象的JavaBean对象来生成多个复选框
<s:bean name="com.service.BookService" id="bs"/>
<s:checkboxlist name="b" label="请选择你喜欢的图书" labelposition="top" list="#bs" listKey="author" listValue="name"/>

public class BookService{
    public Book[]getBooks(){
         return new Book[]{
            new Book("Java编程思想","李刚");
            new Book("J2EE企业应用实战","李刚");
         };
    }
}

public class Book{
  private String name;
  private String author;
  
  public Book(String name,String author){
     this.name=name;
     this.author=author;
  }
  //getter&setter...
}

select标签:

使用集合来生成下拉选择框

<s:select name="a" lable="请选择你喜欢的图书" lableposition="top" multiple="true" list="{'Java编程思想','J2EE企业应用实战'}" />

使用简单Map对象来生成下拉选择框

<s:select name="b" lable="请选择你喜欢的图书" lableposition="top" multiple="true" list="#{'Java编程思想':'2012年8月','J2EE企业应用实战':'2012年9月'}" listKey="key" listValue="value"/>

属性说明:
multiple:设置该列表框是否允许多选 
listKey:指定集合中的某个元素作为复选框的value
listValue:指定集合中的某个元素作为复选框的标签

使用集合里放多个JavaBean实例来生成下拉选择框

<s:bean name="com.service.BookService" id="bs"/>
<s:select name="b" lable="请选择你喜欢的图书" labelposition="top" multiple="true" list="#bs.books" listKey="author" listValue="name"/>

radio标签:

使用集合来生成单选框

<s:radio name="a" lable="请选择你喜欢的图书" lableposition="top" multiple="true" list="{'Java编程思想','J2EE企业应用实战'}" />

使用简单Map对象来生成单选框

<s:radio name="b" lable="请选择你喜欢的图书" lableposition="top" multiple="true" list="#{'Java编程思想':'2012年8月','J2EE企业应用实战':'2012年9月'}" listKey="key" listValue="value"/>

使用集合里放多个JavaBean实例来生成单选框

<s:bean name="com.service.BookService" id="bs"/>
<s:radio name="c" lable="请选择你喜欢的图书" labelposition="top" multiple="true" list="#bs.books" listKey="author" listValue="name"/>

optgroup标签:
<s:optgroup lable="请选择你喜欢的图书" list="#{'Java编程思想':'2012年8月'}" listKey="value" listValue="key"/>
<s:optgroup lable="请选择你喜欢的图书" list="#{'J2EE企业应用实战':'2012年9月'}" listKey="value" listValue="key"/>

token标签:
这是一个防止多次提交表单的标签,如果需要该标签起作用,则应该在Struts2的配置文件中启用TokenInterceptor拦截器或TokenSessionStoreInterceptor拦截器。
token的实现原理:在表单中增加一个隐藏域,每次加载页面时,该隐藏域的值都不同,而TokenInterceptor则拦截所有的用户请求,如果两次请求时该token对应隐藏域的值相同,则阻止表

单提交。
<s:token />

doubleselect标签:

doubleselect标签会生成一个级联列表框,当选择第一个下拉列表框时,第二个下拉列表框的内容会随之而改变。
<s:doubleselect lable="请选择你喜欢的图书"
                name="author"
                list="{'李刚','David'}"
                doubleList="top=='李刚'?{'Struts2权威指南','轻量级Java EE企业应用实战'}:{'Java编程思想','23种设计模式'}"/>

使用Map对象来创建doubleselect
<s:set name="bs" value="#{'李刚':{'Struts2权威指南','轻量级Java EE企业应用实战'},'David':{'Java编程思想','23种设计模式'}}"/>
<s:doubleselect lable="请选择你喜欢的图书" 
                size="3"
                name="author"
                list="#bs[top]"
                doubleSize="3"
                doubleName="book"/>

optiontransferselect标签:

optiontransferselect标签会生成两个列表选择框,并生成系列的按钮来控制各选项在两个下拉列表之间的移动、升降。当提交表单时,两个列表选择框对应的请求参数都会被提交。

<s:optiontransferselect 
                lable="请选择你喜欢的图书"
                name="cnbook"
                leftTitle="中文图书"
                rightTitle="外文图书"
                list="{'Struts2权威指南','Java编程思想'}"
                multiple="true"
                addToLeftLable="向左移动"
                selectAllLable="全部选择"
                addAllToRightLable="全部右移"
                headerKey="cnKey"
                headerValue="---选择中文图书---"
                emptyOption="true"
                doubleList="{'Expert One-on-One J2EE Design and Development','JavaScript: The Definitive Guide'}"
                doubleName="enBook"
                doubleHeaderKey="enKey"
                doubleHeaderValue="---选择外文图书---"
                doubleEmptyOption="true"
                doubleMultiple="true"
/>

属性说明:

list:设置第一个下拉列表选择框的集合

listKey:设置第一个下拉列表选择框的value属性

listValue:设置第一下下拉列表选择框的lable属性

doubleList:设置第二个下拉列表选择框的集合

doubleListKey:设置第二个下拉列表选择框的value属性

doubleListValue:设置第二个下拉列表选择框的lable属性

doubleMultiple:设置第二个下拉列表选择框是否允许多选

updownselect标签:

使用简单集合来生成可上下移动选项的下拉选择框
<s:updownselect name="a" label="请选择你喜欢的图书"
                lableposition="top"
                moveUpLable="向上移动"
                list="{'Struts2权威指南','Java编程思想'}"/>

使用简单Map对象来生成可上下移动选项的下拉选择框
<s:updownselect name="b" lable="请选择你喜欢的图书"
                lableposition="top"
                moveDownLable="向下移动"
                list="{'Struts2权威指南':'2012年8月','Java编程思想':'2012年9月'}"
                listKey="key"
                listValue="value"
                emptyOption="true"
/>
               
使用集合里放多个JavaBean实例来生成可上下移动选项的下拉选择框
<s:bean name="com.service.BookService" id="bs"/>
<s:updownselect name="c" lable="请选择你喜欢的图书"
                lableposition="top"
                selectAllLable="全部选择"
                list="#bs.books"
                listKey="author"
                listValue="name"
                multiple="true"
/>

数据标签

bean标签:
作用:用于创建一个JavaBean实例

例子:
<s:bean name="com.dto.Person">
//设置JavaBean的属性
<s:param name="name" value="Jay"/>
<s:param name="age" value="29"/>
//输出显示
姓名:<s:property name="name"/> 
年龄:<s:property name="age"/>
</s:bean>

在<s:bean.../>标签外访问JavaBean
例子:
<s:bean name="com.dto.Person" var="p">
//设置JavaBean的属性
<s:param name="name" value="Jay"/>
<s:param name="age" value="29"/>
</s:bean>
//输出显示
姓名:<s:property value="#p.name"/>
年龄:<s:property value="#p.age"/>

说明:为bean标签指定var属性,意味着将该JavaBean放置到Stack Context中,因此即使不在<s:bean.../>内,也可以通过该var属性来访问该JavaBean。

date日期标签:

日期的格式化输出
例子:
<s:bean var="now" name="java.util.Date">
<s:date name="#now" formar="yyyy/mm/dd"/>
</s:bean>

将格式化后的日期值字符串放入StackContext中并放入requestScope中,该属性也可用id代替,但推荐使用var
例子:
<s:date name="#now" var="abc"/>
<s:property value="abc"/>

debug标签:
该标签主要用来调试,它在页面生成一个超级链接,通过该链接可以查看到ValueStack和Stack Context中所有值信息,该标签只有一个

id属性,没有太大的意义。
例子:
<s:debug id="deb">

include标签:
该标签用于将一个Jsp页面或者一个Servlet包含到本页面中
例子:
<s:include value="included-file.jsp">
<!--传入参数到包含的Jsp或者Servlet-->
<s:param name="author" value="admin">
</s:include>

集合操作

判断元素是否在指定集合中:

in:判断元素是否在指定集合中
例子:
<s:if test="'foo' in {'foo','bar'}">
foo包含在集合中
</s:if>
<s:else>
foo不包含在集合中
</s:else>

not in: 判断元素是否不在指定集合中
例子:
<s:if test="'foo' not in{'foo','bar'}">
foo不包含在集合中
</s:if>
<s:else>
foo包含在集合中
</s:else>
取集合中指定条件的子集合:

?:取出所有符合选择逻辑的元素
^:取出符合选择逻辑的第一个元素
$:取出符合选择逻辑的最后一个元素

例子:
person.relatives.{? #this.gender=='male'}
取出person的所有性别为male的集合

对集合进行迭代:

Iterator:迭代输出List
例子:
<table>
<s:iterator value="{'Jay',  'Jolin',  'Andy'}" id="name" status="st">
<tr>
<td>
<s:property value="#st.index"/>
</td>
<td>
<s:property value="name"/>
</td>
</tr>
</s:iterator>
</table>

Iterator:迭代输出Map
例子:
<table>
<s:iterator value="#{'Jay' : '周杰伦',    'Jolin' : '蔡依林',    'Andy' : '刘德华'}" id="score" status="st">
<tr>
<td>
<s:property value="key"/>
</td>
<td>
<s:property value="value"/>
</td>
</tr>
</s:iterator>
</table>

iterator标签中的其它方法:

getCount():  返回当前迭代了几个元素
getIndex():  返回当前被迭代元素的索引
isEven():    返回当前元素被迭代元素的索引是否是偶数
isOdd():     返回当前元素被迭代元素的索引是否是奇数
isFirst():   返回当前被迭代元素是否是第一个元素
isLast():    返回当前被迭代元素是否是最后一个元素

例子:
<table>
<s:iteraotr value="{'Jay','Jolin','Andy'}" id="name" status="st">
<tr <s:if test="#st.odd">style="background-color:#bbbbbb"</s:if>>
<td>
<s:property value="name"/>
</td>
</tr>
</s:iterator>
</table>

Stack Context中的对象与访问

根对象的访问:

传统的OGNL表达式求值中,系统会假设只有一个根对象。如果系统的Stack Context中包含两个对象,foo和bar,它们在Context中的名字分别为foo和bar,并将foo设置为Context的根对象。

访问根对象foo的属性: #foo.blah或blah
访问其它对象:  #bar.blah

如果要访问的属性属于根对象,则可以直接访问该属性,否则使用一个名作为前缀修饰属性。

Struts2提供的命名对象

Struts2使用标准的Context进行OGNL表达式语言求值,OGNL的*对象是一个Map类型实例对象Context,其根对象就是ValueStack。要访问ValueStack中的属性,可以通过以下方式:${bar}
Struts2提供了一些命名对象,但这些对象不是Stack Context的根对象,它们只是存在于Stack Context中,所以要访问这些对象时需要使用#前缀来指明。
(1).parameters对象:用于访问Http请求参数,如:#parameters.foo,  #parameters['foo']。用于返回调用HttpServletRequest的getParameter("foo")的返回值。
(2).request对象:用于访问HttpServletRequest的属性。如:#request['foo'],  #request.foo。用于返回调用HttpServletRequest的getAttribute("foot")的返回值。
(3).session对象:用于访问HttpSession的属性。如:#session['foo'],  #session.foo。用于返回调用HttpSession的getAttribute("foo")的返回值。
(4).application对象:用于访问ServletContext的属性。如:#application['foo'],  #application.foo。用于返回调用ServletContext的getAttribute("foo")的返回值。
(5).attr对象:该对象将依次搜索如下对象:PageContext,  HttpServletRequest,  HttpSession,  ServletContext中的属性。

当系统创建的Action实例后,该Action实例已经被保存到ValueStack中,所以无需写#即可直接访问Action属性。

Stack Context中的对象:

Stack Context---ValueStack(根对象)
                        ---parameters(命名对象)
                        ---request(命名对象)
                        ---session(命名对象)
                        ---application(命名对象)
                        ---attr(命名对象)

访问Stack Context的根对象的属性时可以省略对象名,访问其它命名对象时需要在对象名前添加#前缀。

JSTL标签

EL表达式
使用很简单,不用在JSP中写入支持标签的语句,直接可以拿来用。 
${hello}        等同于    <%= request.getAttribute("hello") %> 
EL表达式还支持四则运算,大小比较(返回true或false),为空验证(${empty hello},返回true或false),还支持如${group.name}   ${map.key}返回相应的值

JSTL核心库 (c标签) 
首先,你要把jar包引进去,这里有个问题,如果是struts1.3.10的话,其自带的jstl包是1.0版本,而1.0版本的jstl在2.0的JSP中,会有问题。所以要下个1.1以上版本的jstl包,下载地址在此:http://jakarta.apache.org/site/downloads/downloads_taglibs-standard.cgi 
然后,在JSP中加入支持标签的语句,<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 
⑴,c:out 就是做输出 
<c:out value="${hello}"/>    等同于    ${hello} 
<c:out value="${abc}" default="haha"/>       如果${abc}不存在,那么给一个初始值haha 
     
String HTML = "<font color='red'>北京欢迎你</font>"; 
request.setAttribute("bj", HTML);     action中把值送出来

<c:out value="${bj}" escapeXml="false">   escapeXml:是否脱离XML语法,不是的话,就还是按照HTML语法解析,输出结果:北京欢迎你 
⑵,c:set , c:remove 
c:set 等于在page级别,setAttribute一个值,在当前页面用c:out可以接收到,例如: 
<c:set value="beckham" var="player"/> 
c:remove就是把一个属性值从当前page中删了,例如: 
<c:remove var="player"/> 
⑶,c:if    就是个条件分支语句,只能表达出if,没有else 
<c:if test="${1 < 2}" var="result"> 
    1 < 2<br> 
    ${result }<br> 
   </c:if> 
输出结果: 
1 < 2 
true

⑷,c:choose,c:when,c:otherwise,其实也是个条件分支语句,不过这次可以形成if。。。else的组合了^_^   
c:when就是if,c:otherwise就是else,要注意的是c:when,c:otherwise必须写在c:choose标签的里面 
<c:choose> 
    <c:when test="${v1 < v2}"> 
     v1 < v2<br> 
   </c:when> 
    <c:otherwise> 
     v1 > v2<br> 
   </c:otherwise> 
</c:choose>

⑸,c:forEach, 就是个循环 
      <c:forEach items="${userList}" var="user">   ←这里的var相当于把一个对象Attribute取出来后,给这个对象起的名字(也就是这个对象的引用),下面就可以用这个引用来显示该对象的属性 
       <tr> 
        <td>${user.username }</td> 
        <td>${user.age }</td> 
        <td>${user.group.name }</td> 
       </tr> 
      </c:forEach> 
输出结果如下 
name age group 
選手 0 20 AC milan 
選手 1 21 AC milan 
選手 2 22 AC milan 
選手 3 23 AC milan 
選手 4 24 AC milan

■ c:forEach中的varStatus属性 ,varStatus可以记录本次循环的一些信息,比如现在循环到第几次啦,就是vs.count ,下面这个例子,当循环进行到偶数次时,改变背景颜色为黄色 
<c:forEach items="${userList}" varStatus="vs" var="user"> 
       <c:choose> 
        <c:when test="${vs.count % 2 == 0}"> ←如果是偶数次,背景色变为黄色 
         <tr bgcolor="yellow"> 
        </c:when> 
        <c:otherwise>     ←如果步是偶数次,背景色不变 
         <tr> 
        </c:otherwise> 
       </c:choose> 
          <td>${user.username }</td> 
          <td>${user.age }</td> 
          <td>${user.group.name }</td> 
         </tr> 
      </c:forEach> 
输出结果如下 
name age group 
選手 0 20 AC milan 
選手 1 21 AC milan 
選手 2 22 AC milan 
選手 3 23 AC milan 
選手 4 24 AC milan

■ c:forEach中的begin , end, step属性,begin:从哪里开始循环,end:到哪里结束,step:每次循环的步长 
■ 可以用c:forEach接受的除了List还有Map,接受Map的时候还可以分别取出key和value的值,例子: 
<c:forEach items="${map}" var="v" > 
     ${v.key } = ${v.value }<br> 
</c:forEach> 
⑹,c:forTokens 用于有分隔符字符串的迭代,delims属性用来设置分隔符的类型(逗号啦,斜杠啦),看例子: 
action中的送值 
request.setAttribute("forTokens","1,2,3,4,5"); 
request.setAttribute("forTokens2","/oracle/db/9.2.0"); 
JSP中的接收值 
<c:forTokens items="${forTokens}" delims="," var="v">    ←分隔符为逗号 
    ${v }<br> 
</c:forTokens> 
   <p> 
<c:forTokens items="${forTokens2}" delims="/" var="v">   ←分隔符为斜杠 
    ${v }<br> 
</c:forTokens> 
结果如下: 





oracle 
db 
9.2.0

⑺,c:catch,捕获异常,相当于java语法的 try......catch,可以用c:catch的var属性打印异常信息 
<c:catch var="v"> 
     <% 
      Integer.parseInt("heihei");        //这里故意整一个错误,把字符串转化为int格式,当然出错了 
     %> 
</c:catch> 
${v }

输出结果: 
java.lang.NumberFormatException: For input string: "heihei" 
⑻,c:import,相当于include,在当前页中引入另一个页面,用法如下: 
<c:import url="http://localhost:8080/struts_JSTL_EL/"></c:import>

⑼,c:redirect 重定向 
<c:redirect context="/struts_JSTL_EL" url="/index.jsp"></c:redirect> 
结果:当前页面会重定向到 http://localhost:8080/struts_JSTL_EL/index.jsp去,就这么个事

格式化库(fmt) 
在JSP中加入支持标签的语句,<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%> 
※:先贴一段在action中的传值,后面的格式化时间和格式化数字都会用到 
request.setAttribute("today",new Date()); 
request.setAttribute("number",1234566.678); 
request.setAttribute("percent", 0.12345); 
⑴,格式化时间,fmt:formatDate 
<fmt:formatDate value="${today}"/><br> 
输出结果:2009/04/22 
<fmt:formatDate value="${today}" type="date"/><br> 
输出结果:2009/04/22 
<fmt:formatDate value="${today}" type="time"/><br> 
输出结果:18:24:21 
<fmt:formatDate value="${today}" type="both"/><br> 
输出结果:2009/04/22 18:24:21 
⑵,格式化数字,fmt:formatNumber 
<fmt:formatNumber value="${number}"/><br> 
输出结果:1,234,566.678   //type默认是数字且有逗号分隔 
<fmt:formatNumber value="${number}" pattern="###,###.##"/><br> 
输出结果:1,234,566.68    //pattern和struts中的一样 
<fmt:formatNumber value="${number}" pattern="###,###.0000"/><br> 
输出结果:1,234,566.6780 //小数点后不够4位就补零 
<fmt:formatNumber value="${number}" type="currency" currencySymbol="$"/><br> 
输出结果:1,234,566.68    //type设为通货,currencySymbol设美元符号 
<fmt:formatNumber value="${percent}" type="percent"/><br> 
输出结果:12%             //type设为百分数 
<fmt:formatNumber value="${percent}" type="percent" maxFractionDigits="2" minFractionDigits="2"/><br> 
输出结果:12.34%          //type设为百分数,且小数点后最大最小都留2位

Jsp自定义标签

Jsp页面中通过xml语法格式被调用,当JSP引擎将JSP页面翻译成Servlet时,就将这些调用转换成执行相应的Java代码

例子:实现在页面输出一个指定范围的随机数

标签:<ct:random min="1" max="100"/>

第一步:编写标签类:

实现标签类的方法有很多,最简单的方法是从javax.servlet.jsp.tagext.TagSupport类继承

java代码:

package com.test.mytag

public calss RandomTag extends TagSupport{

private int min=0;//标签中的属性min,默认值设置为0

private int max=Integer.MAX_VALUE;//标签中的属性max,默认值设置为int类型的最大值

public void setMin(int min){

this.min=min;

}

public void setMax(int max){

this.max=max

}

public int doStartTag()throws JspException{

try{

Random random=new Random();

int result=min+random.nextInt(max-min);

pageContext.getOut().write(String.valueOf(result));

//输出随机数,pageContext变量是在TagSupport类中定义的一个类变量,该变量通过TagSupport类中的

//setPageContext方法赋值,setPageContext方法是在Tag接口中定义的,

//而TagSupport实现了Tag接口的setPageContet方法,

//Servlet容器在调用doStartTag方法前会先调用setPageContext方法

}catch(IOException e){

System.out.println("error!");

}

//TagSupport类的doStartTag方法默认返回SKIP_BODY,表示忽略自定义标签体

return super.doStartTag();

}

}

第二步:

编写标签库描述符文件(TLD文件)

要想自定义标签正常工作,必须在TLD文件中对该标签进行配置:

在WEB-INF目录中建一个jsp-taglib.tld文件,内容如下:

<?xml version="1.0" encoding="UTF-8"?>

<taglib xmlns="http://java.sun.com/xml/ns/j2ee"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2.0.xsd" version="2.0">

<description>自定义标签库</descrption>

<tlib-version>1.1</tlib-version>

<short-name>ct</short-name><!--标签前缀-->

<uri>http://www.javaeye.net</uri>

<taglib>

<tag>

<desrption>产生一个指定范围的随机数</desrption>

<name>random</name>

<tag-class>com.test.mytag.RandomTag</tag-class>

<body-content>empty</body-content><!--表示标签体类型不支持标签体-->

<attribute>

<name>min</name>

<required>false</required>

<rtexprvalue>false</rtexprvalue>

</attribute>

<attribute>

<name>max</name>

<required>false</required>

<rtexprvalue>false</rtexprvalue>

</attribute>

</tag>

</taglib>