6、Struts2中的國際化、Ognl(對象圖導航語言)表達式語言

Struts2中的國際化、Ognl(對象圖導航語言)表達式語言

回顧:Servlet 中國際化:
1). 寫資源文件
基礎名.properties 【默認的語言環境的配置】
基礎名語言簡稱國家簡稱.properties
2). 讀取資源文件,再使用
程序:ResourceBundle
Jsp: jstl提供的格式化與國際化標籤庫。

一、Struts2中國際化:
1. 寫資源文件 (同servlet)
2. 讀資源文件
程序:ResourceBundle (同servlet)
JSP:
1)jstl表親啊 (同servlet)
2)struts標籤獲取資源文件內容

區別:
Struts2加載資源文件更加簡單!通過常量加載即可!再在jsp頁面直接使用!

  1. 寫資源文件
    Msg.properties 默認的語言環境; 找不到配置就找它
    Msg_en_US.properties 美國
  2. 加載
<constant name="struts.custom.i18n.resources" value="cn.itcast.config.msg"></constant>
  1. 使用: 標籤name值直接寫配置文件中的key
<s:text name="title"></s:text>

另外一點,
(推薦)加載資源文件通過常量加載
還可以在頁面加載, 這樣用:

        <s:i18n name="cn.itcast.config.msg">
            <s:text>  標籤必須放到標籤體中。
</s:i18n>

二、 Ognl表達式語言
概述
OGNL表達式
OGNL是Object Graphic Navigation Language(對象圖導航語言)的縮寫,它是一個開源項目。 Struts2框架使用OGNL作爲默認的表達式語言。
OGNL優勢
1、支持對象方法調用,如xxx.doSomeSpecial();
2、支持類靜態的方法調用和值訪問,表達式的格式:
@[類全名(包括包路徑)]@[方法名 | 值名],例如:
@java.lang.String@format(‘foo %s’, ‘bar’)
或@tutorial.MyConstant@APP_NAME;
3、支持賦值操作和表達式串聯,如price=100, discount=0.8,
calculatePrice(),這個表達式會返回80;
4、訪問OGNL上下文(OGNL context)和ActionContext;
5、操作集合對象。
總結
OGNL 有一個上下文(Context)概念,說白了上下文就是一個MAP結構,它實現了 java.utils.Map 的接口。 OgnlContext對象

分析:
Struts框架默認就支持Ognl表達式語言。
(struts必須引用的包:ognl.jar)
作用
頁面取值用。

El表達式語言,用於頁面取值,jsp頁面取值的標準。(默認直接可以使用)
(應用範圍更廣。)
Ognl表達式語言, struts標籤默認支持的表達式語言。
必須配置struts標籤用,不能離開struts標籤直接用。

OgnlContext對象(瞭解)
OgnlContext對象是ognl表達式語言的核心。
源碼類:

public class OgnlContext extends Object implements Map{..}

硬編碼方式,瞭解OgnlContext對象:

// OgnlContext用法
public class OgnlDemo1 {

    /**
     * 1. Ognl表達式語言語言取值,取非根元素的值,必須用#號
     * @throws Exception
     */
    @Test
    public void testOgnl() throws Exception {
        // 創建一個Ognl上下文對象
        OgnlContext context = new OgnlContext();
        // 放入數據
        User user = new User();
        user.setId(100);
        user.setName("Jack");
        // 【往非根元素放入數據, 取值的時候表達式要用"#"】
        context.put("user", user);

        // 獲取數據(map)
        // 先構建一個Ognl表達式, 再解析表達式
        Object ognl = Ognl.parseExpression("#user.name");
        Object value = Ognl.getValue(ognl, context, context.getRoot());

        System.out.println(value);
    }

