深入分析JavaWeb Item45 -- Struts2封裝請求參數與類型轉換

來源:互聯網
上載者:User

深入分析JavaWeb Item45 -- Struts2封裝請求參數與類型轉換

作為MVC架構,必須要負責解析HTTP請求參數,並將其封裝到Model對象中,Struts2提供了非常強大的類型轉換機制用於請求資料 到 model對象的封裝。

1、Struts2 提供三種資料封裝的方式Action 本身作為model對象,通過成員setter封裝

建立獨立model對象,頁面通過ognl運算式封裝

使用ModelDriven介面,對請求資料進行封裝

1. 方式一:在動作類中成員變數給予初始值。

在設定檔中struts.xml中

                    /result.jsp        

編寫result.jsp

  
${name}

編寫實作類別PersonAction,重寫excute()方法

package com.itheima.actions;import com.opensymphony.xwork2.ActionSupport;public class PersonAction extends ActionSupport {    private String name = "劉小晨";    private String password;    private int age;    public String getName() {        return name;    }    public void setName(String name) {        System.out.println("調用了setName方法");        this.name = name;    }    public String getPassword() {        return password;    }    public void setPassword(String password) {        this.password = password;    }    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;    }    public String execute() throws Exception {        System.out.println(name+":"+password+":"+age);        return super.execute();    }}

運行結果為:劉小晨

這種在類的成員變數時,就賦值的方法,亦可以在設定檔中注入動作類的參數值(靜態參數設定),Action 本身作為model對象,通過成員setter封裝(一個名字為params的攔截器乾的)

重新設定struts.xml如下:

                       王衛星            /result.jsp            

運行結果為:王衛星

實際上是由一個叫做staticParams的攔截器做的,可以查看 struts-default.xml設定檔,如果將staticParams這個攔截器刪除,則得不到想要的結果

此外還有動態參數注入,同樣用動作類作為model對象。

編寫result.jsp


設定檔和動作實作類別不變,這裡要注意: 表單的欄位輸入欄位的name,password, age取值要和動作類的寫屬性名稱一致。

運行結果:表單中name輸入的結果。

動態參數的注入也是由一個攔截器來做的:params

2、方式二:動作類和模型分開(我們以表單請求參數為例)

寫設定檔struts.xml

編寫動作類StudentAction

package com.itheima.actions;import com.itheima.domain.Student;import com.opensymphony.xwork2.ActionSupport;public class StudentAction extends ActionSupport {    private Student student = new Student();    public Student getStudent() {        System.out.println("調用了getStudent方法");        return student;    }    public void setStudent(Student student) {        System.out.println("調用了setStudent方法");        this.student = student;    }    public String execute() throws Exception {        System.out.println(student);        return NONE;    }}

編寫模型類Student.java

package com.itheima.domain;import java.io.Serializable;public class Student implements Serializable {    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;    }    @Override    public String toString() {        return "Student [name=" + name + ", age=" + age + "]";    }}

編寫訪問的頁面addStudent.jsp

  

這樣上述就將模型(Student)和動作類(StudentAction)分開了,在頁面中,我們可以用student.name和student.age來封裝請求參數了。

主要原理如下:

架構建立了一個Student的執行個體,通過調用setStudent(Student s),傳遞對象架構再調用StudentAction的getStudent(),方法,得到剛剛建立的對象緊接著,調用student執行個體的setName和setAge方法,設定值。 3. 方式三:模型驅動(面試)(與後面ValueStack值棧有關)

編寫struts.xml設定檔

編寫CustomerAction的動作類

package com.itheima.actions;import com.itheima.domain.Customer;import com.opensymphony.xwork2.ActionSupport;import com.opensymphony.xwork2.ModelDriven;//使用模型驅動:public class CustomerAction extends ActionSupport implements ModelDriven{    private Customer customer = new Customer();//這裡一定要new()出一個實體類。    public Customer getCustomer() {        return customer;    }    public void setCustomer(Customer customer) {        this.customer = customer;    }    @Override    public String execute() throws Exception {        System.out.println(customer);        return NONE;    }    public Customer getModel() {        return customer;    }}

編寫實體類Customer.java

package com.itheima.domain;import java.io.Serializable;public class Customer implements Serializable {    private String name;    private String city;    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public String getCity() {        return city;    }    public void setCity(String city) {        this.city = city;    }    @Override    public String toString() {        return "Customer [name=" + name + ", city=" + city + "]";    }}

編寫addCustomer.jsp頁面

  

這裡可以直接寫name和city來封裝請求參數,而不需要些customer.name和customer.city。

註:模型驅動實際上是由一個攔截器來做的。modelDriven攔截器來做。把getModel方法返回的對象,壓入一個叫做ValueStack的棧頂。struts架構就會根據表單的name屬性,調用對應棧頂對象的setter方法,從而把請求參數封裝進來。可以看源碼:
注意這一定要new出來! 否則架構調用CustomerAction的getCustomer()方法,得到傳回值為null。

2、 封裝資料到集合類型中

Struts2 還允許填充 Collection 裡的對象, 這常見於需要快速錄入批量資料的場合

類型轉換與Collection配合使用

類型轉換與Map配合使用

執行個體:

編寫配置struts.xml

編寫動作類CollectionAction

