在之前我們所示範的範例中,Action 的 property 都是以 primary data type 為主!如果我們有一些 domain object 已經定義好了,那我們可不可以 reuse 這些 objects 呢?以 programmer 的角度來說,應該是可行!沒錯~ Struts2 的確有提供這樣的機制,讓我們可以 reuse 已經定義好的物件!例如:我們已經定義好一個 User 物件如下:
public class User
{
private String name;
private String password;
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getPassword()
{
return password;
}
public void setPassword(String password)
{
this.password = password;
}
}
User class 中包含了 username 與 password 的 properties,當然,我們的物件也一定是一個 JavaBean,這樣我們才可以針對物件的 properties 進行存取!
接下來,我們就要更改我們的 HelloUser Action 的程式,當然是要使用我們已經定義好的 User 物件作為 property。在 Struts2 中提供了兩種方式:Object-backed JavaBean properties 與 ModelDriven actions。接下來我們會分別介紹這兩種方式來達到我們的目的。
Object-backed JavaBean properties
Object-backed JavaBean properties 的方式是最直接的,就是直接將我們所定義好的 User 物件當作 HelloUser Action 中的 property,所以我們的 HelloUser 程式修改為:
package silver8250.hello;
import com.opensymphony.xwork2.ActionSupport;
public class HelloUser extends ActionSupport
{
private User user;
private String message;
public User getUser()
{
return user;
}
public void setUser(User user)
{
this.user = user;
}
public String getMessage()
{
return message;
}
public void setMessage(String message)
{
this.message = message;
}
public String execute()
{
this.message = "Hi~"+this.user.getName();
return super.SUCCESS;
}
}
上面的程式碼中只是很簡單的將我們 User 物件當作 property,而且我們不必自己去初始化這個物件,因為 Struts2 framework 會幫我們去處理這個細節。這樣的方式讓我們的 Action 看起來更簡潔有力了~
不過對應的 Jsp 頁面則是要作一些修正,因為我們原先將使用者輸入的資料是直接屬於 Action 之下,但是因為我們現在是將使用者輸入資料的對應 property 放至於 User 物件中,所以我們要將 tag 更改為:
<s:textfield name="user.name" label="Your Name" value="" />
很直覺吧~當然,取值的時候也是這樣~其實就是 OGNL 的更改罷了~不過現在我們並不會深入 OGNL 的功能上!
ModelDriven actions
ModelDriven actions 是另一種可以實現與 Object-backed JavaBean properties 的方法,屬於 Struts2 framework 內建的機制,也就是將我們的 Action implements ModelDriven,並且 ModelDriven interface 有提供 Generic 的機制,所以我們的程式可以修改如下:
package silver8250.hello;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
public class HelloUser extends ActionSupport implements ModelDriven<User>
{
private User user = new User();
private String message;
public User getModel()
{
return user;
}
public String getMessage()
{
return message;
}
public void setMessage(String message)
{
this.message = message;
}
public String execute()
{
this.message = "Hi~"+this.user.getName();
return super.SUCCESS;
}
}
這種方式並不難,只是將我們原先針對 User 物件的 getter/setter 拿掉,並且實做出 getModel() method,而且回傳我們的 User 物件就可以了!不過這裡有一點要注意,我們的 User 物件一定要初始化,否則會在執行 execute() method 時出現錯誤!
使用 ModelDriven actions 的方式,User 物件裡面的所有 properties 就會像是被嵌入到我們的 Action 一樣,也就是說,當我們在 JSP 頁面取值的時候,OGNL 就不用像 Object-backed JavaBean properties 需要先以我們的 User 物件為開始點,所以我們可以直接取 name properties:
不過採用 ModelDriven actions 時還有一點要注意,如果我們所 reuse 的物件中與 Action 中有一樣的 property,那 Action 中的 property 就會被隱藏~例如:我們將 HelloUser Action 更改為:
package silver8250.hello;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
public class HelloUser extends ActionSupport implements ModelDriven<User>
{
private User user = new User();
private String name;
public User getModel()
{
return user;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String execute()
{
this.name = "Hi~"+this.user.getName();
return super.SUCCESS;
}
}
使用者所輸入的 name 在送出後,我們取 name 的值就會只有取到 User 中的 name,而且使用者所輸入的 name 資料也只會被存在 User 的 name 中!所以這點要小心,否則當出現問題時會很不容易發現!
Conclusion
雖然 Struts2 有兩種方式可以讓我們 reuse 已經撰寫好的物件,不過我個人是比較喜歡也比較建議使用 Object-backed JavaBean properties 的方式,因為這種方式比較直覺,而且我們可以在 Action 中 reuse 一個以上的物件,而 ModelDriven actions 的方式就不行!而且在撰寫頁面中的 OGNL 時也比較好 debug~畢竟他很明確的指出是在往下一層!
不過還是看個人習慣囉~