    /**
     * 2. Ognl表達式語言語言取值,取根元素的值,不用帶#號
     * @throws Exception
     */
    @Test
    public void testOgn2() throws Exception {
        // 創建一個Ognl上下文對象
        OgnlContext context = new OgnlContext();
        // 放入數據
        User user = new User();
        user.setId(100);
        user.setName("Jack");
        // 【往根元素放入數據】
        context.setRoot(user);

        // 獲取數據(map)
        // 先構建一個Ognl表達式, 再解析表達式
        Object ognl = Ognl.parseExpression("address.province");
        Object value = Ognl.getValue(ognl, context, context.getRoot());

        System.out.println(value);
    }

    /**
     * 3.Ognl對 靜態方法調用的支持
     * @throws Exception
     */
    @Test
    public void testOgn3() throws Exception {
        // 創建一個Ognl上下文對象
        OgnlContext context = new OgnlContext();

        // Ognl表單式語言,調用類的靜態方法
        //Object ognl = Ognl.parseExpression("@Math@floor(10.9)");
        // 由於Math類在開發中比較常用,所以也可以這樣寫
        Object ognl = Ognl.parseExpression("@@floor(10.9)");
        Object value = Ognl.getValue(ognl, context, context.getRoot());
        System.out.println(value);
    }
}

ValueStack對象
ValueStack, 即值棧對象。
值棧對象:
是整個struts數據存儲的核心,或者叫中轉站。
用戶每次訪問struts的action,都會創建一個Action對象、值棧對象、ActionContext對象; 然後把Action對象放入值棧中; 最後再把值棧對象放入request中,傳入jsp頁面。
(key: struts.valueStack); 開發者只需要通過ActionContext對象就可以訪問struts的其他的關鍵對象。 (ActionContext是給開發者用的,便於學習與使用。)

問題:
OgnlContext與ValueStack對象的關係?
這裏寫圖片描述

這裏寫圖片描述

這裏寫圖片描述

這裏寫圖片描述
Struts標籤
Struts標籤取值,就使用了Ognl表達式語言。

Struts數據效驗
表單數據的驗證:
前臺驗證:主要是通過JS驗證, 表達數據是否合法!
後臺驗證:通過後臺java代碼進行驗證!
Struts也提供了數據效驗的方式!

Struts數據效驗, 通過攔截器完成:

public synchronized void addFieldError(String fieldName, String errorMessage) {
        // 1. 保存錯誤信息的map集合
        final Map<String, List<String>> errors = internalGetFieldErrors();
        // 2. Map的value值  (一個key,對應的多個值用list存儲)
        List<String> thisFieldErrors = errors.get(fieldName);
        // 3. 如果錯誤信息的map中沒有當前的key,就直接創建集合
        if (thisFieldErrors == null) {
            // 創建
            thisFieldErrors = new ArrayList<String>();
            errors.put(fieldName, thisFieldErrors);
        }
         // 4. 添加錯誤信息
        thisFieldErrors.add(errorMessage);
    }

Action實現:

/**
 * 注意:如果要想用struts的數據效驗功能,必須繼承ActionSupport或實現相關接口
 * @author Jie.Yuan
 *
 */
public class UserAction extends ActionSupport {

    // 封裝請求數據
    private User user = new User();
    public void setUser(User user) {
        this.user = user;
    }
    public User getUser() {
        return user;
    }

    // 重寫數據驗證的方法
    @Override
    public void validate() {
        // 用戶名非空
        if (user.getUserName() == null || "".equals(user.getUserName())) {
            // 保存錯誤信息
            super.addFieldError("userName", "用戶名必須填寫!");
        }
        // 密碼
        if (user.getPwd() == null || "".equals(user.getPwd())) {
            super.addFieldError("pwd", "密碼必填");
        }
    }
….. 
}

