Struct2入門四

OGNL表達式使用和值棧
1、 值棧在開發中應用
主流應用 : 值棧 解決 Action 向 JSP 傳遞 數據問題

Action 向JSP 傳遞數據處理結果 ,結果數據有兩種形式
1) 消息 String類型數據

    this.addFieldError("msg", "字段錯誤信息");
    this.addActionError("Action全局錯誤信息");
    this.addActionMessage("Action的消息信息");
  • fieldError 針對某一個字段錯誤信息 (常用於表單校驗)、actionError (普通錯誤信息,不針對某一個字段 登陸失敗)、 actionMessage 通用消息

在jsp中使用 struts2提供標籤 顯示消息信息

    <s:fielderror fieldName="msg"/>
    <s:actionerror/>
    <s:actionmessage/>

2) 數據 (複雜類型數據)
使用值棧 valueStack.push(products);

哪些數據默認會放入到值棧 ???
1)每次請求,訪問Action對象 會被壓入值棧 ——- DefaultActionInvocation 的 init方法 stack.push(action);
* Action如果想傳遞數據給 JSP,只有將數據保存到成員變量,並且提供get方法就可以了
2)ModelDriven 接口 有一個單獨攔截器

<interceptor name="modelDriven" class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/>
在攔截器中 ,將model對象 壓入了 值棧 stack.push(model);
* 如果Action 實現ModelDriven接口,值棧默認棧頂對象 就是model對象 

2、 值棧的數據 通過EL訪問
問題七:爲什麼 EL也能訪問值棧中的數據

StrutsPreparedAndExecuteFilter的doFilter代碼中 request = prepare.wrapRequest(request);  
    * 對Request對象進行了包裝 ,StrutsRequestWrapper 
    * 重寫request的 getAttribute 
        Object attribute = super.getAttribute(s);
        if (attribute == null) {
           attribute = stack.findValue(s);
        }
  訪問request範圍的數據時,如果數據找不到,去值棧中找 

 request對象 具備訪問值棧數據的能力 (查找root的數據)

3、 OGNL表達式 常見使用
(#、 % 、$ 符號使用 )
1) # 的 使用
用法一 # 代表 ActionContext.getContext() 上下文
————> ActionContext().getContext().getRequest().get(“name”);
#request
#session
#application
#attr
#parameters

用法二 : 不寫# 默認在 值棧中root中進行查找
在root中查找name屬性
* 查詢元素時,從root的棧頂元素 開始查找, 如果訪問指定棧中元素 訪問棧中第二個元素name屬性
* 訪問第二個元素對象

用法三 :進行投影映射 (結合複雜對象遍歷 )
1)集合的投影(只輸出部分屬性

   <h1>遍歷集合只要name屬性</h1>
    <s:iterator value="products.{name}" var="pname"> 
        <s:property value="#pname"/>
    </s:iterator>

2)遍歷時,對數據設置條件

<h1>遍歷集合只要price大於1500商品</h1>
    <s:iterator value="products.{?#this.price>1500}" var="product"> 
        <s:property value="#product.name"/> --- <s:property value="#product.price"/>    
    </s:iterator>

3)綜合

 <h1>只顯示價格大於1500 商品名稱</h1>
    <s:iterator value="products.{?#this.price>1500}.{name}" var="pname"> 
        <s:property value="#pname"/>
    </s:iterator>   

用法四: 使用#構造map集合
經常結合 struts2 標籤用來生成 select、checkbox、radio

<h1>使用#構造map集合 遍歷</h1>
    <s:iterator value="#{'name':'aaa','age':'20', 'hobby':'sport' }" var="entry">
        key : <s:property value="#entry.key"/> , value:  <s:property value="#entry.value"/> <br/>
    </s:iterator>

2) %的使用
用法一: 結合struts2 表單表單使用, 通過%通知struts, %{}中內容是一個OGNL表達式,進行解析

用法二: 設置ognl表達式不解析 %{‘ognl表達式’}

3)使OGNLpropertiesmsg=, {#request.username}
在頁面



* 自動將值棧的username 結合國際化配置信息顯示
用法二 :在Struts 2配置文件中,引用OGNL表達式

contentType {contentType} 讀取值棧中contentType數據,在Action提供 getContentType 因爲Action對象會被壓入值棧,
contentType是Action屬性,從值棧獲得

結論: #使用ognl表達式獲取數據,% 控制ognl表達式是否解析 ,$ 用於配置文件獲取值棧的數據
struts2 標籤庫
tag-reference.html 就是 struts2 標籤規範
1、 通用標籤庫 的學習

<s:property> 解析ognl表達式,設置默認值,設置內容是否HTML轉義
<s:set> 向四個數據範圍保存數據 
<s:iterator> 遍歷值棧中數據 
<s:if> <s:elseif> <s:else>
 進行條件判斷 -------- elseif 可以有多個 
<s:url> 進行URL重寫(追蹤Session ) ,結合s:param 進行參數編碼 
* <s:url action="download" namespace="/" var="myurl"><s:param name="filename" value="%{'MIME協議簡介.txt'}"></s:param>
* </s:url>
<s:property value="#myurl"/>
<s:a> 對一個鏈接 進行參數編碼 
 * <s:a action="download" namespace="/" >下載MIME協議簡介.txt
<s:param name="filename" value="%{'MIME協議簡介.txt'}"></s:param>
</s:a>

OGNL 瞭解部分 : 支持賦值操作和表達式串聯 、 操作集合對象
1) 在值棧中保存一個對象
自動查找值棧中 price 和 name 屬性 爲其賦值
2) ognl操作集合
訪問集合第一個元素name屬性
訪問map中key爲name的值
{} 直接構造List 元素、 #{} 直接構造 Map元素





