Spring MVC+BlazeDS+Flex框架实践:Database篇

http://blog.csdn.net/meteorlWJ/archive/2009/09/12/4545858.aspx 中实践了此框架的基础搭建,本次的实践将在此基础上引入hibernate配置,并创建FLEX应用实现数据库操作。

一、环境配置
MyEclipse 7.0

Flex Builder 3.0

Tomcat 6.0

JDK1.6

Flex sdk 3.2

Oracle 10g :XE


二、Hibernate+Proxool配置
Hibernate管理JAVA类到数据库表的映射,并提供数据查询和获取的方法。Hibernate对JDBC进行了轻量级的对象封装,完成了数据持久化的重任。
这是一个Java SQL Driver驱动程序,提供了对你选择的其它类型的驱动程序的连接池封装。Proxool提供一个健壮、易用的连接池,最为关键的是这个连接池提供监控的功能,方便易用,便于发现连接泄漏的情况。

1)连接池配置:proxool.xml
在JAVA工程src下创建proxool.xml,添加如下配置:

其中参数详解如下:
alias :数据源别名
driver-url :连接字符串
driver-class :驱动类
statistics :连接池使用状态统计
driver-properties :数据库连接用户名/密码
house-keeping-sleep-time :house keeper保留线程处于睡眠状态的最长时间,
house-keeper的职责就是检查各个连接的状态,并判断是否需要销毁或创建
maximum-new-connections :没有空闲连接时可以分配在队列中等待的最大请 求数
maximum-connection-count :最大连接数
minimum-connection-count :最小连接数
trace :每个被执行的SQL语句是执行期是否用被LOG记录
verbose :详细信息设置


<br><br><?xml version="1.0" encoding="UTF-8"?> <something-else-entirely> <proxool> <alias>test</alias> <driver-url>jdbc:oracle:thin:@localhost:1521:xe</driver-url> <driver-class>oracle.jdbc.driver.OracleDriver</driver-class> <statistics>1m,15m,1d</statistics> <driver-properties> <property name="user" value="hosf" /> <property name="password" value="hosf" /> </driver-properties> <house-keeping-sleep-time>90000 </house-keeping-sleep-time> <maximum-new-connections>20</maximum-new-connections> <prototype-count>5</prototype-count> <maximum-active-time>3600000</maximum-active-time> <maximum-connection-count>100</maximum-connection-count> <minimum-connection-count>10</minimum-connection-count> <trace>true</trace> <verbose>true</verbose> <house-keeping-test-sql>select sysdate from dual</house-keeping-test-sql> </proxool> </something-else-entirely>

2)hibernate配置
在JAVA工程src目录下创建Application-hibernate.xml,添下如下配置
<?xml version="1.0" encoding="UTF-8"?> <!--添加模式文件--> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:security="http://www.springframework.org/schema/security" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"> <!--添加session-factory--> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <!-- 自动实现实体类的扫描 --> <property name="packagesToScan" value="com.hand.**.domain" /> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect"> org.hibernate.dialect.Oracle9Dialect </prop> <prop key="hibernate.show_sql">false</prop> <prop key="hibernate.connection.autocommit"> true</prop> <prop key="hibernate.cglib.use_reflection_optimizer"> true</prop> <prop key="hibernate.connection.provider_class"> org.hibernate.connection.ProxoolConnectionProvider </prop> <prop key="hibernate.proxool.pool_alias">test</prop> <prop key="hibernate.proxool.xml">proxool.xml</prop> <!-- 缓存设置默认是EhCache --> <prop key="hibernate.cache.provider_class"> org.hibernate.cache.EhCacheProvider </prop> <!-- enable the query cache --> <prop key="hibernate.cache.use_query_cache"> true</prop> <!--store the second-level cache entries in a more human-friendly format--> <prop key="hibernate.cache.use_structured_entries"> true</prop> </props> </property> </bean> <!--事务处理配置--> <!-- 进行事务性控制时使用 --> <tx:annotation-driven transaction-manager="transactionManager" /> <!-- 定义事务管理器(声明式的事务) --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTrans actionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean>