代碼方式驗證Action中指定的方法:
寫驗證方法命名規則:
validate + 要驗證的方法名
如:
public void validateRegister() {
只會驗證當前action的register方法!
XML方式驗證Action中所有的方法:
總結代碼方式驗證:
繁瑣,設計很多重複的驗證邏輯!例如:非空驗證、數值驗證、email、日期等。

Struts對於常用的驗證,進行了封裝,即提供了驗證器, 驗證指定的常用業務邏輯!

Struts提供的所有驗證器:

路徑:

xwork-core-2.3.4.1.jar/com.opensymphony.xwork2.validator.validators/default.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
        "-//Apache Struts//XWork Validator Definition 1.0//EN"
        "http://struts.apache.org/dtds/xwork-validator-definition-1.0.dtd">

<!-- START SNIPPET: validators-default -->
<validators>
    <validator name="required" class="com.opensymphony.xwork2.validator.validators.RequiredFieldValidator"/>
    <validator name="requiredstring" class="com.opensymphony.xwork2.validator.validators.RequiredStringValidator"/>
    <validator name="int" class="com.opensymphony.xwork2.validator.validators.IntRangeFieldValidator"/>
    <validator name="long" class="com.opensymphony.xwork2.validator.validators.LongRangeFieldValidator"/>
    <validator name="short" class="com.opensymphony.xwork2.validator.validators.ShortRangeFieldValidator"/>
    <validator name="double" class="com.opensymphony.xwork2.validator.validators.DoubleRangeFieldValidator"/>
    <validator name="date" class="com.opensymphony.xwork2.validator.validators.DateRangeFieldValidator"/>
    <validator name="expression" class="com.opensymphony.xwork2.validator.validators.ExpressionValidator"/>
    <validator name="fieldexpression" class="com.opensymphony.xwork2.validator.validators.FieldExpressionValidator"/>
    <validator name="email" class="com.opensymphony.xwork2.validator.validators.EmailValidator"/>
    <validator name="url" class="com.opensymphony.xwork2.validator.validators.URLValidator"/>
    <validator name="visitor" class="com.opensymphony.xwork2.validator.validators.VisitorFieldValidator"/>
    <validator name="conversion" class="com.opensymphony.xwork2.validator.validators.ConversionErrorFieldValidator"/>
    <validator name="stringlength" class="com.opensymphony.xwork2.validator.validators.StringLengthFieldValidator"/>
    <validator name="regex" class="com.opensymphony.xwork2.validator.validators.RegexFieldValidator"/>
    <validator name="conditionalvisitor" class="com.opensymphony.xwork2.validator.validators.ConditionalVisitorFieldValidator"/>
</validators>
<!--  END SNIPPET: validators-default -->

如果寫xml,從而定義驗證規則:
1)XML文件名稱語法: ActionClassName-validation.xml
注意:此xml需要與當期要驗證的action在同一個目錄:
舉例:UserAction-validation.xml
2) 寫XML

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
        "-//Apache Struts//XWork Validator 1.0.3//EN"
        "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">

<validators>

    <!-- 驗證的每一個字段用field表示 -->
    <field name="user.userName">
        <!-- 指定使用的驗證器 -->
        <field-validator type="requiredstring">
            <!-- 驗證失敗的錯誤提示信息 -->
            <message>用戶名不能爲空!</message>
        </field-validator>
    </field>

    <!-- 驗證pwd -->
    <field name="user.pwd">

        <!-- 非空 -->
        <field-validator type="requiredstring">
            <message>密碼不能爲空!</message>
        </field-validator>

        <!-- 長度 -->
        <field-validator type="stringlength">
            <param name="minLength">6</param>
            <param name="maxLength">8</param>
            <message>密碼必須爲6-8位!</message>
        </field-validator>
    </field>

    <!-- 驗證日期 -->
    <field name="user.birth">
        <field-validator type="date">
            <message>日期格式不對!</message>
        </field-validator>
    </field>

    <!-- 驗證Email -->
    <field name="user.email">
        <field-validator type="email">
            <message>郵箱格式錯誤!</message>
        </field-validator>
    </field>

</validators>       

XML方式驗證Action中指定的方法:

與上面xml驗證方式大致相同: 驗證xml文件內容不變;
文件命名:
語法:ActionClassName-ActionName-validation.xml
舉例:UserAction-user_register-validation.xml
驗證UserAction中的register方法

