Struts2學習筆記

目錄

Ø  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服務器才生效。

     -->   

<constantname="struts.devMode"value="true"/>

   

    <!--

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

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

     -->

    <packagename="default"namespace="/"extends="struts-default">

       <actionname="hello">

           <result>

                /hello.jsp

           </result>

       </action>

</package>

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

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

4、修改對應的web.xml,建立struts2的filter(參考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來區分。   前臺<packagename="front">後臺<package name="back">

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

五、Action

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

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

<constantname="struts.devMode"value="true"/>

    <packagename="front"extends="struts-default"namespace="/">

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

           <resultname="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()方法就可以了。

importcom.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()方法就可以了。

 

importcom.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=來指定執行哪個方法

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

           <result>/user_add_success.jsp</result>

</action>

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

importcom.opensymphony.xwork2.ActionSupport;

public class UserAction extends ActionSupport {

    public String add() {

        returnSUCCESS;

    }  

}

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

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

方法:action + ! + 方法名

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

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

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

       <result>/user_add_success.jsp</result>

</action>

Action類:

public class UserAction extends ActionSupport {

    public Stringadd() {

        returnSUCCESS;

    }  

}

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

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

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

1、  通配符

星號(*)  表示所有

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

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

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

2、  實例

<packagename="actions"extends="struts-default"namespace="/actions">

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

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

       </action>

       

       <actionname="*_*"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}”,表示所有Action以Student開始的都會執行這個Action,並且執行Student後字符爲方法名的方法,例如:訪問的Action爲Studentadd,會執行這個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地址:

其中傳遞了兩個參數:name和age,其值分別爲:a、8,此Action執行的是add()方法。

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

public class UserAction extends ActionSupport {

   

    private Stringname;

    private int age;

   

    public String add() {

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

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

        returnSUCCESS;

    }

    public String getName() {

        returnname;

    }

    public void setName(String name) {

        this.name = name;

    }

    public int getAge() {

        returnage;

    }

    public void setAge(int age) {

        this.age = age;

    }  

}

2、 域模型(Domain Model)

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

例如請求的URL地址:

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

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

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

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

//User對象

public class User {

  private Stringname;

  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 Useruser;

  //private UserDTO userDTO;

  public String add() {

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

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

      return SUCCESS;

  }

 

  public User getUser() {

      returnuser;

  }

  public void setUser(User user) {

      this.user = user;

  }

}

3、 ModelDriven接收參數

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

例如URL如下:

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

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

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

對象模型User:

public class User {

    private Stringname;

    private int age;

    public String getName() {

        returnname;

    }

    public void setName(String name) {

        this.name = name;

    }

    public int getAge() {

        returnage;

    }

    public void setAge(int age) {

        this.age = age;

    }

}

    Action對象

importcom.opensymphony.xwork2.ActionSupport;

importcom.opensymphony.xwork2.ModelDriven;

public class UserAction extends ActionSupportimplements ModelDriven<User>{

  private Useruser = 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>

    <constantname="struts.devMode"value="true"/>

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

    <packagename="user"extends="struts-default"namespace="/user">

       <actionname="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”action的name=”user” Action所執行的方法method=”add”並且傳入了一個參數name=a.如下:

<packagename="user"extends="struts-default"namespace="/user">

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

           <result>/user_add_success.jsp</result>

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

       </action>

</package>

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

importcom.opensymphony.xwork2.ActionSupport;

public class UserAction extends ActionSupport {

    private Stringname;

    public String add() {

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

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

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

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

            returnERROR;

        }

        returnSUCCESS;

    }

    public String getName() {

        returnname;

    }

    public void setName(String name) {

        this.name = name;

    }

}

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

this.addFieldError(name,errorMessage);

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

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

   errorMessage:添加的信息

 

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

<body>

    UserAdd Error!

    <s:fielderrorfieldName="name"theme="simple"/>

    <br/>

    <s:propertyvalue="errors.name"/>

    <s:debug></s:debug>

</body>

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

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

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

                     FiledName:指定信息的名稱。

                     Theme: 指定顯示的主題。

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

<ulclass="errorMessage">

               <li><span>nameis error</span></li>

               <li><span>nameis too long</span></li>

     </ul>

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

 

 

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

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

<s:propertyvalue="errors.name"/>

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

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

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

          Value=”errors.name”獲取errors屬性的對象Map的key爲name的value

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

注:如果獲取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");

        returnSUCCESS;

    }

}

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

<body>

    UserLogin Success!

    <br/>

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

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

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

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

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

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

    <s:debug></s:debug>

    <br/>

</body>

注:因爲request、session、application對象Struts2將在放入到Action Context中,

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

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

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

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