3)配置web.xml

在上一篇中提到web.xml中配置了初始化时加载的文件,在添加了hibernate配置后,同样需要将其添加到web.xml的初始化文件列表中,

修改web.xml中的相关配置:
<context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath:ApplicationContext.xml, classpath:Application-Flex.xml, classpath:Application-hibernate.xml </param-value> </context-param>

三、数据库对象映射配置
<!-- [if gte mso 9]><xml> <w:WordDocument> <w:View>Normal</w:View> <w:Zoom>0</w:Zoom> <w:PunctuationKerning/> <w:DrawingGridVerticalSpacing>7.8 磅</w:DrawingGridVerticalSpacing> <w:DisplayHorizontalDrawingGridEvery>0</w:DisplayHorizontalDrawingGridEvery> <w:DisplayVerticalDrawingGridEvery>2</w:DisplayVerticalDrawingGridEvery> <w:ValidateAgainstSchemas/> <w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid> <w:IgnoreMixedContent>false</w:IgnoreMixedContent> <w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText> <w:Compatibility> <w:SpaceForUL/> <w:BalanceSingleByteDoubleByteWidth/> <w:DoNotLeaveBackslashAlone/> <w:ULTrailSpace/> <w:DoNotExpandShiftReturn/> <w:AdjustLineHeightInTable/> <w:BreakWrappedTables/> <w:SnapToGridInCell/> <w:WrapTextWithPunct/> <w:UseAsianBreakRules/> <w:DontGrowAutofit/> <w:UseFELayout/> </w:Compatibility> <w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel> </w:WordDocument> </xml><![endif]--><!-- [if gte mso 9]><xml> <w:LatentStyles DefLockedState="false" LatentStyleCount="156"> </w:LatentStyles> </xml><![endif]--><!-- /* Font Definitions */ @font-face {font-family:宋体; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-alt:SimSun; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 135135232 16 0 262145 0;} @font-face {font-family:"Book Antiqua"; panose-1:2 4 6 2 5 3 5 3 3 4; mso-font-charset:0; mso-generic-font-family:roman; mso-font-pitch:variable; mso-font-signature:647 0 0 0 159 0;} @font-face {font-family:"\@宋体"; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 135135232 16 0 262145 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; mso-pagination:widow-orphan; mso-layout-grid-align:none; punctuation-wrap:simple; text-autospace:none; font-size:10.0pt; font-family:"Book Antiqua"; mso-fareast-font-family:宋体; mso-bidi-font-family:"Times New Roman";} /* Page Definitions */ @page {mso-page-border-surround-header:no; mso-page-border-surround-footer:no;} @page Section1 {size:612.0pt 792.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:36.0pt; mso-footer-margin:36.0pt; mso-paper-source:0;} div.Section1 {page:Section1;} --><!-- [if gte mso 10]> <mce:style><!-- /* Style Definitions */ table.MsoNormalTable {mso-style-name:普通表格; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-parent:""; mso-padding-alt:0cm 5.4pt 0cm 5.4pt; mso-para-margin:0cm; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:10.0pt; font-family:"Times New Roman"; mso-fareast-font-family:"Times New Roman"; mso-ansi-language:#0400; mso-fareast-language:#0400; mso-bidi-language:#0400;} --><!-- [endif]--> 项目中使用 Hibernate 管理 JAVA 类到数据库表的映射,它可以实现 ORM(Object Relational Mapping) ,将关系数据库中表的数据映射成对象。

1)创建数据库对象
通过以下脚本创建数据库对象
-- Create table create table FWK.FWK_USERS ( USER_ID NUMBER not null, USER_NAME VARCHAR2(100) not null, USER_PASSWORD VARCHAR2(240), USER_DESCRIPTION VARCHAR2(240), EMAIL_ADDRESS VARCHAR2(240), START_DATE_ACTIVE DATE, END_DATE_ACTIVE DATE, OBJECT_VERSION_NUMBER NUMBER, CREATED_BY NUMBER not null, CREATION_DATE DATE not null, LAST_UPDATED_BY NUMBER not null, LAST_UPDATE_DATE DATE not null ); create unique index FWK_USERS_PK on fwk_users(USER_ID); create sequence fwk_users_s start with 1000;

