Struts2中的ModelDriven機制及其運用
所謂ModelDriven,意思是直接把實體類當成頁面資料的收集物件。比如,有實體類User如下:
[html] view plain copy print?- package cn.com.leadfar.struts2.actions;
- public class User {
- private int id;
- private String username;
- private String password;
- private int age;
- private String address;
- public String getUsername() {
- return username;
- }
- public void setUsername(String username) {
- this.username = username;
- }
- 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 getAddress() {
- return address;
- }
- public void setAddress(String address) {
- this.address = address;
- }
- public int getId() {
- return id;
- }
- public void setId(int id) {
- this.id = id;
- }
- }
package cn.com.leadfar.struts2.actions;
public class User {
private int id;
private String username;
private String password;
private int age;
private String address;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
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 getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
假如要寫一個Action,用來新增User。
第一種做法是直接在Action中定義所有需要的屬性,然後在JSP中直接用屬性名稱來提交資料:
UserAction:
[java] view plain copy print?- publicclass UserAction {
- privateint id;
- private String username;
- private String password;
- privateint age;
- private String address;
- public String add(){
- User user = new User();
- user.setId(id);
- user.setUsername(username);
- user.setPassword(password);
- user.setAge(age);
- user.setAddress(address);
- new UserManager().addUser(user);
- return“success”;
- }
- publicint getId() {
- return id;
- }
- publicvoid setId(int id) {
- this.id = id;
- }
- public String getUsername() {
- return username;
- }
- publicvoid setUsername(String username) {
- this.username = username;
- }
- public String getPassword() {
- return password;
- }
- publicvoid setPassword(String password) {
- this.password = password;
- }
- publicint getAge() {
- return age;
- }
- publicvoid setAge(int age) {
- this.age = age;
- }
- public String getAddress() {
- return address;
- }
- publicvoid setAddress(String address) {
- this.address = address;
- }
- }
public class UserAction {
private int id;
private String username;
private String password;
private int age;
private String address;
public String add(){
User user = new User();
user.setId(id);
user.setUsername(username);
user.setPassword(password);
user.setAge(age);
user.setAddress(address);
new UserManager().addUser(user);
return "success";
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
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 getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
add_input.jsp:[html] view plain copy print?
- <formaction=“test/user.action”method=“post”>
- <inputtype=“hidden”name=“method:add”>
- username:<inputtype=“text”name=“username”><br/>
- password:<inputtype=“text”name=“password”><br/>
- age:<inputtype=“text”name=“age”><br/>
- address:<inputtype=“text”name=“address”><br/>
- <inputtype=“submit”name=“submit”value=“新增使用者”>
- </form><br/>
<form action="test/user.action" method="post">
<input type="hidden" name="method:add">
username:<input type="text" name="username"> <br/>
password:<input type="text" name="password"> <br/>
age:<input type="text" name="age"> <br/>
address:<input type="text" name="address"> <br/>
<input type="submit" name="submit" value="新增使用者">
</form> <br/>
上述做法不好之處是:如果實體類的屬性非常多,那麼Action中也要定義相同的屬性
第二種做法是將User物件定義到UserAction中,然後在JSP中通過user屬性來給user賦值:
UserAction:
- publicclass UserAction {
- private User user;
- public String add(){
- new UserManager().addUser(user);
- return“success”;
- }
- public User getUser() {
- return user;
- }
- publicvoid setUser(User user) {
- this.user = user;
- }
- }
public class UserAction {
private User user;
public String add(){
new UserManager().addUser(user);
return "success";
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
add_input.jsp:
[html] view plain copy print?- <formaction=“test/user.action”method=“post”>
- <inputtype=“hidden”name=“method:add”>
- username:<inputtype=“text”name=“user.username”><br/>
- password:<inputtype=“text”name=“user.password”><br/>
- age:<inputtype=“text”name=“user.age”><br/>
- address:<inputtype=“text”name=“user.address”><br/>
- <inputtype=“submit”name=“submit”value=“新增使用者”>
- </form><br/>
<form action="test/user.action" method="post">
<input type="hidden" name="method:add">
username:<input type="text" name="user.username"> <br/>
password:<input type="text" name="user.password"> <br/>
age:<input type="text" name="user.age"> <br/>
address:<input type="text" name="user.address"> <br/>
<input type="submit" name="submit" value="新增使用者">
</form> <br/>
這種做法不好的地方是:JSP頁面上表單域中的命名變得太長第三種做法是利用ModelDriven機制,讓UserAction實現一個ModelDriven介面,同時實現介面中的方法:getModel()。如下所示:[java] view plain copy print?
- publicclass UserAction implements ModelDriven{
- private User user;
- @Override
- public Object getModel() {
- if(user == null){
- user = new User();
- }
- return user;
- }
- public String add(){
- new UserManager().addUser(user);
- return“success”;
- }
- public User getUser() {
- return user;
- }
- publicvoid setUser(User user) {
- this.user = user;
- }
- }
public class UserAction implements ModelDriven{
private User user;
@Override
public Object getModel() {
if(user == null){
user = new User();
}
return user;
}
public String add(){
new UserManager().addUser(user);
return "success";
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
JSP的程式碼如下:[html] view plain copy print?
- <formaction=“test/user.action”method=“post”>
- <inputtype=“hidden”name=“method:add”>
- username:<inputtype=“text”name=“username”><br/>
- password:<inputtype=“text”name=“password”><br/>
- age:<inputtype=“text”name=“age”><br/>
- <inputtype=“submit”name=“submit”value=“新增使用者”>
- </form><br/>
<form action="test/user.action" method="post">
<input type="hidden" name="method:add">
username:<input type="text" name="username"> <br/>
password:<input type="text" name="password"> <br/>
age:<input type="text" name="age"> <br/>
<input type="submit" name="submit" value="新增使用者">
</form> <br/>
可見,第三種做法是比較好的,Action和JSP寫起來都比較簡單。
注意:(1)一個請求在最終到達Action的方法之前,Action物件本身會被壓入ValueStack(實際上就是放到ValueStack的CompoundRoot中),所以Action物件是CompoundRoot中的一個元素(2)這裡的user必須不能為null才會被壓入到棧頂中!!
ModelDriven機制
ModelDriven背後的機制就是ValueStack。介面通過:username/age/address這樣的名稱,就能夠被直接賦值給user物件,這證明user物件正是ValueStack中的一個root物件!
那麼,為什麼user物件會在ValueStack中呢?它是什麼時候被壓入ValueStack的呢?答案是:ModelDrivenInterceptor。ModelDrivenInterceptor是預設的攔截器鏈的一部分,當一個請求經過ModelDrivenInterceptor的時候,在這個攔截器中,會判斷當前要呼叫的Action物件是否實現了ModelDriven介面,如果實現了這個介面,則呼叫getModel()方法,並把返回值(本例是返回user物件)壓入ValueStack。
請看ModelDrivenInterceptor的程式碼:
[java] view plain copy print?- @Override
- public String intercept(ActionInvocation invocation) throws Exception {
- //獲取當前正在執行的Action
- Object action = invocation.getAction();
- //如果Action實現了ModelDriven介面
- if (action instanceof ModelDriven) {
- ModelDriven modelDriven = (ModelDriven) action;
- ValueStack stack = invocation.getStack();
- //通過getModel方法獲取model
- Object model = modelDriven.getModel();
- //如果model不為null則把model壓入值棧
- if (model != null) {
- stack.push(model);
- }
- if (refreshModelBeforeResult) {
- //在執行Result之前是否要更新model物件,預設為false
- invocation.addPreResultListener(new RefreshModelBeforeResult(modelDriven, model));
- }
- }
- return invocation.invoke();//呼叫下一個攔截器
- }
- 從ModelDrivenInterceptor中,即可以看到model物件被壓入ValueStack中!
@Override
public String intercept(ActionInvocation invocation) throws Exception {
//獲取當前正在執行的Action
Object action = invocation.getAction();
//如果Action實現了ModelDriven介面
if (action instanceof ModelDriven) {
ModelDriven modelDriven = (ModelDriven) action;
ValueStack stack = invocation.getStack();
//通過getModel方法獲取model
Object model = modelDriven.getModel();
//如果model不為null則把model壓入值棧
if (model != null) {
stack.push(model);
}
if (refreshModelBeforeResult) {
//在執行Result之前是否要更新model物件,預設為false
invocation.addPreResultListener(new RefreshModelBeforeResult(modelDriven, model));
}
}
return invocation.invoke();//呼叫下一個攔截器
}
從ModelDrivenInterceptor中,即可以看到model物件被壓入ValueStack中!
其中的refreshModelBeforeResult是為了接下來描述的一個問題而提供的解決方法。
理解常見的陷阱及其解決方法
假設我們要更新一個實體物件,那麼第一步首先是開啟更新介面,請看下述模擬開啟更新介面的程式碼:
- publicclass UserAction implements ModelDriven{
- private User user;
- public Object getModel() {
- if(user == null){
- user = new User();//user.setUsername(“這是原來的User物件”);
- }
- return user;
- }
- public String updateInput(){
- //根據ID,查詢資料庫,得到User物件
- user = new UserManager().findUserById(user.getId());
- return“update_input”;
- }
- }
public class UserAction implements ModelDriven{
private User user;
public Object getModel() {
if(user == null){
user = new User();//user.setUsername("這是原來的User物件");
}
return user;
}
public String updateInput(){
//根據ID,查詢資料庫,得到User物件
user = new UserManager().findUserById(user.getId());
return "update_input";
}
}上述程式碼中,new UserManager().findUserById(user.getId());這一行,將從資料庫中查詢相應的記錄,同時轉換為User物件返回。而return “update_input”;將轉向更新顯示頁面。
更新頁面如下:
- <formaction=“test/user.action”method=“post”>
- <inputtype=“hidden”name=“method:update”>
- id:<inputtype=“text”name=“id”value=”<s:property value=”id“/>”><br/>
- username:<inputtype=“text”name=“username”value=”<s:property value=”username“/>”><br/>
- password:<inputtype=“text”name=“password”value=”<s:property value=”password“/>”><br/>
- age:<inputtype=“text”name=“age”value=”<s:property value=”age“/>”><br/>
- address:<inputtype=“text”name=“address”value=”<s:property value=”address“/>”><br/>
- <inputtype=“submit”name=“submit”value=“更新使用者”>
- </form><br/>
<form action="test/user.action" method="post">
<input type="hidden" name="method:update">
id:<input type="text" name="id" value="<s:property value="id"/>"> <br/>
username:<input type="text" name="username" value="<s:property value="username"/>"> <br/>
password:<input type="text" name="password" value="<s:property value="password"/>"> <br/>
age:<input type="text" name="age" value="<s:property value="age"/>"> <br/>
address:<input type="text" name="address" value="<s:property value="address"/>"> <br/>
<input type="submit" name="submit" value="更新使用者">
</form> <br/>
上述程式碼執行起來之後,你在更新介面上將看不到資料(id屬性有值,其它屬性無顯示)。關鍵的原因是在執行到updateInput之前,user物件(在getMode()方法中建立的物件)被壓到ValueStack中,這時候,UserAction和ValueStack都指向同一個user物件;但緊接著,UserAction中的user被一個新的user物件覆蓋,這時候,UserAction和ValueStack不再指向同一個user物件!ValueStack中是舊的user物件,而UserAction中是新的user物件!我們在JSP中,直接通過username/address等直接訪問,當然是要訪問ValueStack中的舊user物件,所以它們的屬性都是空的(id屬性除外)!
理解上述問題很重要,當你理解了問題,那麼問題的解決方法就可以有很多了:
比如,你可以把新物件的屬性拷貝到舊物件上;比如,你可以先把舊物件從ValueStack中移除,然後再把新物件壓入ValueStack等……
在最新的struts2版本中,ModelDrivenInterceptor提供了一個配置引數:refreshModelBeforeResult,只要將它定義為true,上述問題就被解決了!struts2的解決方案就是:先把舊的model物件從ValueStack中移除,然後再把新的model物件壓入ValueStack!
再看下一個例子會更加清楚:
MyJsp.jsp:
[html] view plain copy print?- <body>
- <formaction=“user_test1.action”method=“post”>
- username:<inputtype=“text”name=“name”><br/>
- dogname:<inputtype=“text”name=“dog.name”><br/>
- <inputtype=“submit”>
- <s:debug></s:debug>
- </form><br/>
- </body>
<body>
<form action="user_test1.action" method="post">
username:<input type="text" name="name"> <br/>
dogname:<input type="text" name="dog.name"> <br/>
<input type="submit">
<s:debug></s:debug>
</form> <br/>
</body>
UserAction:[java] view plain copy print?
- publicclass UserAction extends ActionSupport implements ModelDriven<User> {
- private User user;
- @Override
- public User getModel() {
- // TODO Auto-generated method stub
- if(user == null){
- user = new User();
- }
- return user;
- }
- public String test1(){
- System.out.println(user.getName());
- System.out.println(user.getDog().getName());
- List list = new ArrayList();
- for(int i=0; i<10; i++){
- User user = new User();
- user.setName(”User”+i);
- list.add(user);
- }
- ActionContext.getContext().put(”users”, list);
- User u = new User();
- u.setName(”趙毅”);
- ActionContext.getContext().getValueStack().push(u);
- return“test1”;
- }
- public String m(){
- return“yes”;
- }
- }
public class UserAction extends ActionSupport implements ModelDriven<User> {
private User user;
@Override
public User getModel() {
// TODO Auto-generated method stub
if(user == null){
user = new User();
}
return user;
}
public String test1(){
System.out.println(user.getName());
System.out.println(user.getDog().getName());
List list = new ArrayList();
for(int i=0; i<10; i++){
User user = new User();
user.setName("User"+i);
list.add(user);
}
ActionContext.getContext().put("users", list);
User u = new User();
u.setName("趙毅");
ActionContext.getContext().getValueStack().push(u);
return "test1";
}
public String m(){
return "yes";
}
}
getData.jsp:
[html] view plain copy print?- <body>
- <s:propertyvalue=“{name}”/><br/>
- <s:property
相關推薦
struts中ModelDriven()介面 Struts2中的ModelDriven機制及其運用、refreshModelBeforeResult屬性解決的問題
Struts2中的ModelDriven機制及其運用、refreshModelBeforeResult屬性解決的問題 1.為什麼需要ModelDriven? 所謂ModelDriven,意思是直接把實體類當成頁面資料的收集物件。比如,有實體類User如下:
Struts2中的ModelDriven機制及其運用
所謂ModelDriven,意思是直接把實體類當成頁面資料的收集物件。比如,有實體類User如下: [html] view plain copy print?package cn.com.leadfar.struts2.actions; public c
遊戲中Buff機制及其實際運用
首先我想說的是,這是一套機制,並不是單獨的一個系統,所謂機制就是一種從邏輯思想到程式碼實現的小竅門的組合,只有當你把它運用到一個實際專案中去了,它才能幫助你建立一個系統。我不敢說它是最好的,但這套東西幫我完成了一個又一個專案的製作,我覺得現在可以簡單的拿出來和大家分享下思維
Struts2中ModelDriven的使用
package com.lsc.alan.action; import com.lsc.alan.vo.User; import com.opensymphony.xwork2.ModelDriven; /** * 使用模型驅動來接受使
Struts2中ModelDriven的作用以及遍歷棧頂的list,map
把當前的類中實體類物件壓入棧頂 public T getModel() { // TODO Auto-generated method stub returnthis.t; } <s:aac
struts2進階二---OGNL表示式與OGNL表示式在struts2中的運用
OGNL(物件檢視導航語言)表示式 (EL表示式就是) OGNL不僅僅可以檢視導航還支援比EL表示式更加豐富的功能 使用: 準備工作1:導包(struts包裡面已經有了) 準備工作2: ognl基本語法: 1:取值 取出root中的屬性值
Struts2中資料封裝機制
Struts2當中資料封裝的三種機制:屬性驅動、標籤驅動、模型驅動。下面來一一介紹。 一、屬性驅動 1、需要提供對應屬性的set方法進行資料的封裝。 2、表單的哪些屬性需要封裝資料,那麼在對應的Act
struts2中的異常對映處理機制
首先在struts2中有兩種異常處理機制:區域性異常對映和全域性異常對映。 拿經典的使用者登入功能來說: 一:區域性異常: 1:首先我們的登入介面:表單交由exAction.action 處理。 &
在struts2中配置自定義攔截器放行多個方法
return med ttr limit ring req tac cat invoke 源碼: 自定義的攔截器類: //自定義攔截器類:LoginInterceptor ; package com.java.action.interceptor; import j
【struts2】struts2中的流接收與流發送
hive req nal oct true 中文名 tom auto 標示 【前言】在我們的struts2後端中,實現流的接收和發送。就能夠實現向server傳視頻流以及下載圖片。 【流接收】 如今舉一個傳公鑰的樣例。struts2用一個action接收Key,而Key
struts2的返回類型、struts的標簽庫、struts2中完成國際化
let 頁面 const patch red struts2標簽 property 單選 bmi struts2的返回類型:在jsp-servlet中, 返回的類型主要有 轉發, 重定向; 轉發主要是RequestDispatcher的forward方法來進行操作的req.
實體、實體集及其運用
sys val can har 賦值 center 過程 num red 一、實體 實體 在C#中的寫法 在C#中 寫法(1): public class UserInfo { public int UserID { get; se
struts2中訪問servlet API
auto etl sid ict htm ngx dff .com zhong iOS%20%E7%96%91%E9%9A%BE%E6%9D%82%E7%97%87%E2%80%94%20%E2%80%94%20%20%E6%94%B6%E5%88%B0%E6%8E%A8%
Eclipse中插件的運用
bug 箭頭 com eclips ips lib debug city ins 1. hotcode2.jar 支持java代碼熱部署,改了本地java代碼不需要重新部署生效,可以節省開發時間,提高開發效率。 安裝方法: 到help -- install new so
struts2中獲取表單數據的方式
處理 struts2 對象 進行 數據模型 模型驅動 屬性 表單 基本 在最近學習的struts2,struts2獲取表單的方式主要有兩種 一:屬性驅動 屬性驅動主要指的是通過字段進行數據的傳輸,其中包括兩種情況 1:與基本數據類型的屬性對應 2:直接使用域對象 二:模型驅
Serializable在C#中的作用及其優點
p s mst access pen eat mat zab ref hal 原文發布時間為:2009-10-27 —— 來源於本人的百度文章 [由搬家工具導入]Serializalbe - Enable the object can be Serialized into
走進Struts2(一) — Struts2的執行流程及其工作原理
管理 npr clean 核心部分 由於 nco 方式 中間 con Struts2是一套很優秀的Web應用框架,實現優雅、功能強大、使用簡潔。能夠說是Struts2是一款很成熟的MVC架構。 在我們學習Struts2時,最好是先學習它的執行流程、核心概念。從中
自己定義struts2中action類型轉換器
ansi work row 接受 4.0 open 技術 oos lang DateAction.java中代碼例如以下: package com.itheima.action; import java.util.Date; public class Da
Cocos2d-X中Menu的綜合運用
cond edi ros log 程序 cal coo 項目 綜合 今天將曾經寫的代碼和項目集成到了一個菜單中,能夠通過菜單切換到曾經做的項目 程序的project文件夾 主要代碼分析: LessonMenu.h中實現創建菜單,遍歷菜單通過菜單切換
Struts2中動態方法調用
.com log ima struts2 http als ges XML 配置 1 . 查看默認配置,是否為:true 2.如果為false 可以通過struts.xml進行相關的配置: Struts2中動態方法調用