2、 UI標籤庫的學習 (Form標籤)
使用struts2 form標籤 好處 : 支持數據回顯 , 佈局排班(基於Freemarker 模板定義 )
struts2 表單標籤 value屬性。 必須寫 %{} 進行設值
* 使用struts2表單標籤前, 必須配置

StrutsPrepareAndExecuteFilter 
  The Struts dispatcher cannot be found.  This is usually caused by using Struts tags without the associated filter. Struts tags are only usable when the request has passed through its servlet filter, which initializes the Struts dispatcher needed for this tag

<s:form> 表單標籤 
    <s:form action="regist" namespace="/" method="post" theme="xhtml">  ---   theme="xhtml" 默認佈局樣式
<s:textfield> 生成 <input type="text" >   
<s:password > 生成 <input type="password" >

<s:submit type="submit" value="註冊"/> 生成 <input type="submit" >
<s:reset type="reset" value="重置" /> 生成 <input type="reset" >
  • struts2 除了支持JSP之外,支持兩種模板技術 Velocity (擴展名 .vm ) 、 Freemarker (擴展名 .ftl)
<s:textarea> 生成 <textarea> 多行文本框
<s:checkboxlist> 生成一組checkbox
    * 使用ognl構造 Map (看到值和提交值 不同時)
    * <s:checkboxlist list="#{'sport':'體育','read':'讀書','music':'音樂' }" name="hobby"></s:checkboxlist>
<s:radio> 生成一組radio
    * 使用 ognl構造 List  (看到內容和提交值 相同時)
    * <s:radio list="{'男','女'}" name="gender"></s:radio>
<s:select> 生成一個<select> 
    * <s:select list="{'北京','上海','南京','廣州'}" name="city"></s:select>

============= struts2 開發 密碼框 默認不回顯 
      <s:password name="password" id="password" showPassword="true"/>

3、 頁面元素主題設置
default.properties —- struts.ui.theme=xhtml 設置struts2 頁面元素使用默認主題
struts.ui.templateSuffix=ftl 默認模板引擎 Freemarker
修改主題
方式一 : 只對當前元素有效
方式二 : 對form中所有元素有效
方式三 : struts.xml
修改默認主題樣式,頁面所有元素都有效
優先級 : 方式一 > 方式二 > 方式三

防止表單重複提交原理
表單防止重複提交
表單重複提交 危害: 刷票、 重複註冊、帶來服務器訪問壓力(拒絕服務)

1、 在jsp 通過 生成令牌號
生成表單隱藏域
將令牌號保存到Session

2、 通過struts2 提供 tokenIntercetor 攔截器 完成請求中令牌號 和 session中令牌號 比較

<interceptor name="token" class="org.apache.struts2.interceptor.TokenInterceptor"/> 
        <action name="token" class="cn.itcast.struts2.TokenAction">
            <result>/index.jsp</result>
            <!-- 重新定義攔截器 -->
            <interceptor-ref name="defaultStack"></interceptor-ref>
            <interceptor-ref name="token"></interceptor-ref>
        </action>

3、 當表單重複提交時,token攔截器自動跳轉 result name=”invalid.token”
通過 顯示錯誤信息

覆蓋重複提交信息 struts.messages.invalid.token=您已經重複提交表單,請刷新後重試

Struts2 內置json插件
知識點 :struts2 的 Ajax 開發
Ajax開發客戶端 和 服務器交互數據格式 ————— json
* json 是最輕量級,體積最小

服務器將程序處理結果,轉換爲json格式發送給 客戶端
* json-lib 、 flexjson 工具類庫

  • struts2-json-plugin-2.3.7.jar

案例一: 輸入用戶名,鼠標點擊密碼(觸發用戶名元素離焦事件),使用Ajax 將用戶名發送到服務器 判斷是否存在
jquery 1.4 、 1.6 新特性比較多 (企業主流 1.4 )

使用struts2 json插件
要點1 : extends 繼承 json-default
要點2 : type 類型寫 json

**** struts2 json插件 ,默認將值棧root頂端對象 所有屬性返回(get方法)

不想將company屬性返回 ,在get方法上 @JSON(serialize=false)

案例二 :服務器將 商品對象 List列表返回
如果Action 實現ModelDriven , model對象就是值棧棧頂對象,struts2 json插件默認 將model返回

通過設置root屬性,修改插件返回 根對象

<param name="root">action</param> 將Action作爲根對象返回 

只想要每個商品的 name 屬性
方案一: 在pnum 、price 的get方法上 添加 @JSON(serialize=false) ========= 只要@JSON註解,屬性將永遠不能參與 json返回
方案二: 設置 includeProperties 屬性

<param name="includeProperties">products[\d+\]\.name</param>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章