2)创建Who字段映射类
如果你接触过ORACLE数据库,相信对WHO字段应该很熟悉了吧,这里就不多做解释了。本例中将WHO字段的映射独立出来,这样对所有的数据库映射类都能同样使用,而不用重复相同的代码。
在src下创建package com.common.domain,创建BaseWhoEntity.java
package com.common.domain; import java.io.Serializable; import java.util.Date; import javax.persistence.Column; import javax.persistence.MappedSuperclass; @MappedSuperclass public class BaseWhoEntity implements Serializable{ // DataType:NUMBER @Column(name = "OBJECT_VERSION_NUMBER", nullable = true) private Long objectVersionNumber; // DataType:NUMBER @Column(name = "CREATED_BY", nullable = false) private Long createdBy; // DataType:DATE @Column(name = "CREATION_DATE", nullable = false) private Date creationDate; // DataType:NUMBER @Column(name = "LAST_UPDATED_BY", nullable = false) private Long lastUpdatedBy; // DataType:DATE @Column(name = "LAST_UPDATE_DATE", nullable = false) private Date lastUpdateDate; public Long getObjectVersionNumber() { return objectVersionNumber; } public void setObjectVersionNumber(Long objectVersionNumber) { this.objectVersionNumber = objectVersionNumber; } public Long getCreatedBy() { return createdBy; } public void setCreatedBy(Long createdBy) { this.createdBy = createdBy; } public Date getCreationDate() { return creationDate; } public void setCreationDate(Date creationDate) { this.creationDate = creationDate; } public Long getLastUpdatedBy() { return lastUpdatedBy; } public void setLastUpdatedBy(Long lastUpdatedBy) { this.lastUpdatedBy = lastUpdatedBy; } public Date getLastUpdateDate() { return lastUpdateDate; } public void setLastUpdateDate(Date lastUpdateDate) { this.lastUpdateDate = lastUpdateDate; } }

3)创建数据库实体类
在创建完数据库表FwkUsers后,我们需要创建与之对应的JAVA实体类,通过Hibernate的annotation实现对象映射
在JAVA工程src下创建package com.admin.domain,创建FrameworkUser.java
package com.admin.domain; import java.util.Date; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.SequenceGenerator; import javax.persistence.Table; import com.common.domain.BaseWhoEntity; @Entity @Table(name = "FWK_USERS") public class FrameworkUser extends BaseWhoEntity{ // DataType:NUMBER @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "FWK_USERS_S") @SequenceGenerator(name = "FWK_USERS_S", sequenceName = "FWK_USERS_S") @Column(name = "USER_ID", nullable = false) private Long userId; // DataType:VARCHAR2 @Column(name = "USER_NAME", nullable = false, length = 100) private String userName; // DataType:VARCHAR2 @Column(name = "USER_PASSWORD", nullable = true, length = 240) private String userPassword; // DataType:VARCHAR2 @Column(name = "USER_DESCRIPTION", nullable = true, length = 240) private String userDescription; // DataType:VARCHAR2 @Column(name = "EMAIL_ADDRESS", nullable = true, length = 240) private String emailAddress; // DataType:DATE @Column(name = "START_DATE_ACTIVE", nullable = true) private Date startDateActive; // DataType:DATE @Column(name = "END_DATE_ACTIVE", nullable = true) private Date endDateActive; public Long getUserId() { return userId; } public void setUserId(Long userId) { this.userId = userId; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getUserPassword() { return userPassword; } public void setUserPassword(String userPassword) { this.userPassword = userPassword; } public String getUserDescription() { return userDescription; } public void setUserDescription(String userDescription) { this.userDescription = userDescription; } public String getEmailAddress() { return emailAddress; } public void setEmailAddress(String emailAddress) { this.emailAddress = emailAddress; } public Date getStartDateActive() { return startDateActive; } public void setStartDateActive(Date startDateActive) { this.startDateActive = startDateActive; } public Date getEndDateActive() { return endDateActive; } public void setEndDateActive(Date endDateActive) { this.endDateActive = endDateActive; } }

4)创建对象扫描类
项目中使用Hibernate映射数据库对象,在做CUDI(Create、Update、Delete、Insert)时希望能够通过对象名自动找到对应的DAO进行事务处理。
在JAVA工程src目录下创建package com.common.util,创建ExtSpringPackageScan.java
package com.common.util; import java.util.ArrayList; import java.util.List; import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.io.support.ResourcePatternResolver; import org.springframework.core.type.classreading.CachingMetadataReaderFactory; import org.springframework.core.type.classreading.MetadataReader; import org.springframework.core.type.classreading.MetadataReaderFactory; import org.springframework.util.ClassUtils; public class ExtSpringPackageScan { static ResourcePatternResolver resourcePatternResolver=new PathMatchingResourcePatternResolver(); public static List<String> getClasses(final String[] packagesToScan){ List<String> classNames=new ArrayList<String>(); if(packagesToScan != null) try { int len = packagesToScan.length; for(int i = 0; i < len; i++) { String pkg =packagesToScan[i]; String pattern = (new StringBuilder()).append("classpath*:").append(ClassUtils.convertClassNameToResourcePath(pkg)).append("**/*.class").toString(); Resource resources[] = resourcePatternResolver.getResources(pattern); MetadataReaderFactory readerFactory = new CachingMetadataReaderFactory(resourcePatternResolver); Resource arr$[] = resources; int len$ = arr$.length; for(int i$ = 0; i$ < len$; i$++) { Resource resource = arr$[i$]; if(!resource.isReadable()) continue; MetadataReader reader = readerFactory.getMetadataReader(resource); String className = reader.getClassMetadata().getClassName(); classNames.add(className); } } } catch(Exception ex) { ex.printStackTrace(); } return classNames; } }