package com.itheima.actions;import java.util.Arrays;import java.util.Collection;import java.util.Map;import com.itheima.domain.Employee;import com.opensymphony.xwork2.ActionSupport;public class CollectionAction extends ActionSupport {    private String[] hobby;//數組    private Collection employees;//集合    private Map emps;//map    public String[] getHobby() {        return hobby;    }    public void setHobby(String[] hobby) {        this.hobby = hobby;    }    public Collection getEmployees() {        return employees;    }    public void setEmployees(Collection employees) {        this.employees = employees;    }    public Map getEmps() {        return emps;    }    public void setEmps(Map emps) {        this.emps = emps;    }    public String execute() throws Exception {//      System.out.println(Arrays.asList(hobby));//      System.out.println(employees);        if(emps!=null){            for(Map.Entry me:emps.entrySet()){                System.out.println(me.getKey()+":"+me.getValue());            }        }        return NONE;    }}

編寫實體類Employee

package com.itheima.domain;import java.io.Serializable;public class Employee implements Serializable {    private String name;    private float salary;    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public float getSalary() {        return salary;    }    public void setSalary(float salary) {        this.salary = salary;    }    @Override    public String toString() {        return "Employee [name=" + name + ", salary=" + salary + "]";    }}

編寫collectionDemo.jsp


大量新增員工資訊
向Map中新增內容3、類型轉換

對於大部分常用類型,開發人員根本無需建立自己的轉換器,Struts2內建了常見資料類型多種轉換器,8大基本類型自動轉換。
- boolean 和 Boolean
- char和 Character
- int 和 Integer
- long 和 Long
- float 和 Float
- double 和 Double
- Date 可以接收 yyyy-MM-dd格式字串,java.util.Date<——–>String(中國:Struts2預設按照yyyy-MM-dd本地格式進行自動轉換)
- 數組 可以將多個同名參數,轉換到數組中
- 集合 支援將資料儲存到 List 或者 Map 集合

總結:在使用Struts2時,基本上不用寫任何類型轉換器。內建的完全夠用。

但是因為使用者介面傳來的資料都是String:String—->其他類型,當一些需求是顯示或者是資料回顯:其他類型—–>String時,我們就要做自訂類型轉換了。

可以看一下源碼<喎?http://www.bkjia.com/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwPjxpbWcgYWx0PQ=="這裡寫圖片描述" src="http://www.bkjia.com/uploads/allimg/160110/042R5A51-7.png" title="\" />

從源碼可以看出,繼承org.apache.struts2.util.StrutsTypeConverter(最簡單和方便)

1、自訂類型轉換器

String—————–>java.util.Date MM/dd/yyyy—–>能轉換
java.util.Date———>String MM/dd/yyyy

步驟:

1. 編寫一個類直接或間接實現:
com.opensymphony.xwork2.conversion.TypeConverter介面。
也可以選擇繼承:
com.opensymphony.xwork2.conversion.impl.DefaultTypeConverter

我們選擇繼承org.apache.struts2.util.StrutsTypeConverter,並覆蓋掉如下方法
public Object convertValue(Object value, Class toType)

假如在動作類HelloWorldAction 中有一個時間參數createtime

import java.util.Date;public class HelloWorldAction {    private Date createtime;    public Date getCreatetime() {        return createtime;    }    public void setCreatetime(Date createtime) {        this.createtime = createtime;    }}

自訂我們的轉換器MyDateConvertor ,覆蓋convertFromString()和convertToString()方法。

package com.itheima.convertor;import java.text.DateFormat;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Map;import org.apache.struts2.util.StrutsTypeConverter;//日期轉換器:/* * String :12/31/2001 ---->Date * Date---------->String:12/31/2001 */public class MyDateConvertor extends StrutsTypeConverter {    private DateFormat df = new SimpleDateFormat("MM/dd/yyyy");    //從字串轉換成日期    public Object convertFromString(Map context, String[] values, Class toClass) {        if(toClass==Date.class){            String value = values[0];//擷取使用者輸入的參數值12/31/2001            try {                return df.parse(value);            } catch (ParseException e) {                e.printStackTrace();            }        }        return null;    }    //日期轉換成字串    public String convertToString(Map context, Object o) {        if(o instanceof Date){            Date d = (Date)o;            return df.format(d);        }        return null;    }}

2.註冊類型轉換器

局部類型轉換器:為某個動作類服務的(特服)

在Action類所在的包下放置ActionClassName-conversion.properties檔案,ActionClassName是Action的類名,後面的-conversion.properties是固定寫法,對於本例而言,檔案的名稱應為HelloWorldAction-conversion.properties 。在properties檔案中的內容為:

屬性名稱=類型轉換器的全類名

對於本例而言, HelloWorldAction-conversion.properties檔案中的內容為:

createtime= cn.itcast.conversion.DateConverter

全域類型轉換器:為所有的動作類服務的
在WEB-INF\classes目錄下(在src下)建立一個固定名稱的設定檔:xwork-conversion.properties

對於本例而言, xwork-conversion.properties檔案中的內容為:
java.util.Date= cn.itcast.conversion.DateConverter

3、出現轉換失敗時的頁面轉向和錯誤訊息提示
Struts2提供了一個名為conversionError的攔截器,查看struts-default.xml

如果Struts2的類型轉換器執行類型轉換時出現錯誤,該攔截器將負責將對應錯誤封裝成表單域錯誤(FieldError),並將這些錯誤資訊放入ActionContext中
使用類型轉換中的錯誤處理使用者定義Action必須繼承ActionSupport

在自訂類型轉換器中,異常必須拋出不能捕獲,conversionError會處理該異常,然後轉入名為input的邏輯視圖
在Action所在包中,建立 ActionName.properties,在局部資源檔中配置提示資訊 : invalid.fieldvalue.屬性名稱= 錯誤資訊
在input邏輯視圖所對應jsp頁面中,通過 輸出類型轉換資訊

a、配置一個name=”input”的結果檢視,一般指向使用者輸入資料的那個頁面

b、在sp中使用struts2的標籤顯示欄位有關的錯誤(後面的國際化再講)

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

c、配置提示資訊為中文的
在動作類所在的包中,建立一個名稱為:動作類名.properties的設定檔

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.