struts2從2007年初推出第一個穩定的版本到現在已經發展了近3個年頭,現在,在新的產品或項目中,如果選用了struts方案,一般都選擇了struts2,並非爲用struts2而用struts2,我想一定是它的優秀吸引着我們。
在struts2中,value stack和ognl這兩個概念非常重要。由於我們大多數人都是從struts1過渡到struts2的,思想的轉變是需要一些時間,更重要的是需要一些實踐的,因而,我們在使用struts2的時候,常常有些類似於struts1的形式,例如,我們來看一個action的代碼:
- package com.javaeye.hnylj.action;
- import java.util.List;
- import javax.servlet.http.HttpServletRequest;
- import org.apache.struts2.interceptor.ServletRequestAware;
- import com.javaeye.hnylj.model.UserInfo;
- import com.javaeye.hnylj.service.UserInfoService;
- import com.opensymphony.xwork2.ActionSupport;
- /**
- * UserAction
- *
- * @since Mar 15, 2010
- */
- public class UserAction extends ActionSupport implements ServletRequestAware {
- private static final long serialVersionUID = 7815936222081975676L;
- private HttpServletRequest request;
- private String id;
- private String name;
- private UserInfoService userInfoService;
- public void setServletRequest(HttpServletRequest request) {
- this.request = request;
- }
- public String getId() {
- return id;
- }
- public void setId(String id) {
- this.id = id;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public UserInfoService getUserInfoService() {
- return userInfoService;
- }
- public void setUserInfoService(UserInfoService userInfoService) {
- this.userInfoService = userInfoService;
- }
- /**
- * list users
- *
- * @return success
- * @throws Exception
- */
- @Override
- public String execute() throws Exception {
- // 注:userInfoService通過spring注入
- List<UserInfo> userList = userInfoService.getUserList();
- request.setAttribute("id", id);
- request.setAttribute("name", name);
- request.setAttribute("userList", userList);
- return SUCCESS;
- }
- }
package com.javaeye.hnylj.action;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.interceptor.ServletRequestAware;
import com.javaeye.hnylj.model.UserInfo;
import com.javaeye.hnylj.service.UserInfoService;
import com.opensymphony.xwork2.ActionSupport;
/**
* UserAction
*
* @since Mar 15, 2010
*/
public class UserAction extends ActionSupport implements ServletRequestAware {
private static final long serialVersionUID = 7815936222081975676L;
private HttpServletRequest request;
private String id;
private String name;
private UserInfoService userInfoService;
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public UserInfoService getUserInfoService() {
return userInfoService;
}
public void setUserInfoService(UserInfoService userInfoService) {
this.userInfoService = userInfoService;
}
/**
* list users
*
* @return success
* @throws Exception
*/
@Override
public String execute() throws Exception {
// 注:userInfoService通過spring注入
List<UserInfo> userList = userInfoService.getUserList();
request.setAttribute("id", id);
request.setAttribute("name", name);
request.setAttribute("userList", userList);
return SUCCESS;
}
}
從上面的代碼中,我們明顯感覺到,這與struts1的代碼模式非常相似,而常常我們在代碼中又是這樣寫的,當然這樣也是完全可以的。
而作爲struts2的代碼應該是這樣的:
- package com.javaeye.hnylj.action;
- import java.util.List;
- import com.javaeye.hnylj.model.UserInfo;
- import com.javaeye.hnylj.service.UserInfoService;
- import com.opensymphony.xwork2.ActionSupport;
- /**
- * UserAction
- *
- * @since Mar 15, 2010
- */
- public class UserAction extends ActionSupport {
- private static final long serialVersionUID = 7815936222081975676L;
- private String id;
- private String name;
- List<UserInfo> userList;
- private UserInfoService userInfoService;
- public String getId() {
- return id;
- }
- public void setId(String id) {
- this.id = id;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public List<UserInfo> getUserList() {
- return userList;
- }
- public void setUserList(List<UserInfo> userList) {
- this.userList = userList;
- }
- public UserInfoService getUserInfoService() {
- return userInfoService;
- }
- public void setUserInfoService(UserInfoService userInfoService) {
- this.userInfoService = userInfoService;
- }
- /**
- * list users
- *
- * @return success
- * @throws Exception
- */
- @Override
- public String execute() throws Exception {
- // 注:userInfoService通過spring注入
- userList = userInfoService.getUserList();
- return SUCCESS;
- }
- }
package com.javaeye.hnylj.action;
import java.util.List;
import com.javaeye.hnylj.model.UserInfo;
import com.javaeye.hnylj.service.UserInfoService;
import com.opensymphony.xwork2.ActionSupport;
/**
* UserAction
*
* @since Mar 15, 2010
*/
public class UserAction extends ActionSupport {
private static final long serialVersionUID = 7815936222081975676L;
private String id;
private String name;
List<UserInfo> userList;
private UserInfoService userInfoService;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<UserInfo> getUserList() {
return userList;
}
public void setUserList(List<UserInfo> userList) {
this.userList = userList;
}
public UserInfoService getUserInfoService() {
return userInfoService;
}
public void setUserInfoService(UserInfoService userInfoService) {
this.userInfoService = userInfoService;
}
/**
* list users
*
* @return success
* @throws Exception
*/
@Override
public String execute() throws Exception {
// 注:userInfoService通過spring注入
userList = userInfoService.getUserList();
return SUCCESS;
}
}
簡單比較這兩段代碼,引起我思考的是這兩種代碼模式在性能上的不同,我們知道,在struts2中,所有的屬性值,包括從客戶端傳遞的參數或從數據庫查詢的數據,只要在action中對應有此屬性變量的定義,並擁有相應的setter與getter方法,這些數據都會被放置到值棧中,在頁面我們就可以使用struts2的標籤或ognl取得這些值。struts2將這些數據放置到值棧中,肯定是需要耗費一定的內存的,但struts2的過濾器有一種功能就是在使用之後執行ActionContextCleanUp.cleanUp(req),將值棧清空。而我們第一種代碼方式,是將所有的數據,包括從客戶端傳遞的參數或從數據庫查詢的數據都放置到request中,然後在頁面通過jstl或el表達式取出request中的值,雖然request在一次請求之後也會把數據銷燬,但我想說的是,既然struts2已經將這些數據放置到了值棧中,而我們又將這些數據在request中放置一遍,那麼這樣一來,每一個action被執行,在數據沒有銷燬之前,數據在內存中就放置了兩份,這無疑會犧牲不必要的內存資源,特別是一些對性能要求較高而硬件配置又有限的情況下。
在struts2中,每一個Action是線程安全的,即每一個客戶端的請求都會new一個新的Action爲其提供服務,如此就會使得,當系統在線人數較多時,會new出較多的Action來爲這些在線的用戶服務,而當我們使用第一種模式的代碼時,每一個Action中都將數據放置到request中,然後通過jstl在頁面中顯示,這樣,request不知要放置多少數據,再加上本來struts2在值棧中也放置了這些數據,那麼內存的使用將是成倍數的上升,我們完全可以放棄使用request,因爲在struts2中所有的數據會自動放置到值棧中,我做了一點測試,使用第一種模式的代碼,我通過查看windows資源管理器的tomcat進程的內存使用,發現它明顯高於第二種代碼模式的內存使用,另外讓我感覺更爲興奮的是,jstl也完全可以取得值棧中的數據,所以你完全可以使用struts2+jstl進行開發。
這是我對關於struts2中使用request中引起系統性能的一點思考,歡迎大家提出異議,一起交流,共同進步!