struts2中使用request引起的性能浪費

struts2從2007年初推出第一個穩定的版本到現在已經發展了近3個年頭,現在,在新的產品或項目中,如果選用了struts方案,一般都選擇了struts2,並非爲用struts2而用struts2,我想一定是它的優秀吸引着我們。

 

在struts2中,value stack和ognl這兩個概念非常重要。由於我們大多數人都是從struts1過渡到struts2的,思想的轉變是需要一些時間,更重要的是需要一些實踐的,因而,我們在使用struts2的時候,常常有些類似於struts1的形式,例如,我們來看一個action的代碼:

Java代碼
  1. package com.javaeye.hnylj.action;   
  2.   
  3. import java.util.List;   
  4. import javax.servlet.http.HttpServletRequest;   
  5. import org.apache.struts2.interceptor.ServletRequestAware;   
  6. import com.javaeye.hnylj.model.UserInfo;   
  7. import com.javaeye.hnylj.service.UserInfoService;   
  8. import com.opensymphony.xwork2.ActionSupport;   
  9.   
  10. /**  
  11.  * UserAction  
  12.  *   
  13.  * @since Mar 15, 2010  
  14.  */  
  15. public class UserAction extends ActionSupport implements ServletRequestAware {   
  16.   
  17.     private static final long serialVersionUID = 7815936222081975676L;   
  18.   
  19.     private HttpServletRequest request;   
  20.   
  21.     private String id;   
  22.   
  23.     private String name;   
  24.   
  25.     private UserInfoService userInfoService;   
  26.   
  27.     public void setServletRequest(HttpServletRequest request) {   
  28.         this.request = request;   
  29.     }   
  30.   
  31.     public String getId() {   
  32.         return id;   
  33.     }   
  34.   
  35.     public void setId(String id) {   
  36.         this.id = id;   
  37.     }   
  38.   
  39.     public String getName() {   
  40.         return name;   
  41.     }   
  42.   
  43.     public void setName(String name) {   
  44.         this.name = name;   
  45.     }   
  46.   
  47.     public UserInfoService getUserInfoService() {   
  48.         return userInfoService;   
  49.     }   
  50.   
  51.     public void setUserInfoService(UserInfoService userInfoService) {   
  52.         this.userInfoService = userInfoService;   
  53.     }   
  54.   
  55.     /**  
  56.      * list users  
  57.      *   
  58.      * @return success  
  59.      * @throws Exception  
  60.      */  
  61.     @Override  
  62.     public String execute() throws Exception {   
  63.         // 注:userInfoService通過spring注入   
  64.         List<UserInfo> userList = userInfoService.getUserList();   
  65.         request.setAttribute("id", id);   
  66.         request.setAttribute("name", name);   
  67.         request.setAttribute("userList", userList);   
  68.         return SUCCESS;   
  69.     }   
  70. }  
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的代碼應該是這樣的:

Java代碼
  1. package com.javaeye.hnylj.action;   
  2.   
  3. import java.util.List;   
  4. import com.javaeye.hnylj.model.UserInfo;   
  5. import com.javaeye.hnylj.service.UserInfoService;   
  6. import com.opensymphony.xwork2.ActionSupport;   
  7.   
  8. /**  
  9.  * UserAction  
  10.  *   
  11.  * @since Mar 15, 2010  
  12.  */  
  13. public class UserAction extends ActionSupport {   
  14.   
  15.     private static final long serialVersionUID = 7815936222081975676L;   
  16.   
  17.     private String id;   
  18.   
  19.     private String name;   
  20.   
  21.     List<UserInfo> userList;   
  22.   
  23.     private UserInfoService userInfoService;   
  24.   
  25.     public String getId() {   
  26.         return id;   
  27.     }   
  28.   
  29.     public void setId(String id) {   
  30.         this.id = id;   
  31.     }   
  32.   
  33.     public String getName() {   
  34.         return name;   
  35.     }   
  36.   
  37.     public void setName(String name) {   
  38.         this.name = name;   
  39.     }   
  40.   
  41.     public List<UserInfo> getUserList() {   
  42.         return userList;   
  43.     }   
  44.   
  45.     public void setUserList(List<UserInfo> userList) {   
  46.         this.userList = userList;   
  47.     }   
  48.   
  49.     public UserInfoService getUserInfoService() {   
  50.         return userInfoService;   
  51.     }   
  52.   
  53.     public void setUserInfoService(UserInfoService userInfoService) {   
  54.         this.userInfoService = userInfoService;   
  55.     }   
  56.   
  57.     /**  
  58.      * list users  
  59.      *   
  60.      * @return success  
  61.      * @throws Exception  
  62.      */  
  63.     @Override  
  64.     public String execute() throws Exception {   
  65.         // 注:userInfoService通過spring注入   
  66.         userList = userInfoService.getUserList();   
  67.         return SUCCESS;   
  68.     }   
  69. }  
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中引起系統性能的一點思考,歡迎大家提出異議,一起交流,共同進步!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章