importorg.apache.struts2.interceptor.ApplicationAware;

importorg.apache.struts2.interceptor.RequestAware;

import org.apache.struts2.interceptor.SessionAware;

importcom.opensymphony.xwork2.ActionSupport;

public class LoginAction2 extends ActionSupportimplements 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");

        returnSUCCESS;

    }

    @Override

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

        this.request = request;

    }

    @Override

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

        this.session = session;

    }

    @Override

    public voidsetApplication(Map<String, Object> application) {

        this.application = application;

    }

}

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

三、方式三:獲取原類型

獲取是的HttpServletRequest/HttpSession/ServletContext

public class LoginAction3 extends ActionSupport {

   

    private HttpServletRequestrequest;

    private HttpSessionsession;

    private ServletContextapplication;

    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");

        returnSUCCESS;

    }

}

 

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

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

 

importjavax.servlet.ServletContext;

importjavax.servlet.http.HttpServletRequest;

importjavax.servlet.http.HttpSession;

 

importorg.apache.struts2.interceptor.ServletRequestAware;

importcom.opensymphony.xwork2.ActionSupport;

public class LoginAction4 extends ActionSupportimplements ServletRequestAware {

    private HttpServletRequestrequest;

    private HttpSessionsession;

    private ServletContextapplication;

    public String execute() {

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

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

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

        returnSUCCESS;

    }

    @Override

    public void setServletRequest(HttpServletRequestrequest) {

        this.request = request;

        this.session = request.getSession();

        this.application =session.getServletContext();

    }

}

 

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

<include>標籤

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

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

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

<?xmlversion="1.0"encoding="UTF-8"?>

<!DOCTYPEstrutsPUBLIC

    "-//ApacheSoftware Foundation//DTD Struts Configuration 2.0//EN"

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

<struts>

    <packagename="login"extends="struts-default"namespace="/login">

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

            <result>/user_login_success.jsp</result>

        </action>

    </package>

</struts>

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

<?xmlversion="1.0"encoding="UTF-8"?>

<!DOCTYPEstrutsPUBLIC

    "-//ApacheSoftware Foundation//DTD Struts Configuration 2.0//EN"

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

 

<struts>

    <constantname="struts.devMode"value="true"/>

    <include file="login.xml" />

</struts>

 

十四、     默認的Action

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

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

<struts>

    <constantname="struts.devMode"value="true"/>

   

    <packagename="default"namespace="/"extends="struts-default">

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

    <actionname="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)  一般不使用Struts的UI標籤

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>

    <constantname="struts.devMode"value="true"/>

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

        <actionname="r1">

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

        </action>

       

        <actionname="r2">

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

        </action>

       

        <actionname="r3">

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

        </action>

       

        <actionname="r4">

        <resulttype="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),如下:

<packagename="user"namespace="/user"extends="struts-default">  

    <global-results>

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

    </global-results>   

    <actionname="index">

        <result>/index.jsp</result>

    </action>     

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

        <result>/user_success.jsp</result>

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

 </action>      

</package>

Action所對應的Action類如下:

UserAction

public class UserAction extends ActionSupport {

    private int type;

    public int getType() {

        returntype;

    }

    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”,但是user的Action中並沒有”mainpage”的Rsult,這時就會使用全局的結果庥(global-result),這人結果集中有”mainpage”

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

<packagename="admin"namespace="/admin"extends="user">

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

        <result>/admin.jsp</result>

    </action>

</package>

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

 

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

<struts>

    <constantname="struts.devMode"value="true"/>

    <packagename="user"namespace="/user"extends="struts-default">

     

     <actionname="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 Stringr;

    public String getR() {

        returnr;

    }

    public void setR(String r) {

        this.r = r;

    }

    public int getType() {

        returntype;

    }

    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)

    客戶端跳轉則不共享

例如:

<packagename="user"namespace="/user"extends="struts-default">

   

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

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

        </action>     

    </package>

UserAction類:

public class UserAction extends ActionSupport {

    private int type;

    public int getType() {

        returntype;

    }

    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>

    UserSuccess!

    fromvaluestack: <s:propertyvalue="t"/><br/>

    fromactioncontext: <s:propertyvalue="#parameters.t"/>

    <s:debug></s:debug>

</body>

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

<s:propertyvalue="#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、  設計約定(硬編碼) ***

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

   

03 OGNL表達式語言

     Object Graph Navigation Language 對象圖導航語言

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

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

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

 

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

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

 

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

Cat

package com.wjt276.struts2.ognl;

public class Cat {

  private Dogfriend

  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 Stringname;

  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 Stringpassword;

  private Useruser;

  private Stringusername;

  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>

    <constantname="struts.enable.DynamicMethodInvocation"value="false"/>