四、DAO设计
DAO层的设计采用的是泛型设计。泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率。

1)DAO接口设计
在JAVA 工程src下创建package com.common.hibernate,创建GenericDao.java
package com.common.hibernate; import java.io.Serializable; import java.lang.reflect.InvocationTargetException; import java.util.List; import java.util.Map; import org.springframework.orm.hibernate3.HibernateCallback; public interface GenericDao<T, PK extends Serializable> { public PK save(T value) throws Exception; public T get(PK id, Class<T> klass); public T beforeSave(T value) throws Exception; }

2)DAO接口实现
在JAVA工程com.common.hibernate下创建GenericDaoImpl.java
package com.common.hibernate; import java.io.Serializable; import java.math.BigDecimal; import java.sql.SQLException; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.beanutils.BeanUtils; import org.apache.log4j.Logger; import org.hibernate.Criteria; import org.hibernate.HibernateException; import org.hibernate.Query; import org.hibernate.SQLQuery; import org.hibernate.Session; import org.hibernate.criterion.Example; import org.hibernate.criterion.Projections; import org.perf4j.aop.Profiled; import org.springframework.orm.hibernate3.HibernateCallback; import org.springframework.orm.hibernate3.support.HibernateDaoSupport; import com.common.domain.BaseWhoEntity; public class GenericDaoImpl<T, PK extends Serializable> extends HibernateDaoSupport implements GenericDao<T, PK> { public T beforeSave(T value) throws Exception { if (value instanceof BaseWhoEntity) { BaseWhoEntity temp = (BaseWhoEntity) value; Map map = new HashMap(); map.put("createdBy", new Long(7)); map.put("creationDate", new Date()); map.put("lastUpdatedBy", new Long(7)); map.put("lastUpdateDate", new Date()); map.put("objectVersionNumber", new Long(1)); try { BeanUtils.populate(value, map); } catch (Exception e) { logger.error("将Map转化为对像时出错", e); throw e; } } return value; } @Profiled(tag = "GenericDaoImpl.save") public PK save(T value) throws Exception { try { System.out.println("执行保存!"); return (PK) this.getHibernateTemplate().save(beforeSave(value)); } catch (Exception e) { throw e; } } @Profiled(tag = "GenericDaoImpl.get") @SuppressWarnings("unchecked") public T get(PK id, Class<T> klass) { return (T) getHibernateTemplate().get(klass, id); } }