驗證總結
代碼:
重寫validate() , 驗證action所有方法
Validate方法名(), 驗證指定“方法名”的方法
Xml:
驗證所有方法: ActionClassName-validation.xml
驗證指定方法: ActionClassName-actionName-validation.xml

代碼驗證,
    比較靈活,可以滿足所有的需求.
    比較繁瑣,要寫重複的驗證判斷邏輯!
    適合: 表單字段較少的情況用!
XML驗證:
    通用,但不夠靈活; 可以驗證特定簡單的業務。
    適合: 驗證表單字段較多,可以大大簡化代碼!
          (配置文件過多)

驗證錯誤處理
Struts在進行數據效驗的時候,驗證失敗,會返回input視圖,要求我們要在struts.xml中配置input視圖對應的錯誤頁面!

配置:

Struts.xml
<!-- 註冊失敗跳轉到註冊頁面,顯示失敗信息 -->
        <global-results>
            <result name="input">/register.jsp</result>
        </global-results>

Jsp顯示錯誤
方式1:顯示所有錯誤

<%@taglib uri="/struts-tags" prefix="s" %>
    <!-- 顯示的是struts在運行時期產生的所有錯誤 -->
    <s:fielderror></s:fielderror>

方式2:顯示指定的錯誤

<!-- 修改struts標籤默認的樣式: 不讓換行 --> 
    <style type="text/css">
    ul{
        display: inline;
    }
    ul li{
        display: inline;
        color: red;
    }
    </style>

顯示指定的錯誤:

<s:fielderror fieldName="user.userName"></s:fielderror>

方式3: 修改標籤定義的模板
找到fielderror標籤定義的模板文件:

Struts-core.jar\template\simple\ fielderror.ftl

把修改後的fielderror.ftl文件,放到src/ template/ simple/ fielderror.ftl

這樣標籤顯示的樣式就修改了!

  1. Struts 簡單UI標籤
<!-- 服務器標籤 : 最終別解析爲html標籤-->
    <s:form action="/user_login" method="post" name="frmLogin" id="frmLogin" theme="simple">

        用戶名:<s:textfield name="user.name"></s:textfield>
        密碼:<s:textfield name="user.pwd"></s:textfield>
        <s:submit value="登陸"></s:submit>
    </s:form>

注意:
給form指定主題,form下所有的表單元素都應用此主題!

對於struts標籤默認的主題樣式:default.xml/struts.ui.theme=xhtml
可以通過常量修改, 改爲簡單主題:

<!-- 修改主題 (當前項目所有的標籤都用此主題)-->
    <constant 
name="struts.ui.theme" value="simple"></constant>
  1. Struts ognl表達式語言幾個符號
    1) # 獲取非根元素值 、 動態都建map集合
    2) $ 配置文件取值
    3) % 提供一個ognl表達式運行環境
<body>
     <br/>獲取request域數據<br/>
     <!-- property 標籤是對象類型的標籤,默認支持ognl表達式, 會從根元素去China名稱對應的值 -->
     <s:property value="China"/>        <br/>
     <!-- 如果直接賦值,需要用單引號 -->
     <s:property value="'China'"/>      <br/>
     <s:property value="%{#request.cn}"/>       <br/>

     <!-- 值類型的標籤,value值默認就是值類型,不支持ognl表達式 -->
     國家:<s:textfield name="txtCountry" value="%{#request.cn}"></s:textfield>
  </body>
  1. Struts中常用的幾個技術
    數據回顯
    數據回顯,必須要用struts標籤!

Action中:
// 進入修改頁面
public String viewUpdate() {
// 模擬一個對象(先獲取一個id,再根據id調用service查詢,把查到的結果保存到域)

    User userInfo = new User();
        userInfo.setUserName("Jack");
        userInfo.setEmail("[email protected]");

        ActionContext ac = ActionContext.getContext();
//      Map<String,Object> request = (Map<String, Object>) ac.get("request");
//      request.put("userInfo", userInfo);

        /************* 數據回顯***************/
        // 獲取值棧
        ValueStack vs = ac.getValueStack();
        vs.pop();// 移除棧頂元素
        vs.push(userInfo);  // 入棧


        // 進入修改頁面
        return "viewUpdate";
    }

