Struct2入門三

Struts2國際化
1、 國際化原理 ? 什麼是國際化 ?
同一款軟件 可以爲不同用戶,提供不同語言界面 —- 國際化軟件
需要一個語言資源包(很多properties文件,每個properties文件 針對一個國家或者語言 ,通過java程序根據來訪者國家語言,自動讀取不同properties文件 )

2、 資源包編寫
properties文件命名 : 基本名稱語言(小寫)國家(大寫).properties
例如 :
messages_zh_CN.properties 中國中文
messages_en_US.properties 美國英文
3、 ResourceBundle 根據不同Locale(地域信息),讀取不同國家 properties文件
ResourceBundle bundle = ResourceBundle.getBundle(“messages”, Locale.US);
國際化配置
第一種 全局國際化信息文件 (所有Action都可以使用 ) ——- 最常用
* properties文件可以在任何包中
* 需要在struts.xml 中配置全局信息文件位置

struts.xml

<constant name="struts.custom.i18n.resources" value="messages"></constant>   messages.properties 在src根目錄
    <constant name="struts.custom.i18n.resources" value="cn.itcast.resources.messages"></constant>   
messages.properties 在 cn.itcast.resources 包

國際化信息
在Action中使用 : this.getText(“msg”);
在jsp中使用 :
在配置文件中(校驗xml) :

第二種 Action範圍信息文件 (只能在某個Action中使用 )
數據只能在對應Action中使用,在Action類所在包 創建 Action類名.properties ——— 無需配置

第三種 package範圍信息文件 (package中所有Action都可以使用 )
數據對包 (包括子包)中的所有Action 都有效 , 在包中創建 package.properties —– 無需配置

第四種 臨時信息文件 (主要在jsp中 引入國際化信息 )
在jsp指定讀取 哪個properties文件


* 向信息中傳遞參數 {0} {1} ———— MessageFormat 動態消息文本
this.getText(“required”, new String[] { “用戶名” });

Struts2攔截器
攔截器介紹
攔截器 的使用 ,源自Spring AOP(面向切面編程)思想
攔截器 採用 責任鏈 模式
* 在責任鏈模式裏,很多對象由每一個對象對其下家的引用而連接起來形成一條鏈。
* 責任鏈每一個節點,都可以繼續調用下一個節點,也可以阻止流程繼續執行

在struts2 中可以定義很多個攔截器,將多個攔截器按照特定順序 組成攔截器棧 (順序調用 棧中的每一個攔截器 )

1、 struts2 所有攔截器 都必須實現 Interceptor 接口
2、 AbstractInterceptor 類實現了 Interceptor 接口. 併爲 init, destroy 提供了一個空白的實現

所有實際開發中,自定義攔截器 只需要 繼承 AbstractInterceptor類, 提供 intercept 方法實現

3、 常用struts2 攔截器

<interceptor-ref name="modelDriven"/> 模型驅動
    <interceptor-ref name="fileUpload"/> 文件上傳
    <interceptor-ref name="params"> 參數解析封裝 
    <interceptor-ref name="conversionError"/> 類型轉換錯誤
    <interceptor-ref name="validation"> 請求參數校驗
    <interceptor-ref name="workflow"> 攔截跳轉 input 視圖

自定義攔截器案例
案例 : 登陸,對其它Action訪問 通過自定義攔截器 進行權限控制
導入jar包 (struts2 jar、c3p0、 dbutils、 mysql驅動)
web.xml
struts.xml
JDBCUtils 工具類

第一步 : 編寫index.jsp 提供 圖書增刪改查 四個功能
編寫BookAction ,提供四個業務方法

第二步: 完成登陸功能

第三步 :必須要登陸 才能進行圖書管理
使用Filter 進行權限控制 —- 過濾所有web請求 (所有web資源訪問)
使用攔截器 進行權限控制 —- 主要攔截對Action訪問 (不能攔截JSP)

定義攔截器 繼承AbstractInterceptor

