struts2馬士兵筆記

 

 

 

 

 


Struts2 學習筆記

---wjt276

 

 

 

[年一月五日 ]

 

 


目錄

01 Struts2-Action. 5

一、         Struts作用:.... 5

二、         搭建Struts2的運行環境:.... 5

三、         Namespace. 6

四、         <package>標籤.... 6

五、         Action. 6

六、         路徑問題的說明.... 8

七、         Action的動態調用方法.... 8

八、         Action通配符(wildcard)的配置.... 9

九、         Action的屬性接收參數.... 10

1       Action添加成員屬性接受參數.... 10

2       域模(Domain Model).. 10

3       ModelDriven接收參數.... 11

十、         Action屬性接收參數中文問題.... 12

十一、         簡單數據驗證.... 12

十二、         訪問Web元素.... 14

一、         方法一:ActionContext方式.... 15

二、         方式二:Ioc(控制反轉)—推薦使用.... 15

三、         方式三:獲取原類型.... 16

四、         方式四:獲取原類型-控制反轉.... 17

十三         Struts2配置文件模塊化包含(include). 17

十四、         默認的Action. 18

十五、         Action總結.... 18

02 Struts2-Result. 19

一、         Result類型 (type). 19

二、         全局結果集(Globle Result). 20

三、         動態的結果集(dynamic result). 21

四、         帶參數的結果集.... 21

五、         Result總結.... 22

六、         項目經理:.... 22

03 OGNL表達式語言.... 23

04 Struts2-Tags. 28

Struts2標籤目錄.... 28

一、         property標籤.... 28

二、         set標籤.... 29

三、         bean標籤.... 29

四、         <include>標籤-少使用.... 29

五、         If elseif else. 30

六、         Iterator標籤.... 31

七、         Theme. 31

05設計約定(編碼規定) 32

06 項目開發順序.... 32

07 聲明式異常處理.... 33

08 國際化.... 35

一、         國際化資源文件.... 35

二、         Java國際化.... 35

三、         Struts2國際化.... 35

1       Action級別.... 35

2       Package級別.... 36

3       Application級別.... 36

四、         資源文件中的參數處理.... 37

五、         國際化-動態語言切換.... 37

09 自定義攔截器.... 38

10 類型轉換.... 38

Struts2總結.... 39

 


目錄

Ø  Action

n  簡單數據校驗

Ø  Result

Ø  常用配置文件

Ø  OGNL & ValueStack

Ø  Tags

Ø  ---------------------Project

n  類型轉換、上傳與下載、interceptor、防止重複提交

Ø  MVC思想深入剖析

Ø  源碼解讀

Ø  其他話題

 

 


01 Struts2-Action

一、Struts作用:

將請求與結果分開

二、搭建Struts2的運行環境:

1、建立Web項目;

2、建立Struts2的配置文件(struts.xml)

     Struts2的空項目中的配置文件(struts.xml)複製到項目的src目錄下。

     配置如下:

<!--

     struts.devMode : 是否設置爲開發模式 true:是開發模式,否則不是

           注:在開發模式下,修改Struts的配置文件後不需要重新啓動Tomcat服務器即生效。

             否則修改Struts配置文件後需要重新啓動Tomcat服務器才生效。

     -->   

<constant name="struts.devMode" value="true" />

   

    <!--

      namespace :對應與項目名稱後面的"/"(例如Struts2_0100_Introduction後面的"/")

        (http://localhost:8080/Struts2_0100_Introduction/)

      -->

    <package name="default" namespace="/" extends="struts-default">

        <action name="hello">

            <result>

                /hello.jsp

            </result>

        </action>

</package>

3、複製Struts2相應的jar包及第三方包。

     將空項目中lib目錄中的除junitspring-test之外的所有文件複製到項目的WebRoot/WEB-INF/lib目錄下

4、修改對應的web.xml,建立struts2filter(參考struts自帶的項目),添加如下配置:

    <filter>

        <filter-name>struts2</filter-name>

        <filter-class>

org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter

</filter-class>

    </filter>

 

    <filter-mapping>

        <filter-name>struts2</filter-name>

        <url-pattern>/*</url-pattern>

    </filter-mapping>

 

三、Namespace

Namespace決定了action的訪問路徑,默認爲“”,可以接收所有路徑的action,如果沒有找到相應的namespace時,則使用namespace爲空的action

Namespace可以寫爲/,或者/xxx,或者/xxx/yyy,對應的action訪問路徑爲/index.action/xxx/index.action、或者/xxx/yyy/index.action.

Namespace最好也用模塊來進行命名。

namespace :對應與項目名稱後面的"/"(例如Struts2_0100_Introduction後面的"/")

        (http://localhost:8080/Struts2_0100_Introduction/)

 

四、<package>標籤

<package>是用來解決重名的問題,例如當系統的前臺和後臺都有一個action名叫hello,這時就需要用package來區分。    前臺<package name="front">後臺<package name="back">

struts2中的packagejavapackage是相同的作用的。

五、Action

具體視圖的返回可以由用戶自己定義的Action來決定

具體的手段是根據返回的字符串找到對應的配置項,來決定視圖的內容,有三種手段:

<constant name="struts.devMode" value="true" />

    <package name="front" extends="struts-default" namespace="/">

        <action name="index" class="com.bjsxt.struts2.front.action.IndexAction1">

            <result name="success">/ActionIntroduction.jsp</result>

        </action>

 </package>

    注:<action>標籤中的class屬性是表示action的對應的類(這個類是一個普通Java),當訪問這個action時會創建這個類成爲一個對象,然後執行這個對象中的execute方法()(execute方法返回類型爲String)

第一種:Action 普通Java

public class IndexAction1 {

    public String execute() {

       return "success";

    }

}

<action>標籤中class屬性省略時,則默認執行com.opensymphony.xwork2.ActionSupport類中的execute方法,而這個方法返回一個字符串常量SUCCESS(常量值爲:”success”).

 

第二種:Action 實現com.opensymphony.xwork2.Action接口,這個接口中定義了一些常量和一個execute方法,我們重寫execute()方法就可以了。

import com.opensymphony.xwork2.Action;

public class IndexAction2 implements Action {

    @Override

    public String execute() {

       //return "success";

       return this.SUCCESS; //SUCCESS常量值爲:"success"

    }

}

 

第三種:Action 繼承com.opensymphony.xwork2.ActionSupport類,而這個類又實現了com.opensymphony.xwork2.Action接口,我們重寫execute()方法就可以了。

 

import com.opensymphony.xwork2.ActionSupport;

public class IndexAction3 extends ActionSupport {

    @Override

    public String execute() {

       //return "success";

       return this.SUCCESS;//SUCCESS常量值爲:"success"

    }

}

注:第三種Action是我們需要使用的方式,因爲這個類不擔實現了com.opensymphony.xwork2.Action接口,更重要的是它已經幫我封裝了許多其它有用的方法。

 

 

六、路徑問題的說明

struts2中的路徑問題是根據action的路徑而不是jsp路徑來確定,所以儘量不要使用相對路徑。
雖然可以用redirect方式解決,但redirect方式並非必要。

解決辦法非常簡單,統一使用絕對路徑。(在jsp中用request.getContextRoot方式來拿到webapp的路徑)
或者使用myeclipse經常用的,指定basePath

 

還有另一種方式,就是在<head>標籤中,指定<base>標籤值,這樣就使用統一絕對路徑。

   <%

String path = request.getContextPath();//

String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

%>

<head>

<base href="<%=basePath%>" />

…………

注:<base>標籤:當前頁面中所有連接都會在前面加上base地址。

七、Action的動態調用方法

Action執行的時候並不一定要執行execute方法,我們可以指定Action執行哪個方法:

1、   方法一(通過methed屬性指定執行方法)

可以在配置文件中配置Action的時候用method=來指定執行哪個方法

<action name="userAdd" class="com.bjsxt.struts2.user.action.UserAction" method="add">

            <result>/user_add_success.jsp</result>

</action>

    這樣,只要在action的對象中有一個add的方法,並且返回類型爲String就可以了。如果沒有method屬性,則默認執行execute()方法。

import com.opensymphony.xwork2.ActionSupport;

public class UserAction extends ActionSupport {

    public String add() {

       return SUCCESS;

    }  

}

2、   動態方法調用DMI(推薦)

可以在url地址中動態指定action執行那個方法。Url地址如下:

方法:action + ! + 方法名

注:只要Action對象中有這個方法,並且返回類型爲String就可以調用。

這樣Struts.xml配置文件中不需要配置methed屬性。代碼如下:

<action name="user" class="com.bjsxt.struts2.user.action.UserAction">

       <result>/user_add_success.jsp</result>

</action>

Action類:

public class UserAction extends ActionSupport {

    public String add() {

       return SUCCESS;

    }  

}

     總結:推薦使用第二種動態方法調用DMI因爲第一種需要大量的Action配置,後者可以在url中動態指定執行action中哪個方法。

八、Action通配符(wildcard)的配置

使用通配符,將配置量降到最低, 不過,一定要遵守"約定優於配置"的原則

1、   通配符

星號(*)  表示所有

{數字} 表示第幾個通配符

例如:Student*  那麼{1}代表第一個星號(*)

           *_*            那麼{1}代表第一個星號(*) {2}代表第二個星號(*)

2、   實例

<package name="actions" extends="struts-default" namespace="/actions">

        <action name="Student*" class="com.bjsxt.struts2.action.StudentAction" method="{1}">

            <result>/Student{1}_success.jsp</result>

        </action>

       

        <action name="*_*" class="com.bjsxt.struts2.action.{1}Action" method="{2}">

            <result>/{1}_{2}_success.jsp</result>

            <!-- {0}_success.jsp -->

        </action>

</package>

解釋:第一個Action的名稱爲name=”Student*” method=”{1}”,表示所有ActionStudent開始的都會執行這個Action,並且執行Student後字符爲方法名的方法,例如:訪問的ActionStudentadd,會執行這個Action(Student*),並且執行add的方法.因爲{1}在這裏代表add,並且返回/Studentadd_success.jsp頁面。

第二個Action的名稱name=”*_*” method=”{2}” class=”action.{1}Action” 表示所有Action中包含下劃線(“_”)都會執行這個Action,例如:Teacher_add,那麼會執行這個Action,並且Action對應的類爲TeacherAction,且執行Action中的add方法,返回結果頁面爲/Teacher_add_success.jsp,因爲在這裏的{1}表示Teacher,{2}表示add

3、   匹配順序

當匹配的Action有兩個以上時,則會按匹配精確度高的那個Action,當有個相同的匹配精確度時,則按先後順序進行。

 

九、Action的屬性接收參數

Action中三種傳遞並接受參數:

1、 Action添加成員屬性接受參數

例如請求的URL地址:

其中傳遞了兩個參數:nameage,其值分別爲:a8,此Action執行的是add()方法。

那我們只要在user這個Action對象中添加這兩個成員屬性並生成setget方法。

public class UserAction extends ActionSupport {

   

    private String name;

    private int age;

   

    public String add() {

       System.out.println("name=" + name);

       System.out.println("age=" + age);

       return SUCCESS;

    }

    public String getName() {

       return name;

    }

    public void setName(String name) {

       this.name = name;

    }

    public int getAge() {

       return age;

    }

    public void setAge(int age) {

       this.age = age;

    }  

}

2、 域模型(Domain Model)

就是利用對象域來進行傳遞和接受參數

例如請求的URL地址:

其中,訪問的是namespace=”/user” actionname=”user” Action所執行的方法method=”add”

     利用對象域user來傳遞參數,爲對象的屬性賦值(user.name=a user.age=8)

     注:需要一個對象user 並且這個對象需要有兩個成員屬性,且具有getset方法。

     然後在Action中添加一個User對象的成員屬性。並且有getset方法,就可以了。

//User對象

public class User {

  private String name;

  private int age;

  public String getName() {

     return name;

  }

  public void setName(String name) {

     this.name = name;

  }

  public int getAge() {

     return age;

  }

  public void setAge(int age) {

     this.age = age;

  }

}

 

    //Action

public class UserAction extends ActionSupport {

  private User user;

  //private UserDTO userDTO;

  public String add() {

     System.out.println("name=" + user.getName());

     System.out.println("age=" + user.getAge());

     return SUCCESS;

  }

 

  public User getUser() {

     return user;

  }

  public void setUser(User user) {

     this.user = user;

  }

}

3、 ModelDriven接收參數

使Action實現com.opensymphony.xwork2.ModelDriven<User>(在實現接口時需要使用泛型,否則使用時需要轉型)中利用其getModel()方法返回對象模型,從而獲得傳入的參數。

例如URL如下:

其:訪問的是namespace=”/user” actionname=”user” Action所執行的方法method=”add”,其傳入了兩個參數:name=a,age=8

參數被傳入至Action後,會被ModelDriven對象根據參數名自動賦值給User對象相應的屬性而生成User對象,並且由getModel()返回。那麼我們在Action中就可以利用這個對象了。

注意:傳入的參數名需要與對象模型中的成員屬性一致。

對象模型User:

public class User {

    private String name;

    private int age;

    public String getName() {

       return name;

    }

    public void setName(String name) {

       this.name = name;

    }

    public int getAge() {

       return age;

    }

    public void setAge(int age) {

       this.age = age;

    }

}

    Action對象

import com.opensymphony.xwork2.ActionSupport;

import com.opensymphony.xwork2.ModelDriven;

public class UserAction extends ActionSupport implements ModelDriven<User>{

  private User user = new User();

  public String add() {

     System.out.println("name=" + user.getName());

     System.out.println("age=" + user.getAge());

     return SUCCESS;

  }

  @Override

  public User getModel() {

     return user;

  }   }  

十、Action屬性接收參數中文問題

如果表單提交數據中有中文時,儘量使用post方式。

需要在Struts.xml配置文件中加入一個常量配置,如下:

<struts>

    <constant name="struts.devMode" value="true" />

    <constant name="struts.i18n.encoding" value="GBK" /><!-- internationalization -->

    <package name="user" extends="struts-default" namespace="/user">

        <action name="userAdd" class="com.bjsxt.struts2.user.action.UserAction" method="add">

            <result>/user_add_success.jsp</result>

        </action>

    </package>

</struts>

但是,在Struts2 2.7之前,這個配置無效,需要其它方法設置。如下:

手動在web.xml中在Struts過濾器之前配置一個過濾器用於解決中文的問題。

十一、     簡單數據驗證

使用addFieldError方法和s:fieldError標籤簡單處理數據校驗

場景:對一個用戶名進行驗證,如果用戶名不合法,則顯示給客戶端查看信息。

URL請求地址:

分析:訪問的Struts2配置,namespace=”/user” actionname=”user” Action所執行的方法method=”add”並且傳入了一個參數name=a.如下:

<package name="user" extends="struts-default" namespace="/user">

        <action name="user" class="com.bjsxt.struts2.user.action.UserAction">

            <result>/user_add_success.jsp</result>

            <result name="error">/user_add_error.jsp</result>

        </action>

</package>

根據配置文件可以得知action所對應的類爲com.bjsxt.struts2.user.action.UserAction,並且具有兩個結果集(successerror).代碼如下:

import com.opensymphony.xwork2.ActionSupport;

public class UserAction extends ActionSupport {

    private String name;

    public String add() {

       if(name == null || !name.equals("admin")) {

           //addFieldError 添加錯誤信息,可以在客戶端訪問到。

           this.addFieldError("name", "name is error");

           this.addFieldError("name", "name is too long");

           return ERROR;

       }

       return SUCCESS;

    }

    public String getName() {

       return name;

    }

    public void setName(String name) {

       this.name = name;

    }

}

     根據Action類代碼,可以看到Action是利用Action的成員屬性(name)來接受參數值,並且使用this.addFieldError()方法添加錯誤信息,以便前臺可以訪問到。

this.addFieldError(name, errorMessage);

注:此方法是使用繼承了ActionSupport父類的

   name:可以是傻的屬性名稱,但一般建議使用哪個成員屬性出題了,就用那個。當前是因爲name沒有通過驗證,所以使用name

   errorMessage:添加的信息

 

在客戶端獲取這些信息,如下:

<body>

    User Add Error!

    <s:fielderror fieldName="name" theme="simple"/>

    <br />

    <s:property value="errors.name"/>

    <s:debug></s:debug>

</body>

注:使用<s:fielderror>標題,需要使用<%@taglib>命令引用Struts2的標籤庫如下:

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

1<s:fielderror>標籤:獲取使用addFieldError()方法添加的信息。

                   FiledName:指定信息的名稱。

                   Theme: 指定顯示的主題。

    注:使用此標籤獲取的錯誤信息,Struts強制添加了css的修飾。生成的HTML代碼如下(不長用)

<ul class="errorMessage">

               <li><span>name is error</span></li>

               <li><span>name is too long</span></li>

     </ul>

Class=”errorMessage”Struts2已經設置好的一個css了。這個方式不方便我們自定義樣式。

 

 

2<s:debug></s:debug>:這是標籤的寫方式,會在頁面上產生一個鏈接,點擊後顯示如下(Struts2生成的一些信息)

3<s:property>標籤:獲取值堆棧屬性所對應的值。

<s:property value="errors.name"/>

   注:value:指定值堆棧的屬性名及數據下標等。

     例如:value=”a” 獲取Action類的成員屬性a的值

         Value=”errors” 獲取errors屬性的對象Map

         Value=”errors.name”獲取errors屬性的對象Mapkeynamevalue

         Value=”errors.name[0] 獲取errors屬性的對象Mapkeynamevalue的第一個元素的值。

注:如果獲取Action Context中的Key值,需要在前面加#(井號)

     例如:<s:property value=”#request”/>

十二、     訪問Web元素

取得Map類型request,session,application,真實類型 HttpServletRequest, HttpSession, ServletContext的引用:

1.   前三者:依賴於容器

2.   前三者:IOC (只用這種)

3.   後三者:依賴於容器

4.   後三者:IOC

一、方法一:ActionContext方式

一般在Action類的構造方法、或execute()方法中獲取。

public class LoginAction1 extends ActionSupport {

   

    private Map request;

    private Map session;

    private Map application;

   

    public LoginAction1() {

       request = (Map)ActionContext.getContext().get("request");

       session = ActionContext.getContext().getSession();

       application = ActionContext.getContext().getApplication();

    }

   

    public String execute() {

       request.put("r1", "r1");

       session.put("s1", "s1");

       application.put("a1", "a1");

       return SUCCESS;

    }

}

然後在Jsp頁面中獲取相關web元素。

<body>

    User Login Success!

    <br />

    <s:property value="#request.r1"/> | <%=request.getAttribute("r1") %> <br />

    <s:property value="#session.s1"/> | <%=session.getAttribute("s1") %> <br />

    <s:property value="#application.a1"/> | <%=application.getAttribute("a1") %> <br />

    <s:property value="#attr.a1"/><br />

    <s:property value="#attr.s1"/><br />

    <s:property value="#attr.r1"/><br />

    <s:debug></s:debug>

    <br />

</body>

注:因爲requestsessionapplication對象Struts2將在放入到Action Context中,

    因此需要使用#key來訪問對象們。

後面的是java腳本代碼的訪問方式。

二、方式二:Ioc(控制反轉)—推薦使用

Action類實現RequestAwareSessionAwareApplicationAware接口,然後重寫他們的set方法(setRequestsetSessionsetApplication),通過依賴注入、控制反轉(原來自己控制,現在由別人來控制值。)

import org.apache.struts2.interceptor.ApplicationAware;

import org.apache.struts2.interceptor.RequestAware;

import org.apache.struts2.interceptor.SessionAware;

import com.opensymphony.xwork2.ActionSupport;

public class LoginAction2 extends ActionSupport implements RequestAware,SessionAware, ApplicationAware {

    private Map<String, Object> request;

    private Map<String, Object> session;

    private Map<String, Object> application;

   

    //DI dependency injection依賴注入

    //IoC inverse of control控制反轉

    public String execute() {

       request.put("r1", "r1");

       session.put("s1", "s1");

       application.put("a1", "a1");

       return SUCCESS;

    }

    @Override

    public void setRequest(Map<String, Object> request) {

       this.request = request;

    }

    @Override

    public void setSession(Map<String, Object> session) {

       this.session = session;

    }

    @Override

    public void setApplication(Map<String, Object> application) {

       this.application = application;

    }

}

在視圖(JSP)頁面中獲取相關對象,同方式一。

三、方式三:獲取原類型

獲取是的HttpServletRequest/HttpSession/ServletContext

public class LoginAction3 extends ActionSupport {

   

    private HttpServletRequest request;

    private HttpSession session;

    private ServletContext application;

    public LoginAction3() {

       request = ServletActionContext.getRequest();

       session = request.getSession();

       application = session.getServletContext();

    }

    public String execute() {

       request.setAttribute("r1", "r1");

       session.setAttribute("s1", "s1");

       application.setAttribute("a1", "a1");

       return SUCCESS;

    }

}

 

四、方式四:獲取原類型-控制反轉

首先需要Action實現org.apache.struts2.interceptor.ServletRequestAware接口,然後重寫setServletRequest()方法,獲取HttpServletRequest對象,再通過HttpServletRequest對象取昨HttpSessionServletContext對象。

 

import javax.servlet.ServletContext;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpSession;

 

import org.apache.struts2.interceptor.ServletRequestAware;

import com.opensymphony.xwork2.ActionSupport;

public class LoginAction4 extends ActionSupport implements ServletRequestAware {

    private HttpServletRequest request;

    private HttpSession session;

    private ServletContext application;

    public String execute() {

       request.setAttribute("r1", "r1");

       session.setAttribute("s1", "s1");

       application.setAttribute("a1", "a1");

       return SUCCESS;

    }

    @Override

    public void setServletRequest(HttpServletRequest request) {

       this.request = request;

       this.session = request.getSession();

       this.application = session.getServletContext();

    }

}

 

十三、     Struts2配置文件模塊化包含(include)

<include>標籤

Struts配置文件比較多,需要模塊化劃分或分開成爲多個配置文件時,這個功能比較好。

    則需要使用<include>標籤把其它的配置文件引入到Struts.xml配置文件中就可以了。

    例如:有一個login.xml配置文件如下:

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

<!DOCTYPE struts PUBLIC

    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"

    "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>

    <package name="login" extends="struts-default" namespace="/login">

        <action name="login*" class="com.bjsxt.struts2.user.action.LoginAction{1}">

            <result>/user_login_success.jsp</result>

        </action>

    </package>

</struts>

則需要在struts.xml文件中使用<include>標籤將其引入就可以了。Struts.xml如下

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

<!DOCTYPE struts PUBLIC

    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"

    "http://struts.apache.org/dtds/struts-2.0.dtd">

 

<struts>

    <constant name="struts.devMode" value="true" />

    <include file="login.xml" />

</struts>

 

十四、     默認的Action

當用戶訪問的namespace下一個不存在的Action,則會將使用默認的Action

使用<default-action-ref name=”name”>標籤 其中 name屬性指向下面已經定義的Action名稱了。

<struts>

    <constant name="struts.devMode" value="true" />

   

    <package name="default" namespace="/" extends="struts-default">

    <default-action-ref name="index"></default-action-ref>

    <action name="index">

        <result>/default.jsp</result>

    </action>

    </package>

</struts>

當前訪問namespace=”/”下不存在的Action時,則返回自動轉到訪問/default.jsp頁面。

 

十五、     Action總結

1、 實現一個Action的最常用的方式:從ActionSupport繼承

2、 DMI動態方式的調用:!

3、 通配符配置:* {1} {2}

4、 接收參數的方式(一般屬性或DomainModel來接收)

5、 簡單參數驗證addFieldError

a)   一般不使用StrutsUI標籤

6、 訪問Web元素

a)   Map類型

              i.      IoC

             ii.      依賴Struts2

b)   原始類型

              i.      IoC

             ii.      依賴Struts2

7、 包含文件配置


02 Struts2-Result

一、Result類型 (type)

1、 dispatcher

運用服務器跳轉 jsp forward

不可以是Action,只可以跳轉到視圖

2、 redirect

客戶端跳轉(重定向)-url發生變化

不可以是Action,只可以跳轉到視圖

3、 chain

跳轉到Action (forward action)

可以動用到Action

在訪問Action,Action前面不要加”/”

4、 redirectAction

客戶端跳轉到Action――-url發生變化

5、 freemarker

6、 httpheader

發送一個http

7、 stream

下載

8、 velocity

9、 xslt

10、   plaintext

返回頁面的源碼

11、   titles

把頁面分成幾塊,每個頁面都可以動態的指定

<struts>

    <constant name="struts.devMode" value="true" />

    <package name="resultTypes" namespace="/r" extends="struts-default">

        <action name="r1">

        <result type="dispatcher">/r1.jsp</result>

        </action>

       

        <action name="r2">

        <result type="redirect">/r2.jsp</result>

        </action>

       

        <action name="r3">

        <result type="chain">r1</result>

        </action>

       

        <action name="r4">

        <result type="redirectAction">r2</result>

        </action>

       

    </package>

</struts>

 

注:當訪問不同的namespace下的Action時,則使用如下方式:

<result type="chain">

            <param name="actionName">dashboard</param>//Action名稱

            <param name="namespace">/secure</param>//namespace

</result>

 

二、全局結果集(Globle Result)

當有多個Action使用同一個結果集時,則可以使用全局結果集(Globle Result),如下:

<package name="user" namespace="/user" extends="struts-default">  

    <global-results>

        <result name="mainpage">/main.jsp</result>

    </global-results>   

    <action name="index">

        <result>/index.jsp</result>

    </action>     

<action name="user" class="com.bjsxt.struts2.user.action.UserAction">

        <result>/user_success.jsp</result>

        <result name="error">/user_error.jsp</result>

 </action>      

</package>

Action所對應的Action類如下:

UserAction

public class UserAction extends ActionSupport {

    private int type;

    public int getType() {

       return type;

    }

    public void setType(int type) {

       this.type = type;

    }

    @Override

    public String execute() throws Exception {

       if(type == 1) return "success";

       else if (type == 2) return "error";

       else return "mainpage";

    }

}

UserAction返回的結果集中有”mainpage”,但是userAction中並沒有”mainpage”Rsult,這時就會使用全局的結果庥(global-result),這人結果集中有”mainpage”

    當其它不同的package需要使用這個全局的Result時,則需要使用<package>標籤中的extends屬性來指定繼承包含全局的package就可以了。如下:

<package name="admin" namespace="/admin" extends="user">

    <action name="admin" class="com.bjsxt.struts2.user.action.AdminAction">

        <result>/admin.jsp</result>

    </action>

</package>

這時package=”user”中的結果集就可以被package=”admin”中的Action使用了。

 

三、動態的結果集(dynamic result)

<struts>

    <constant name="struts.devMode" value="true" />

    <package name="user" namespace="/user" extends="struts-default">

     

      <action name="user" class="com.bjsxt.struts2.user.action.UserAction">

      <result>${r}</result>

      </action>     

    </package>

</struts>

注:${}:作用是用於在配置文件中從Value stack(值棧)中取值。

    例如:${r} 表示從Value stack(值棧)中取rAction(成員屬性)的值。注意這個成員屬性必需具有

注:此處的${}不是el表達式。

get/set方法。

    Action類中指定了r的值。這樣就動態確定了Result的值

public class UserAction extends ActionSupport {

    private int type;

    private String r;

    public String getR() {

       return r;

    }

    public void setR(String r) {

       this.r = r;

    }

    public int getType() {

       return type;

    }

    public void setType(int type) {

       this.type = type;

    }

    @Override

    public String execute() throws Exception {

       if(type == 1) r="/user_success.jsp";

       else if (type == 2) r="/user_error.jsp";

       return "success";

    }

}

四、帶參數的結果集

也就是向結果集傳參數

    服務器forward共享一個值棧(Value stack)

    客戶端跳轉則不共享

例如:

<package name="user" namespace="/user" extends="struts-default">

   

        <action name="user" class="com.bjsxt.struts2.user.action.UserAction">

        <result type="redirect">/user_success.jsp?t=${type}</result>

        </action>     

    </package>

UserAction類:

public class UserAction extends ActionSupport {

    private int type;

    public int getType() {

       return type;

    }

    public void setType(int type) {

       this.type = type;

    }

    @Override

    public String execute() throws Exception {

       return "success";

    }

}

因爲當執行Action後,已經將Action的成員屬性寫入了值堆棧了,因此可以在配置文件中使用${type}取出type的值。

但是隻有Action才具有值堆棧的。Jsp是沒有什麼值堆棧的。因爲當result重新定向到/user_success.jsp?t=${type}後,是不能從值堆棧中取出t的值。但是有ActionContext的,所以可以從中取出t的值。JSP代碼如下:

<body>

    User Success!

    from valuestack: <s:property value="t"/><br/>

    from actioncontext: <s:property value="#parameters.t"/>

    <s:debug></s:debug>

</body>

注:<s:property value="t"/>取不到值,因爲jsp不是一個Action沒有值堆棧。

<s:property value="#parameters.t"/>可以取出t的值,因爲#方式是從ActionContext中取屬性值。

    ActionContext堆棧中具有parameters這個屬性是用於存儲傳入的參數。所以可以取出。

五、Result總結

1、 常用的四種類型

a)   dispatcher(默認)

b)   redirect

c)   chain

d)   redirectAction

2、 全局結果集

a)   Global-result | extends

3、 動態結果集(瞭解)

a)   Action中保存一個屬性,存儲具體的結果location

4、 傳遞參數

a)   客戶端跳轉才需要傳遞

b)   ${}表達式(不是el表達式)

六、項目經理:

1、  界面原型

2、  設計數據庫

3、  使用什麼框架構

4、  設計約定(硬編碼) ***

項目名稱、數據庫名稱、配置文件名稱、ActionJSP……

   

03 OGNL表達式語言

     Object Graph Navigation Language 對象圖導航語言

     <s:property value=””> 注意:  value裏的內容稱爲ognl表達式

     User.xxx 只有傳入參數,纔會構造對象,或者直接在actionnew也可以,但是User對象必需具有無參數的構造方法。

     {}大括號 在OGNL中可以表示一個集合

 

    OGNL表達式語言訪問靜態方法,需要在Struts2.xml配置文件如下:

      <constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>

 

使用一個實例如說明OGNL表達式語言,如下:

Cat

package com.wjt276.struts2.ognl;

public class Cat {

  private Dog friend; 

  public Dog getFriend() {

     return friend;

  }

  public void setFriend(Dog friend) {

     this.friend = friend;

  }

  public String miaomiao() {

     return "miaomiao";

  }

}

Dog

package com. wjt276.struts2.ognl;

public class Dog {

  private String name;

  public Dog() {    }

  public Dog(String name) {

     super();

     this.name = name;

  }  

  public String getName() {

     return name;

  }

  public void setName(String name) {

     this.name = name;

  }

  @Override

  public String toString() {

     return "dog: " + name;

  }

}

S

package com. wjt276.struts2.ognl;

public class S {

  public static String STR = "STATIC STRING";  

  public static String s() {

     return "static method";  }}

 

User

package com. wjt276.struts2.ognl;

public class User {

  private int age = 8;

  public User() {} 

  public User(int age) {

     super();

     this.age = age;

  }

  public int getAge() {

     return age;

  }

  public void setAge(int age) {

     this.age = age;

  }  

  @Override

  public String toString() {

     return "user" + age;

  }

}

 

OgnlAction

package com. wjt276.struts2.ognl;

public class OgnlAction extends ActionSupport {

  private Cat cat;

  private Map<String, Dog> dogMap = new HashMap<String, Dog>();

  private Set<Dog> dogs = new HashSet<Dog>();

  private String password;

  private User user;

  private String username;

  private List<User> users = new ArrayList<User>();

 

  public OgnlAction() {

     users.add(new User(1));

     users.add(new User(2));

     users.add(new User(3));

 

     dogs.add(new Dog("dog1"));

     dogs.add(new Dog("dog2"));

     dogs.add(new Dog("dog3"));

    

     dogMap.put("dog100", new Dog("dog100"));

     dogMap.put("dog101", new Dog("dog101"));

     dogMap.put("dog102", new Dog("dog102"));     

  }

  public String execute() {

     return SUCCESS;

  }

  public Cat getCat() {

     return cat;

  }  

  public Map<String, Dog> getDogMap() {

     return dogMap;

  }

  public Set<Dog> getDogs() {

     return dogs;

  }  

  public String getPassword() {

     return password;

  }  

  public User getUser() {

     return user;

  }

  public String getUsername() {

     return username;

  }

  public List<User> getUsers() {

     return users;

  }

  public String m() {

     return "hello";

  }

  public void setCat(Cat cat) {

     this.cat = cat;

  }  

  public void setDogMap(Map<String, Dog> dogMap) {

     this.dogMap = dogMap;

  }

  public void setDogs(Set<Dog> dogs) {

     this.dogs = dogs;

  }

  public void setPassword(String password) {

     this.password = password;

  }

  public void setUser(User user) {

     this.user = user;

  }

  public void setUsername(String username) {

     this.username = username;

  }

  public void setUsers(List<User> users) {

     this.users = users;

  }

}

Struts2.xml配置文件:

<struts>

    <constant name="struts.enable.DynamicMethodInvocation" value="false" />

    <constant name="struts.devMode" value="true" />

    <!-- 允許ognl訪問靜態方法 -->

    <constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>

  <include file="/com/wjt276/struts2/ognl/ognl.xml"/>

</struts>

Com.wjt276.struts2.ognl.ognl.xml配置文件

    <package name="ognl" extends="struts-default">

        <action name="ognl" class="com.wjt276.struts2.ognl.OgnlAction">

            <result>/ognl.jsp</result>

        </action>

    </package>

客戶端請求的URL地址:

     分析:此請求是訪問actionname=”ognl.action”namespace=”/” 並傳入了幾個參數(前兩個由Action的成員屬性接受,後一個由Action的成員對象屬性user接受。),根據Struts2配置文件得知此請求轉到/ognl.jsp頁面。如下:

<ol>

       <li>訪問值棧中的action的普通屬性: username = <s:property value="username"/> </li>

       <li>訪問值棧中對象的普通屬性(get set方法)<s:property value="user.age"/> | <s:property value="user['age']"/> | <s:property value="user[/"age/"]"/> | wrong: <%--<s:property value="user[age]"/>--%></li>

       <li>訪問值棧中對象中的成員對象的普通屬性(get set方法): <s:property value="cat.friend.name"/></li>

       <li>訪問值棧中對象的普通方法:<s:property value="password.length()"/></li>

       <li>訪問值棧中對象的普通方法:<s:property value="cat.miaomiao()" /></li>

       <li>訪問值棧中action的普通方法:<s:property value="m()" /></li>

       <hr />

       <li>訪問靜態方法:<s:property value="@com.wjt276.struts2.ognl.S@s()"/></li>

       <li>訪問靜態屬性:<s:property value="@com.wjt276.struts2.ognl.S@STR"/></li>

       <li>訪問Math的靜態方法:<s:property value="@@max(2,3)" /></li>

       <hr />

       <li>訪問普通類的構造方法:<s:property value="new com.bjsxt.struts2.ognl.User(8)"/></li><%--返回對象的toString()生成的數據--%>

       <hr />

       <li>訪問List:<s:property value="users"/></li>

       <li>訪問List中某個元素:<s:property value="users[1]"/></li>

       <li>訪問List中元素某個屬性的集合:<s:property value="users.{age}"/></li>

       <li>訪問List中元素某個屬性的集合中的特定值:<s:property value="users.{age}[0]"/> | <s:property value="users[0].age"/></li>

       <li>訪問Set:<s:property value="dogs"/></li>

       <li>訪問Set中某個元素:<s:property value="dogs[1]"/></li>

       <li>訪問Map:<s:property value="dogMap"/></li>

       <li>訪問Map中某個元素:<s:property value="dogMap.dog101"/> | <s:property value="dogMap['dog101']"/> | <s:property value="dogMap[/"dog101/"]"/></li>

       <li>訪問Map中所有的key:<s:property value="dogMap.keys"/></li>

       <li>訪問Map中所有的value:<s:property value="dogMap.values"/></li>

       <li>訪問容器的大小:<s:property value="dogMap.size()"/> | <s:property value="users.size"/> </li>

       <hr />

       <li>投影(過濾)<s:property value="users.{?#this.age==1}[0]"/></li>

       <li>投影:<s:property value="users.{^#this.age>1}.{age}"/></li><%--頭一個 --%>

       <li>投影:<s:property value="users.{$#this.age>1}.{age}"/></li><%--最後一個--%>

       <li>投影:<s:property value="users.{$#this.age>1}.{age} == null"/></li>

        <hr />

       <li>[]:<s:property value="[0].username"/></li><%--值堆棧中的對象(Object),從上開始的第0個至堆棧底對象 --%>     

    </ol>

    <s:debug></s:debug>

訪問後服務器返回給客戶端的結果:

1.        訪問值棧中的action的普通屬性: username = u

2.        訪問值棧中對象的普通屬性(get set方法)9 | 9 | 9 | wrong:

3.        訪問值棧中對象的普通屬性(get set方法):

4.        訪問值棧中對象的普通方法:1

5.        訪問值棧中對象的普通方法:

6.        訪問值棧中action的普通方法:hello


7.        訪問靜態方法:static method

8.        訪問靜態屬性:STATIC STRING

9.        訪問Math類的靜態方法:3


10.     訪問普通類的構造方法:user8


11.     訪問List:[user1, user2, user3]

12.     訪問List中某個元素:user2

13.     訪問List中元素某個屬性的集合:[1, 2, 3]

14.     訪問List中元素某個屬性的集合中的特定值:1 | 1

15.     訪問Set:[dog: dog1, dog: dog2, dog: dog3]

16.     訪問Set中某個元素: <!—沒有顯示是因爲在Set中沒有排序就不存在的用下標訪問了-->

17.     訪問Map:{dog102=dog: dog102, dog101=dog: dog101, dog100=dog: dog100}

18.     訪問Map中某個元素:dog: dog101 | dog: dog101 | dog: dog101

19.     訪問Map中所有的key:[dog102, dog101, dog100]

20.     訪問Map中所有的value:[dog: dog102, dog: dog101, dog: dog100]

21.     訪問容器的大小:3 | 3


22.     投影(過濾)user1

23.     投影:[2]

24.     投影:[3]

25.     投影:false


26.     []:u

27.     [Debug]

04 Struts2-Tags

Struts2標籤目錄

1、  通用標籤

a)    Property

b)    Set

              i.      默認爲action scope,會將值放入requestActionContext

             ii.      page/request/session/application

c)    bean

d)    include對中文文件支持的問題,不建議使用,如需要包含,改用jsp包含

e)    param

f)    debug

2、  控制標籤

a)    If elseif else

b)    Iterator

              i.      collections map enumerateon iterator array

c)    subset

3、  UI標籤

a)    Theme

              i.      Simple xhtml(默認) css_xhtml ajax

4、  AJAX標籤

a)    補充

5、  $ # % 的區別

a)    $ 用於i18nStruts配置文件

b)    # 取得ActionContext的值

c)    % 將原本的文本屬性解析爲ognl,對於本來就是ognl的屬性不起作用

              i.      參考<s:property><s:include>

 

一、 property標籤

格式:<s:property value=””default=”” escape=”true|false”/>

     如果value中的內容爲object,則Struts2都會把它解析成ognl表達式

     如果裏面需要表示爲字符串,則需要將內容用單引號括起來

1、  利用ognl表達式取值(例如:取值堆棧中的username)

<s:property value="username"/>

2、  取值爲字符串

需要將內容用單引號括起來

<s:property value="’username’"/>

3、  設置默認值-default

如果一個對象值取不到,則可以使用default設置一個默認值。

<s:property value="admin" default=”管理員/>

4、  設定HTML-escape

是否設置返回值爲HTML原代碼樣式

true:解析返回值的html代碼 false:原封不動返回值

<s:property value="'<hr/>'" escape="false"/>

 

 

 

 

二、 set標籤

注:var 用於設定變量名

     value 變量值(可以是ognl表達式)也可以是字符串

         scope 就是的作用範圍 request session page application action(默認)

 

<li>set 設定adminName值(默認爲request ActionContext: <s:set var="adminName" value="username" /></li>

      

<li>set request取值: <s:property value="#request.adminName" /></li>

<li>set ActionContext取值: <s:property value="#adminName" /></li>

      

<%--<li>set 設定範圍: <s:set name="adminPassword" value="password" scope="page"/></li>

<li>set 從相應範圍取值: <%=pageContext.getAttribute("adminPassword") %></li>

       --%>

<li>set 設定var,範圍爲ActionContext: <s:set var="adminPassword" value="password" scope="session"/></li>

<li>set 使用#取值: <s:property value="#adminPassword"/> </li>

<li>set 從相應範圍取值: <s:property value="#session.adminPassword"/> </li>

 

三、 bean標籤

    定義bean,並使用param來設定新的屬性值

     <s:bean name="com.bjsxt.struts2.tags.Dog" >

              <s:param name="name" value="'pp'"></s:param>

    </s:bean>

定義bean,並使用一個變量(var)來接受創建的這個bean,取出值來

<s:bean name="com.bjsxt.struts2.tags.Dog" var="myDog">

               <s:param name="name" value="'oudy'"></s:param>

</s:bean>

拿出值:因爲在actionContext中,所以使用#

<s:property value="#myDog.name"/>

 

<s:bean>不指定var時,則對象相關屬性會在值棧中。如果需要訪問,則只能在<s:bean>標籤內訪問。

<s:bean>標籤結束後,則值棧就不存在這個對象了。

     <s:bean name="com.bjsxt.struts2.tags.Dog" >

              <s:param name="name" value="'pp'"></s:param>

              <s:property value="name"/>

    </s:bean>

 

四、 <include>標籤-少使用

包含文件

<li>include _include1.html 包含靜態英文文件

       <s:include value="/_include1.html"></s:include>

       </li>

      

       <li>include _include2.html 包含靜態中文文件

       <s:include value="/_include2.html"></s:include>

       </li>

      

       <li>include _include1.html 包含靜態英文文件,說明%用法

       <s:set var="incPage" value="%{'/_include1.html'}" />

       <s:include value="%{#incPage}"></s:include>

    </li>

%{xxx} 強制將xxx內容轉換成OGNL表達式

<-- One: -->
<s:include value="myJsp.jsp" />
<-- Two: -->
<s:include value="myJsp.jsp">
   <s:param name="param1" value="value2" />
   <s:param name="param2" value="value2" />
</s:include>
<-- Three: -->
<s:include value="myJsp.jsp">
   <s:param name="param1">value1</s:param>
   <s:param name="param2">value2</s:param>
</s:include>

五、 If elseif else

<li>if elseif else:

       age = <s:property value="#parameters.age[0]" /> <br />

       <s:set var="age" value="#parameters.age[0]" />

       <s:if test="#age < 0">wrong age!</s:if>

       <s:elseif test="#parameters.age[0] < 20">too young!</s:elseif>

       <s:else>yeah!</s:else><br />

      

       <s:if test="#parameters.aaa == null">null</s:if>

</li>

 

<s:if test="%{false}">
    <div>Will Not Be Executed</div>
</s:if>
<s:elseif test="%{true}">
    <div>Will Be Executed</div>
</s:elseif>
<s:else>
    <div>Will Not Be Executed</div>

</s:else>

 

 

 

 

六、 Iterator標籤

<li>遍歷集合:<br />

       <s:iterator value="{1, 2, 3}" >

           <s:property/> |      <!—不需要寫其它的,就可以輸出數組內的值-->

       </s:iterator>

       </li>

       <li>自定義變量:<br />

       <s:iterator value="{'aaa', 'bbb', 'ccc'}" var="x">

           <s:property value="#x.toUpperCase()"/> |

       </s:iterator>

       </li>

       <li>使用status:<br />

       <s:iterator value="{'aaa', 'bbb', 'ccc'}" status="status">

           <s:property/> |

           遍歷過的元素總數:<s:property value="#status.count"/> |

           遍歷過的元素索引:<s:property value="#status.index"/> |

           當前是偶數?:<s:property value="#status.even"/> |

           當前是奇數?:<s:property value="#status.odd"/> |

           是第一個元素嗎?:<s:property value="#status.first"/> |

           是最後一個元素嗎?:<s:property value="#status.last"/>

           <br />

       </s:iterator>

      

       </li>

      

       <li>

       <s:iterator value="#{1:'a', 2:'b', 3:'c'}" >

           <s:property value="key"/> | <s:property value="value"/> <br />

       </s:iterator>

       </li>

      

       <li>

       <s:iterator value="#{1:'a', 2:'b', 3:'c'}" var="x">

           <s:property value="#x.key"/> | <s:property value="#x.value"/> <br />

       </s:iterator>

       </li>

 

七、 Theme

1、  css(覆蓋Struts2原來的css)

2、  覆蓋單個文件

3、  定義自己的theme

4、  實戰

a)    把所有主題定義爲simple

b)    Fielderror特殊處理

c)    自己控制其他標籤的展現

 

 

05設計約定(編碼規定)

1、  原則:簡單就是美

2、  庫名:項目名

3、  表的命名:t_model

4、  字段:保持和屬性名一致(儘量不要起和數據庫命名衝突)

5、  用層來劃分包

com.wjt276.bbs.action model(bean) service dto(vo)

6、  Action xxxAction

7、  *.*

8、  前臺: /

9、  後臺: /admin

10、Package: “action” adminAction

 

06 項目開發順序

1、  建立界面原型

2、  建立Struts.xml

a)    確定namespace

b)    確定packge

c)    確定Action的名稱

d)    確定Result

e)    將界面原型頁面進行修改,匹配現有設置

f)    測試

3、  建立數據庫(或實體類)

4、  建立Model

5、  建立Service(後面講hibernate後再完美)

a)    此時可以使用Junit進行單元測試了

6、  着手開發

 


07 聲明式異常處理

     注:Struts2支持聲明式異常處理。

    Struts2是通過攔截器(interceptor)來處理聲明式異常處理。

     要求在DAOServiceAction層都需要拋出導演就可以了。其它的讓Struts2來處理。詳細過程如下:

實例:

如果在列表時出現錯誤,則方法如下:

public List<Category> list() throws SQLException{

     Connection conn = DB.createConn();

     String sql = "select * from _category";

     List<Category> categories = new ArrayList<Category>();

     PreparedStatement ps = DB.prepare(conn, sql);

     ResultSet rs = null;

     try {

         rs = ps.executeQuery();

         Category c = null;

         while(rs.next()){

            c = new Category();

            …………

         }

     } catch (SQLException e) {

         e.printStackTrace();

         throw(e);//此處向外拋出異常,讓調用它的方法知道

     } finally{

         DB.close(rs);

         DB.close(ps);

         DB.close(conn);

        

     }

     return categories;

}

然後在調用它的Action也向上拋出異常

public String list() throws SQLException{

     categories = categoryService.list();

     return SUCCESS;

}

注意重點:我們需要在Struts.xml配置文件中配置需要處理的異常就可以了。

<action name="*-*" class="com.wjt276.bbs2009.action.{1}Action" method="{2}">

           <result>/admin/{1}-{2}.jsp</result>

           <result name="input">/admin/{1}-{2}.jsp</result>

<!--   <exception-mapping>標籤是映射異常處理。表示映射哪種異常,此處是java.lang.Exception  如果出現異常,那麼它會跳轉到reslut="error"的結果集,也就是/error.jsp        -->

           <exception-mapping result="error" exception="java.lang.Exception"/>

           <result name="error">/error.jsp</result>

</action>

當然,我們也可以將所有的異常使用同一個異常映射,那就是<global-exception-mappings>需要映射的packge只需要繼承此package就可以了。如下:

 

<package name="bbs2009-deafult" extends="struts-default">

       <global-results>

           <result name="error">/error.jsp</result>

       </global-results>

      

       <global-exception-mappings>

           <exception-mapping result="error" exception="java.lang.Exception"/>

       </global-exception-mappings>

    </package>

 

    <!-- 後臺Action的配置區 -->

    <package name="admin" namespace="/admin" extends="bbs2009-default">

       <default-action-ref name="index"></default-action-ref>

       <action name="index">

           <result>index.html</result>

       </action>

       <action name="*-*" class="com.wjt276.bbs2009.action.{1}Action" method="{2}">

           <result>/admin/{1}-{2}.jsp</result>

           <result name="input">/admin/{1}-{2}.jsp</result>

           <result name="error">/error.jsp</result>

       </action>

    </package>

注意:如果使用全局異常映射(<global-exception-mappings>)和全局結果集(<global-results>)則需要全局結果集(<global-results>)在前。

    如果局部(當前)Action、和全局結果集存在相同的<result>,則使用最近的那個結果。

總結:

1、  Action中進行異常映射

2、  package中進行全局異常映射

3、  使用繼承共用異常映射

4、  Struts2中異常處理由攔截器實現(觀察struts-default.xml)

a)    實際上Struts2的大多數功能都由攔截器實現。

 

 


08 國際化

一、  國際化資源文件

     命名格式:xxx_語言_國家.properties

     例如:app_en_US.properties  表示美國 英語

          app_zh_CN.properties  表示中國 漢語

     資源文件的編碼是使用UTF-8的編碼,這樣中文也必需是UTF-8的格式,則需要將中文轉換成UTF-8的,你可以使用propertiesEditor插件來進行輸入中文。

 

app_en_US.properties文件內容

welcome.msg=hello world!

app_zh_CN.properties

welcome.msg=歡迎您!

二、  Java國際化

     要求:資源文件要求存放在classpath的根目錄下(src)

     然後再建立一個Java類和一個main方法如下:這樣就可以進行國際化處理了。

     public static void main(String[] args) {

        ResourceBundle res = ResourceBundle.getBundle("app",Locale.CHINA);

        System.out.println(res.getString("welcome.msg"));

    }

注:java.util.ResourceBundle是加載國際化資源文件的類。利用此類的getBundle()方法加載classpath下的指定開頭的文件名的國際化資源文件。並且在加載時需要指定加載哪個國家的國際人資源文件。

     此實例中的ResourceBundle.getBundle("app",Locale.CHINA);表示加載以"app"開頭的國際化資源文件,並且是中國的(對應的zh_CN)的。

     一但國際化資源文件加載上來後,就可以使用ResourceBundle類的getSring("welcome.msg")方法獲取當前內容。

三、 Struts2國際化

Struts2國際化分爲:Action級別、package級別、Application級別

1、  Action級別

條件:要求國際化資源文件名的前綴同相應的Action名,並且國際化資源文件需要與相應的Action在同一個包中

例如:我們需要國際化登錄頁面。如下

原始代碼<body>

     Login_input <br>

    <form action="admin/Login_login">

    username:<input name="username" type="text"/><br/>

    password:<input name="password" type="password"/>

    <input type="submit" value="login">

    </form> </body>

這裏需要對"Login_input""username""password""login"進行國際化。因爲登錄頁面的請求URL

根據Struts2.xml的配置文件可知對應的ActionLoginAction.java.因爲國際化資源文件名應是LoginAction_開頭(此處爲LoginAction_zh_CN.propertiesLoginAction_en_US.properties)如下

注意:要求國際化資源文件需要與相應的Action在同一包中(見上第三個圖),這樣Struts2就可以保證當訪問這個LoginAction時國際化資源文件會自動加載。我們在相應的文件中可以直接訪問(利用ActionSupport類中的getText()方法。)了。

我們現在只需要將登錄頁面代碼修改就可以了。

 

  <body>

     <s:property value="getText('login.title')"/><br>

    <form action="admin/Login-login" method="post">

    <s:property value="getText('login.username')"/><input name="username" type="text"/><br/>

    <s:property value="getText('login.password')"/><input name="password" type="password"/>

    <input type="submit" value="<s:property value='getText("login.login")'/>">

    </form>

    <s:debug></s:debug>

  </body>

注意:Struts2國際化是使用<s:property value=”getText()”/>來獲取信息的。

格式:

<s:property value="getText('login.title',defaultValue)"/>

    其中:getText()ActionSuppot類中的方法。因爲<s:property>標籤只可以直接使用Action的方法。方法中的參數一:表示國際化資源文件中的標籤,因爲要求是字符串,所以使用單引號括起來。

    參數二:當沒有取出數據時,則使用這個默認的值,可以省略此參數。

 

     總結:國際化資源文件建立完、使用標籤取值後,其它都將由Struts2來完成。

 

2、 Package級別

Package級別的只是將國際化資源文件建立在package()下,要求資源文件名前綴同包名就可以了。

其它的使用同Action級別的一樣。

例如:如果在com.wjt276.bbs2009.action包下建立國際化資源文件,則文件名必須以package開頭

         package_en_US.properties 及 package_zh_CN.properties

總結:1、包級別的資源文件名,必須以package開頭

         2、包級別的資源文件可以給此包中的所有Action類使用。

3、 Application級別

Application級別也只是資源文件存放的位置不同,相同的所使用的範圍也不一樣。

資源文件要求存放在classpath的根目錄下。

國際化資源文件以任何名稱開頭都可以,只是需要在Struts2.xml配置文件中告訴Struts2資源文件是以什麼開頭的。

例如:現在以項目名爲前綴:bbs2009

      bbs2009_en_US.properties 及 bbs2009_en_US.properties

告訴Struts2資源文件是以什麼開頭的

<constant name="struts.custom.i18n.resources" value="bbs2009"/>

四、 資源文件中的參數處理

場景:如果一個登錄系統,用戶登錄後頁面提示“歡迎您,xxxx,如果是英文:”Welcome,xxx”

     正常應該如下處理:先取職歡迎信息 + 再顯示登錄的用戶名。

<s:property value="getText('welcome.msg')"/><s:property value="username"/>

     注意:但是這要就需要兩個Struts2的標籤來完成這件事。

         資源文件中welcome.msg的值如下:

              welcome.msg=歡迎您,   welcome.msg=Welcome,

     我們還有別外一種方式解決它,只需要一個Struts2標籤,只是加入一個參數,這個標籤是<s:text>。具體方式如下:

首先是資源文件需要修改,如下

 

     注意:需要在資源文件中使用{index}來表示傳入參數是哪一個。這個index是從0開始

 文件中的歡迎您,{0}Welcome,{0}, 如果第一個參數傳入值爲wjt276,那麼頁面將顯示歡迎您,wjt276Welcome,wjt276

其次需要使用<s:text>標籤是獲取信息。如下:

    <s:text name="welcome.msg">

        <s:param value="username"></s:param>

</s:text>

注意:<s:text>標籤中的name中的值不需要單引號括起來,因爲是OGNL表達式,而<s:property>標籤中value=”getText(‘welcome.msg’)”中的值需要用單引號括起來。因爲需要傳一個字符串

五、 國際化-動態語言切換

在某些網站中,會發現頁面中有國家語言的選擇,如:中文、英語、日語等語言供您選擇。

Struts2也可以實現這種動態語言切換的功能,方法非常的簡單。

     方法:只需要傳入一個參數(參數名必需爲request_locale),參數值爲語言_國家”(也就是資源文件的後綴,zh_CNen_US)就可以了。例:如果當前訪問的頁面爲中文並且URL

如果需要切換成英文,則只需要傳入一個參數request_locale=en_US就可以了。URL如下

這樣當前進程的瀏覽器就可以訪問這個網站的所有頁面爲英文,至到這個進程結束,因爲Struts2session中寫入locale

WW_TRANS_I18N_LOCALE=en_US

 

09 自定義攔截器

一般99.9%用不上

 

10 類型轉換

public class MyPointConverter extends DefaultTypeConverter{

 

    @Override

    public Object convertValue(Object value, Class toType) {

       if(toType == Point.class) {

           Point p = new Point();

           String[] strs = (String[])value;

           String[] xy = strs[0].split(",");

           p.x = Integer.parseInt(xy[0]);

           p.y = Integer.parseInt(xy[1]);

           return p;

       }

       if(toType == String.class) {

           return value.toString();

       }

       return super.convertValue(value, toType);

    }

}

public class MyPointConverter extends StrutsTypeConverter{

 

    @Override

    public Object convertFromString(Map context, String[] values, Class toClass) {

      

           Point p = new Point();

           String[] strs = (String[])values;

           String[] xy = strs[0].split(",");

           p.x = Integer.parseInt(xy[0]);

           p.y = Integer.parseInt(xy[1]);

           return p;

      

      

    }

 

    @Override

    public String convertToString(Map context, Object o) {

       // TODO Auto-generated method stub

       return o.toString();

    }

}

 

a)   三種註冊方式:

        i.      局部:XXXAction-conversion.properties

1.   p(屬性名稱) =  converter

       ii.      全局:xwork-conversion.properties

1.   com.xxx.XXX(類名)= converter

     iii.      Annotation

b)   如果遇到非常麻煩的映射轉換

        i.      request.setAttribute();

       ii.      session

 

Struts2總結

1.         Action

a)         namespace(掌握)

b)         path(掌握)

c)         DMI(掌握)

d)         wildcard(掌握)

e)         接收參數(掌握前兩種)

f)          訪問request等(掌握Map IOC方式)

g)         簡單數據驗證(掌握addFieldError<s:fieldError

2.         Result

a)         結果類型(掌握四種,重點兩種)

b)         全局結果(掌握)

c)         動態結果(瞭解)

3.         OGNL表達式(精通)

a)         # % $

4.         Struts標籤

a)         掌握常用的

5.         聲明式異常處理(瞭解)

6.         I18N(瞭解)

7.         CRUD的過程(最重要是設計與規劃)(精通)

8.         Interceptor的原理(掌握)

9.         類型轉換(掌握默認,瞭解自定義)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章