JSP頁面:

<body>
    <%@taglib uri="/struts-tags" prefix="s" %>


    <br/>
    <!-- 在頁面文本框內,顯示要修改記錄的數據 -->

    <!-- 手動通過value設置顯示的值 
    <s:form action="#">

        用戶名: <s:textfield name="user.userName" value="%{#request.userInfo.userName}"></s:textfield>   <br/>

        郵箱: <s:textfield name="user.email" value="%{#request.userInfo.email}"></s:textfield>     <br/>
    </s:form>
    -->

    <!-- 數據回顯技術:s:textfield會自動查找根元素數據(Ognl表達式語言取值)  -->
    <s:form action="#">

        用戶名: <s:textfield name="userName"></s:textfield>   <br/>

        郵箱: <s:textfield name="email"></s:textfield>     <br/>
    </s:form>

    <s:debug></s:debug>
  </body>

模型驅動
Struts運行時候,會執行默認的攔截器棧,其中有一個攔截器,模型驅動攔截器:

<interceptor 
name="modelDriven" class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/>

@Override
    public String intercept(ActionInvocation invocation) throws Exception {
        Object action = invocation.getAction();

        if (action instanceof ModelDriven) {
            ModelDriven modelDriven = (ModelDriven) action;
            ValueStack stack = invocation.getStack();
            Object model = modelDriven.getModel();
            if (model !=  null) {
                stack.push(model);
            }
            if (refreshModelBeforeResult) {
                invocation.addPreResultListener(new RefreshModelBeforeResult(modelDriven, model));
            }
        }
        return invocation.invoke();
    }

引入

prams攔截器,可以把請求數據自動填充的action的屬性中

舉例1:
JSP

   <input type=text name=userName />
   <input type=text name=pwd />

Action
    class UserAction{
        // 封裝請求數據
        private String userName;
        private String pwd;
        //.. set方法
    }

舉例2:
JSP

   <input type=text name=user.userName />
   <input type=text name=user.pwd />

Action

 class UserAction{
        // 封裝請求數據
        private User user;

        ..
    }

舉例3:(模型驅動)
JSP

   <input type=text name=userName />
   <input type=text name=pwd />

Action

  class UserAction{
        // 封裝請求數據
        private User user;

        ..
    }

步驟及原理
步驟:
1. 實現ModelDriver接口
2. 實現接口方法: 接口方法返回的就是要封裝的對象
3. 對象一定要實例化。

分析:

/**
 * 1. 數據回顯
 * 2. 模型驅動
 * @author Jie.Yuan
 *
 */
public class UserAction extends ActionSupport implements ModelDriven<User> {

    // 封裝請求數據
    private User user = new User();
    public void setUser(User user) {
        this.user = user;
    }
    public User getUser() {
        return user;
    }

    // 實現模型驅動接口方法
    @Override
    public User getModel() {
        return user;
    }


    public String add() {
        // 測試: 使用了模型驅動,是否數據正常? Ok
        System.out.println(user);
        return "success";
    }

防止表單重複提交
Struts提供了防止表單重複提交攔截器:

<interceptor name="token" 
class="org.apache.struts2.interceptor.TokenInterceptor"/>

綜合案例:
1. 建庫、建表


-- 刪除數據庫
DROP DATABASE hib_demo;
-- 創建數據庫
CREATE DATABASE hib_demo DEFAULT CHARACTER SET utf8;
-- 建表
CREATE TABLE employee (
   id INT PRIMARY KEY AUTO_INCREMENT,
   empName VARCHAR(20),
   workDate DATE      -- 入職時間
)
2. 搭建環境
    搭建struts環境
    組件:c3p0/dbutils/驅動
發佈了52 篇原創文章 · 獲贊 77 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章