配置攔截器
方式一

<!-- 註冊攔截器 -->
<interceptors>
            <interceptor name="privilege" class="cn.itcast.interceptor.PrivilegeInterceptor"></interceptor>
        </interceptors>
        <action name="book_*" class="cn.itcast.action.BookAction" method="{1}" >
            <!-- 使用攔截器 -->
            <!-- 當使用自定義攔截器 後,默認攔截器 就會失效  -->
    <interceptor-ref name="defaultStack"></interceptor-ref>
    nterceptor-ref name="privilege"></interceptor-ref>
        </action>
方式二
    <!-- 註冊攔截器 -->
<interceptors>
            <interceptor name="privilege" class="cn.itcast.interceptor.PrivilegeInterceptor"></interceptor>
            <!-- 自定義攔截器棧 -->
            <interceptor-stack name="privilegeStack">
                <interceptor-ref name="defaultStack"></interceptor-ref>
                <interceptor-ref name="privilege"></interceptor-ref>
            </interceptor-stack>
        </interceptors>

        <!-- 設置當前包 所有Action 都使用 自定義攔截器棧 -->
        <default-interceptor-ref name="privilegeStack"></default-interceptor-ref>

Struts2文件上傳下載
Struts2文件上傳
提供 FileUpload 攔截器,用於解析 multipart/form-data 編碼格式請求,解析上傳文件的內容
fileUpload攔截器 默認在 defaultStack 棧中, 默認會執行的

在Action需要對上傳文件內容進行接收
頁面:

<input type="file" name="upload" />
    Action :
        public class UploadAction extends ActionSupport {
            // 接收上傳內容
            // <input type="file" name="upload" />
            private File upload; // 這裏變量名 和 頁面表單元素 name 屬性一致
            private String uploadContentType;
            private String uploadFileName;
        } 
    * 格式 : 上傳表單項name屬性 + ContentType 、 上傳表單項name屬性 + FileName
    * 爲三個對象 提供 setter 方法

通過FileUtils 提供 copyFile 進行文件複製,將上傳文件 保存到服務器端
Struts2文件上傳問題解決
配置 input 視圖 ,作爲上傳出錯後 跳轉頁面
在文件上傳時,如果發生錯誤 ,fileUpload攔截器 會設置錯誤信息,workflow攔截器 跳轉到 input 視圖

struts.multipart.parser=jakarta 定義文件上傳,採用 commons-fileupload 技術
* 同時支持 cos 、pell 上傳技術 (如果使用其它上傳技術,單獨下載jar包 )

通過 struts.multipart.maxSize 常量設置文件上傳總大小限制
* struts.multipart.maxSize=2097152 默認上傳文件總大小 2MB
* 超過文件總大小,跳轉input 視圖, 通過 回顯錯誤信息
在struts.xml 設置上傳總大小

設置上傳文件總大小,對所有上傳form有效,只想對當前form進行設置,可以設置fileUpload攔截器屬性
FileUpload 攔截器有 3 個屬性可以設置.
* maximumSize: 上傳文件的最大長度(以字節爲單位), 默認值爲 2 MB
* allowedTypes: 允許上傳文件的類型, 各類型之間以逗號分隔
* allowedExtensions: 允許上傳文件擴展名, 各擴展名之間以逗號分隔
如果針對fileUpload 進行參數設置,當出錯時,在頁面通過 回顯錯誤信息

struts-messages.properties 文件裏預定義 上傳錯誤信息,通過覆蓋對應key 顯示中文信息

struts.messages.error.uploading=Error uploading: {0}
    struts.messages.error.file.too.large=The file is to large to be uploaded: {0} "{1}" "{2}" {3}
    struts.messages.error.content.type.not.allowed=Content-Type not allowed: {0} "{1}" "{2}" {3}
    struts.messages.error.file.extension.not.allowed=File extension not allowed: {0} "{1}" "{2}" {3}

修改爲

struts.messages.error.uploading=上傳錯誤: {0}
    struts.messages.error.file.too.large=上傳文件太大: {0} "{1}" "{2}" {3}
    struts.messages.error.content.type.not.allowed=上傳文件的類型不允許: {0} "{1}" "{2}" {3}
    struts.messages.error.file.extension.not.allowed=上傳文件的後綴名不允許: {0} "{1}" "{2}" {3}

多文件上傳
第一步:在WEB-INF/lib下加入commons-fileupload-1.2.1.jar、commons-io-1.3.2.jar。這兩個文件可以從http://commons.apache.org/下載。
第二步:把form表的enctype設置爲:“multipart/form-data“,如下:

<form enctype="multipart/form-data" action="${pageContext.request.contextPath}/xxx.action" method="post">
  <input  type="file" name="uploadImages">
  <input  type="file" name="uploadImages">
</form>

第三步:在Action類中添加以下屬性,屬性紅色部分對應於表單中文件字段的名稱:

public class uploadAction{
  private File[] uploadImages;//得到上傳的文件
  private String[] uploadImagesContentType;//得到文件的類型
  private String[] uploadImagesFileName;//得到文件的名稱
  //這裏略省了屬性的getter/setter方法
  public String saveFiles() throws Exception{
        ServletContext sc = ServletActionContext.getServletContext();
        String realpath = sc.getRealPath("/uploadfile");
        try {
            if(uploadImages!=null&&uploadImages.length>0){
                 for(int i=0;i<uploadImages.length;i++){
                         File destFile = new File(realpath,uploadImageFileNames[i]);
                         FileUtils.copyFile(uploadImages[i], destFile);
                  }
             }
         } catch (IOException e) {
              e.printStackTrace();}return "success";}}

Struts2文件下載
1) struts2 完成文件下載,通過 結果集類型 (Result Type) stream 來完成的
struts-default.xml 定義
2) 使用Stream結果集 完成文件下載
文件下載原理: 服務器讀取下載文件內容,通過Response響應流寫回, 設置 ContentType、 ContentDisposition 頭信息

public class StreamResult extends StrutsResultSupport {
    protected String contentType = "text/plain"; // contentType頭信息  (下載文件對應 MIME協議規定類型 )
        * html --- text/html . txt--- text/plain 
    protected String contentDisposition = "inline"; // ContentDisposition頭信息 (下載文件打開方式 inline瀏覽器內部打開, attachment 以附件形式打開)

    protected String inputName = "inputStream";  // 需要Action中 提供 getInputStream 方法 返回 InputStream 提供下載文件 內容 
}   

Action 提供 InputStream 返回值 getInputStream 方法 ——- 指定下載文件流
配置 stream 結果集 參數 contentTypeActiongetContentTypeServletActionContext.getServletContext().getMimeType(filename);streamattachment;filename= {filename} —- 在Action 提供 getFilename
* 下載附件名亂碼問題 , IE和火狐 解決不同
* public String encodeDownloadFilename(String filename, String agent)
throws IOException {
if (agent.contains("Firefox")) { // 火狐瀏覽器
filename = "=?UTF-8?B?"
+ new BASE64Encoder().encode(filename.getBytes("utf-8"))
+ "?=";
} else { // IE及其他瀏覽器
filename = URLEncoder.encode(filename, "utf-8");
}
return filename;
}

OGNL表示式使用 和 值棧

OGNL是Object Graphic Navigation Language(對象圖導航語言)的縮寫,它是一個開源項目。 Struts2框架使用OGNL作爲默認的表達式語言。
* xwork 提供 OGNL表達式
* ognl-3.0.5.jar
OGNL 是一種比EL 強大很多倍的語言

OGNL 提供五大類功能
1、支持對象方法調用,如xxx.doSomeSpecial();
2、支持類靜態的方法調用和值訪問
3、訪問OGNL上下文(OGNL context)和ActionContext; (重點 操作ValueStack值棧 )
4、支持賦值操作和表達式串聯
5、操作集合對象。