五、Service设计
通过设计Service层,实现与FLEX之间的数据传递。

1)在JAVA 工程src下创建package com.common.service,创建GenericService.java
package com.common.hibernate; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hibernate.SessionFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.orm.hibernate3.HibernateCallback; import com.common.util.ExtSpringPackageScan; public class GenericService implements InitializingBean { private static final Log logger = LogFactory.getLog(GenericService.class); private SessionFactory sessionFactory; private String[] packagesToScan; @SuppressWarnings("unchecked") private Map<String, GenericDao> daoMap = new HashMap<String, GenericDao>(); private List<String> classList = new ArrayList<String>(); public Map<String, GenericDao> getDaoMap() { return daoMap; } public void setDaoMap(Map<String, GenericDao> daoMap) { this.daoMap = daoMap; } public String[] getPackagesToScan() { return packagesToScan; } public void setPackagesToScan(String[] packagesToScan) { this.packagesToScan = packagesToScan; } @SuppressWarnings("unchecked") public void afterPropertiesSet() throws Exception { classList.addAll(ExtSpringPackageScan.getClasses(packagesToScan)); StringBuffer sb = new StringBuffer(); for (String className : classList) sb.append(className + ","); logger.info("初始化完成Pojo与表的映射:" + sb.toString()); logger.info("初始化完成DaoMap:" + daoMap); } public SessionFactory getSessionFactory() { return sessionFactory; } public void setSessionFactory(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } @SuppressWarnings("unchecked") public <T, PK> PK save(T value) throws Exception { try { GenericDao gd = getDao(value.getClass().getName()); if (gd != null) { return (PK) gd.save(value); } else { logger.error("保存错误,无法找到相应的DAO来处理,请确认配置信息是否正确!"); return null; } } catch (Exception e) { throw e; } } public String getClass(String className) { for (String classInList : classList) { if (classInList.endsWith(className) || classInList.equals(className)) return classInList; } return null; } @SuppressWarnings("unchecked") public GenericDao getDao(String fullClassName) { GenericDao gd = null; if (daoMap.get(fullClassName) == null) { logger.debug("使用缺省的Dao"); gd = daoMap.get("default"); } else { gd = daoMap.get(fullClassName); logger.debug("使用Dao:" + gd.getClass().getName()); } return gd; } @SuppressWarnings("unchecked") public <T, PK extends Serializable> T get(PK id, String className) { try { String fullClassName = getClass(className); Class<T> klass = (Class<T>) Class.forName(fullClassName); GenericDao gd = getDao(fullClassName); return (T) gd.get(id, klass); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (NullPointerException ne) { logger.error("传入类型:" + className + "不存在!"); ne.printStackTrace(); } return null; } }

2)创建具体应用类BaseService.java
在JAVA工程com.common.service下创建BaseService.java
package com.common.service; import java.util.Date; import java.util.Map; import org.apache.commons.beanutils.BeanUtils; import org.apache.commons.beanutils.ConvertUtils; import org.apache.commons.beanutils.PropertyUtilsBean; import org.apache.commons.beanutils.converters.DateConverter; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import com.common.hibernate.GenericService; public class BaseService { GenericService genericService; private PropertyUtilsBean pb = new PropertyUtilsBean(); static { ConvertUtils.deregister(Date.class); DateConverter dateConverter = new DateConverter(null); ConvertUtils.register(dateConverter, Date.class); } public GenericService getGenericService() { return genericService; } public void setGenericService(GenericService genericService) { this.genericService = genericService; } @Transactional(propagation = Propagation.SUPPORTS) @SuppressWarnings("unchecked") public Map save(Map map) throws Exception { try { if (map.get("className") != null) { Object value = this.popMapToObject(map); genericService.save(value); return pb.describe(value); } } catch (Exception e) { e.printStackTrace(); throw e; } return null; } public Object popMapToObject(Map proerties) throws Exception { System.out.println("组装POJO参数:" + proerties); if (proerties.get("className") != null) { String className = (String) proerties.get("className"); Object value = Class.forName(genericService.getClass(className)).newInstance(); BeanUtils.populate(value, proerties); System.out.println("组装后的class:" + BeanUtils.describe(value)); return value; } return null; } }