    <constantname="struts.devMode"value="true"/>

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

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

  <includefile="/com/wjt276/struts2/ognl/ognl.xml"/>

</struts>

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

    <packagename="ognl"extends="struts-default">

        <actionname="ognl"class="com.wjt276.struts2.ognl.OgnlAction">

            <result>/ognl.jsp</result>

        </action>

    </package>

客戶端請求的URL地址:

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

<ol>

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

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

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

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

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

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

        <hr/>

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

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

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

        <hr/>

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

        <hr/>

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

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

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

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

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

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

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

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

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

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

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

        <hr/>

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

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

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

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

        <hr/>

        <li>[]:<s:propertyvalue="[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,會將值放入request和ActionContext中

            ii.     page/request/session/application

c)    bean

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

e)    param

f)    debug

2、  控制標籤

a)    Ifelseif else

b)    Iterator

             i.     collections map enumerateon iteratorarray

c)    subset

3、  UI標籤

a)    Theme

             i.     Simple xhtml(默認) css_xhtml ajax

4、  AJAX標籤

a)    補充

5、  $ #% 的區別

a)    $ 用於i18n和Struts配置文件

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:propertyvalue="username"/>

2、  取值爲字符串

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

<s:propertyvalue="’username’"/>

3、  設置默認值-default

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

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

4、  設定HTML-escape

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

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

<s:propertyvalue="'<hr/>'"escape="false"/>

 

 

 

 

二、 set標籤

注:var 用於設定變量名

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

          scope 就是的作用範圍 request sessionpage 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:setname="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:beanname="com.bjsxt.struts2.tags.Dog">

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

    </s:bean>

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

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

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

</s:bean>

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

<s:propertyvalue="#myDog.name"/>

 

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

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

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

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

                <s:propertyvalue="name"/>

    </s:bean>

 

四、 <include>標籤-少使用

包含文件

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

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

        </li>

       

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

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

        </li>

       

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

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

        <s:includevalue="%{#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:propertyvalue="#parameters.age[0]"/> <br/>

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

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

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

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

       

        <s:iftest="#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:iteratorvalue="{1, 2, 3}">

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

        </s:iterator>

        </li>

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

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

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

        </s:iterator>

        </li>

        <li>使用status:<br/>

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

            <s:property/> |

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

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

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

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

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

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

            <br/>

        </s:iterator>

       

        </li>

       

        <li>

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

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

        </s:iterator>

        </li>

       

        <li>

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

            <s:propertyvalue="#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)來處理聲明式異常處理。

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

實例:

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

public List<Category>list()throws SQLException{

      Connectionconn = DB.createConn();

      Stringsql = "select* from _category";

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

      PreparedStatementps = 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配置文件中配置需要處理的異常就可以了。

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

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

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

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

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

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

</action>

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

 

<packagename="bbs2009-deafult"extends="struts-default">

        <global-results>

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

        </global-results>

       

        <global-exception-mappings>

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

        </global-exception-mappings>

    </package>

 

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

    <packagename="admin"namespace="/admin"extends="bbs2009-default">

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

        <actionname="index">

            <result>index.html</result>

        </action>

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

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

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

            <resultname="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 voidmain(String[] args) {

        ResourceBundleres = 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:<inputname="username"type="text"/><br/>

    password:<inputname="password"type="password"/>

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

    </form></body>

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

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

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

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

 

  <body>

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

    <formaction="admin/Login-login"method="post">

    <s:propertyvalue="getText('login.username')"/><inputname="username"type="text"/><br/>

    <s:propertyvalue="getText('login.password')"/><inputname="password"type="password"/>

    <inputtype="submit"value="<s:propertyvalue='getText("login.login")'/>">

    </form>

    <s:debug></s:debug>

  </body>

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

格式:

<s:propertyvalue="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:propertyvalue="getText('welcome.msg')"/><s:propertyvalue="username"/>

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

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

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

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

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

 

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

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

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

    <s:textname="welcome.msg">

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

</s:text>

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

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

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

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

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

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

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

WW_TRANS_I18N_LOCALE=en_US

 

09 自定義攔截器

一般99.9%用不上

 

10 類型轉換

public class MyPointConverter extendsDefaultTypeConverter{

 

    @Override

    public ObjectconvertValue(Object value, Class toType) {

        if(toType == Point.class) {

            Pointp = 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();

        }

        returnsuper.convertValue(value,toType);

    }

}

public class MyPointConverter extends StrutsTypeConverter{

 

    @Override

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

       

            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 StringconvertToString(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.        類型轉換(掌握默認,瞭解自定義)

 

發佈了78 篇原創文章 · 獲贊 287 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章