1、 使用OGNL訪問 對象方法 和 靜態方法
* OGNL 在jsp 結合 struts2 標籤庫 使用 , 執行 ognl表達式
調用 實例方法 : 對象.方法() —-
調用 靜態方法 : @[類全名(包括包路徑)]@[方法名] —
* 使用 靜態方法調用 必須 設置 struts.ognl.allowStaticMethodAccess=true

2、 訪問OGNL上下文(OGNL context)和ActionContext
OGNL上下文(OGNL context) 對象 —– 值棧 ValueStack

問題一 : 什麼是值棧 ValueStack ?
ValueStack 是 struts2 提供一個接口,實現類 OgnlValueStack —- 值棧對象 (OGNL是從值棧中獲取數據的 )
每個Action實例都有一個ValueStack對象 (一個請求 對應 一個ValueStack對象 )
在其中保存當前Action 對象和其他相關對象 (值棧中 是有Action 引用的 )
Struts 框架把 ValueStack 對象保存在名爲 “struts.valueStack” 的請求屬性中,request中 (值棧對象 是 request一個屬性)

問題二 : 值棧的內部結構 ?
值棧由兩部分組成
ObjectStack: Struts 把動作和相關對象壓入 ObjectStack 中–List
ContextMap: Struts 把各種各樣的映射關係(一些 Map 類型的對象) 壓入 ContextMap 中
Struts 會把下面這些映射壓入 ContextMap 中
parameters: 該 Map 中包含當前請求的請求參數
request: 該 Map 中包含當前 request 對象中的所有屬性
session: 該 Map 中包含當前 session 對象中的所有屬性
application:該 Map 中包含當前 application 對象中的所有屬性
attr: 該 Map 按如下順序來檢索某個屬性: request, session, application

ValueStack中 存在root屬性 (CompoundRoot) 、 context 屬性 (OgnlContext )
* CompoundRoot 就是ArrayList
* OgnlContext 就是 Map
context 對應Map 引入 root對象
* context中還存在 request、 session、application、 attr、 parameters 對象引用
* OGNL表達式,訪問root中數據時 不需要 #, 訪問 request、 session、application、 attr、 parameters 對象數據 必須寫 #
* 操作值棧 默認指 操作 root 元素

問題三 : 值棧對象的創建 ,ValueStack 和 ActionContext 是什麼關係 ?
值棧對象 是請求時 創建的
doFilter中 prepare.createActionContext(request, response);
* 創建ActionContext 對象過程中,創建 值棧對象ValueStack
* ActionContext對象 對 ValueStack對象 有引用的 (在程序中 通過 ActionContext 獲得 值棧對象 )
Dispatcher類 serviceAction 方法中 將值棧對象保存到 request範圍
request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack());

問題四 : 如何獲得值棧對象
獲得值棧對象 有兩種方法

ValueStack valueStack = (ValueStack) ServletActionContext.getRequest().getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
    ValueStack valueStack2 = ActionContext.getContext().getValueStack();

問題五: 向值棧保存數據 (主要針對 root)
兩種方式

// 將數據保存root的索引0位置,放置到第一個元素 ArrayList add(0,element);
        valueStack.push("itcast");

        // 在值棧創建參數map, 將數據保存到map中
        valueStack.set("company", "傳智播客");

    在jsp中 通過 <s:debug /> 查看值棧的內容 

問題六: 在JSP中獲取值棧的數據
訪問root中數據 不需要#
訪問 其它對象數據 加 #

通過下標獲取root中對象
//取值棧頂對象
直接在root中查找對象屬性 (自上而下自動查找)
valueStack:

在OgnlContext中獲取數據

request:<s:property value="#request.username"/>
session:<s:property value="#session.username"/>
application:<s:property value="#application.username"/>
attr:<s:property value="#attr.username"/>
parameters:<s:property value="#parameters.cid[0]"/>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章