3)完成DAO与Service层的设计后,需要修改hibernate配置
修改Application-hibernate.xml,添加如下配置:
<!-- Hibernate用通用数据库操作服务 --> <bean id="genericService" class="com.hand.common.hibernate.GenericService"> <property name="sessionFactory"> <ref bean="sessionFactory" /> </property> <property name="packagesToScan"> <list> <value>com.hand.**.domain</value> </list> </property> <property name="daoMap"> <map> <entry key="default"> <ref bean="defaultDAO" /> </entry> </map> </property> </bean> <!-- Hibernate用核心数据库操作服务 --> <bean id="defaultDAO" class="com.hand.common.hibernate.GenericDaoImpl"> <property name="sessionFactory"> <ref bean="sessionFactory" /> </property> </bean>

六、远程服务应用
1)发布BaseService
修改Application-Flex.xml,添加如下配置:
<bean id="BaseService" class="com.hand.common.service.BaseService"> <property name="genericService" ref="genericService"/> <!-- 公布给Flex使用 --> <flex:remoting-destination /> </bean>

2)FLEX引用BaseService
修改FLEX工程remoting-config.xml,添加如下配置:
<destination id="BaseService"> <properties> <source>BaseService</source> </properties> </destination>

3)创建UserModule.mxml
在FLEX工程src/modules下创admin目录,创建UserModule.mxml,通过RemoteObject调用远程服务
<?xml version="1.0" encoding="utf-8"?> <mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="400" height="300"> <mx:Script> <!--[CDATA[ import mx.rpc.events.ResultEvent; import mx.controls.Alert; private var saveBaseParams:Object = new Object(); private function saveRecord():void{ saveBaseParams.className = 'FrameworkUser'; saveBaseParams['userName'] = username.text; saveBaseParams['userPassword'] = password.text; saveBaseParams['emailAddress'] = email.text; BaseService.save(saveBaseParams); BaseService.save.addEventListener(ResultEvent.RESULT ,saveHandler); } private function saveHandler(evt:ResultEvent):void{ BaseService.save.removeEventListener(ResultEvent.RES ULT,saveHandler); var obj:Object = evt.result as Object; Alert.show(obj['userName']+' 保存成功!'); } ]]--> </mx:Script> <mx:RemoteObject id="BaseService" destination="BaseService"/> <mx:VBox width="50%" left="43" top="90"> <mx:FormItem label="User Name:" width="100%" labelWidth="100"> <mx:TextInput width="200" id="username"/> </mx:FormItem> <mx:FormItem label="Password:" width="100%" labelWidth="100"> <mx:TextInput width="200" id="password" displayAsPassword="true"/> </mx:FormItem> <mx:FormItem label="Email:" width="100%" labelWidth="100"> <mx:TextInput width="200" id="email"/> </mx:FormItem> <mx:HBox width="100%"> <mx:Spacer width="100%"/> <mx:Button label="保存" width="80" click="saveRecord()" x="761" y="277" cornerRadius="9"/> </mx:HBox> </mx:VBox> </mx:Module>

4)修改Index.mxml,添加如下内容:
<mx:ModuleLoader url="../admin/UserModule.swf" width="50%" height="50%"/>

七、编译运行
1)编译FLEX工程
选择Project—>Clean—>TestProject
2)拷贝编译目录bin-debug/modules到JAVA工程WebRoot下
3)启动本地数据库
4)启动Tomcat服务器
5)服务器正常启动后,在浏览器中输入地址(其中9090为服务器端口)
http://localhost:9090/TestProject/modules/common/Index.html

运行结果如下:
首页:

保存数据,检查JAVA与FLEX通信是否正常:

访问数据库,检查数据是否保存成功: