1. 概述 DynaFuse類似Appfuse,是一套整合目前主流J2EE技術的新構架,使用到的技術有struts,springframework,hibernate,groovy等,提出了Evertything be Dynamic的理念,從DAO到WEB層提供了全新的動態建模,動態編程的方案。2. 運行例子
下載並安裝MySQL-4.0,建立數據庫dynafuse,建立用戶username/passWord為admin/admin。
下載並解壓dynafuse-xx.zip,在MySQL中執行data/create-tables.sql中的語句。
下載jakarta-tomcat-5.0.28,將dynafuse\lib\mysql-connector-java-3.0.14-production\MySQL-connector-Java-3.0.14-production-bin.jar和dynafuse\lib\jta-1.0\jta.jar拷貝到jakarta-tomcat-5.0.28\common\lib下,將dynafuse\dynafuse.XML拷貝到jakarta-tomcat-5.0.28\conf\Catalina\localhost下,
下載dynafuse.war拷貝到jakarta-tomcat-5.0.28\webaPPS下。
啟動tomcat,打開浏覽器http://localhost:8080/dynafuse進入例子程序。 3. 包結構說明
下載並解壓dynafuse包,會得到如下的目錄結構:
build:編譯後文件
config:配置文件
data:試驗數據
dist:打包後的發布文件
docs:文檔
lib:使用到的jar文件
metadata:xdoclet需要的配置文件片斷
script:groovy腳本
src:源碼
test:測試源碼
web:例子程序的JSP等文件
4. 構架說明 dynafuse最主要的特征是提倡Everything be Dynamic,從dao到service到web三個層面,每個層面都提供了對groovy新型server端srcipt語言的整合,使得web應用中基本所有的邏輯代碼都能夠以動態的形式編寫,維護,構架分為三層: DAO層 - 這個層面中,dynafuse提供了兩個interface:DAO 和 DynaDAO ,DAO是一個通用的數據訪問(增、刪、改、查)接口,DynaDAO在DAO的基礎上提供了對DAO層面腳本的調用功能。這兩個interface目前只提供了hibernate的實現。 DAO和DynaDAO分別作為springframewok中的bean在IOC容器中進行配置,詳細請參考config\applicationContext-hibernate.xml。 Service層 - 這個層面中,dynafuse提供了兩個interface:Manager 和 DynaManager,完成對DAO的封裝並提供對service層面中業務邏輯腳本的調用功能,調用service層面腳本有兩個方法,一是在事務環境中執行腳本(invokeScriptInTransaction),一個是不需要事務(invokeScript)。Manager和DynaManager分別作為springframewok中的bean在IOC容器中進行配置,詳細請參考config\applicationContext-service.XML。 Web層 - 這個層面中,dynafuse提供了DynaAction,完成對web層面腳本的調用。
5. 構架使用
下面的文字將描述如何利用dynafuse進行web應用程序的開發。
1.構建hibernate的動態模型
hibernate在正式發布的3.0版本中,提供了動態模型,關於動態模型,可以查閱hibernate的相關資料,下面給出的是dynafuse示例程序的動態模型,文件參見dynafuse\model\Example.hbm.XML
這裡沒有靜態的POJO持久類,所有的持久數據都通過Map結構來存放。
2.DAO層面的腳本,如果DAO接口中提供的方法不能滿足需要,那麼可以在DAO層面加入腳本,然後在service層通過DynaDAO完成對DAO腳本的調用,下面是示例程序中的dynafuse cript\PersonDAO.groovy
import org.hibernate.Session; import org.hibernate.Query; public class PersonDAO {
public Session session; public Object getAvgAgeOfDept(Integer deptId) { String hsql = "select avg(t.age) from Person t where t.dept.id=:deptId"; Query query = session.createQuery(hsql); query.setInteger("deptId", deptId.intValue()); return query.uniqueResult(); } }
這裡需要說明的是session這個成員變量,它是必須要在DAO層面的腳本中申明的,在dao層面的腳本被執行的時候,dynafuse將會自動對這個session賦值,在腳本中,你不用關心session是怎麼得到,你只管放心使用。
3.service層面的腳本,在實際的應用中,業務邏輯是千變萬化的,所以service層面加入腳本支持是非常有用的,service層的腳本將在web層通過DynaManager被調用,下面是示例程序中的dynafuse cript\DeptManager.groovy
import org.robusta.dynafuse.dao.DynaDAO; import Java.util.List; public class DeptManager {
public DynaDAO dynaDao; public List getDepts() { return dynaDao.getObjects("Dept", null, null, null); } public Object getAvgAgeOfDept(Integer deptId) { return dynaDao.invokeScript("PersonDAO.groovy", "getAvgAgeOfDept", new Object[]{deptId}); } }
這裡需要說明的是dynaDao這個類成員變量,和dao層面腳本中的session一樣,是在service層面的腳本中執行的時候,由dynafuse自動賦值,你只管放心使用它。
還需要注意的是,在service層面的腳本中可以利用dynaDao去調用DAO層面的腳本,如上面的getAvgAgeOfDept。
4.構建web層的動態模型,struts提供了DynaValidatorActionForm這種構造動態模型的機制,請參考示例中的dynafuse\metadata\web truts-forms.XML。
5.web層面的腳本,跟業務邏輯一樣,頁面邏輯也是千變萬化的,所以web層的腳本非常有用,下面是示例程序中的dynafuse cript\DeptAction.groovy
public class DeptAction extends BaseAction {
....
public DynaManager dynaManager;
....
public ActionForward editDept(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { if (log.isDebugEnabled()) { log.debug("Entering 'editDept' method"); } String deptId = request.getParameter("deptId"); if (deptId != null && !"".equals(deptId)) { Map data = dynaManager.getObject("Dept", new Integer(deptId)); Long avgAge = (Long) dynaManager.invokeScript("DeptManager.groovy", "getAvgAgeOfDept", new Object[]{new Integer(deptId)}); DynaValidatorActionForm deptForm = (DynaValidatorActionForm) form; deptForm.set("id", data.get("id")); deptForm.set("name", data.get("name")); deptForm.set("description", data.get("description")); deptForm.set("avgAge", avgAge); updateFormBean(mapping, request, deptForm); } return mapping.findForward("edit"); }
....
和servcIE和dao層的腳本一樣,web層腳本中有一個dynaManager成員變量。
6.將web層的腳本配置到action中,可以參考dynafuse\metadata\web truts-actions.XML
....
....
需要注意的是這裡的parameter,指定了web層某個腳本中的某個method。