本节通过按步骤详细解释Marmot的core项目,带领读者一步步从配置数据源开始看清Marmot框架的配置方法和运行机制。
示例演示说明
在前面完成Marmot的core项目导入配置之后,启动Server服务(本例是Tomcat应用服务器)。通过【Browse】打开employee.jsp页面,点击【Query】执行查询查看效果。
图18-08
本例中的数据持久层采用iBatis实现,关于iBatis框架的相关使用请参考相关资料。现在我们就从点击了【Query】之后开始认识Marmot之旅。
配置数据源
毋庸置疑,我们首先要做的还是配置数据源,此处数据源的配置主要为iBatis服务。在core\web\WEB-INF\configs目录下的jdbc.properties文件中,配置数据库连接属性。
jdbc.url=jdbc\:hsqldb\:file:D\: marmot/sample/data/marmot-sample jdbc.username=sa jdbc.password= jdbc.driverClassName=org.hsqldb.jdbcDriver
图18-09
配置iBatis和DAO
- iBatis在Spring中的配置
Spring中提供了iBatis框架集成的接口,使得我们不需要单独去创建iBatis配置文件,这一切在Spring中配置即可。在同样的configs目录中,由base-context.xml负责配置。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <!-- DataSource --> <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>WEB-INF/configs/jdbc.properties</value> <!-- 加载JDBC配置文件 --> </list> </property> </bean> <!-- 配置dataSource数据源对象 --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${jdbc.driverClassName}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </bean> <!-- Transaction 配置事务--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource"> <ref bean="dataSource" /> </property> </bean> <bean id="txProxyTemplate" abstract="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="proxyTargetClass"> <value>true</value> </property> <property name="transactionManager"> <ref bean="transactionManager" /> </property> <property name="transactionAttributes"> <props> <prop key="get*">PROPAGATION_REQUIRED,readOnly,ISOLATION_DEFAULT,-Exception</prop> <prop key="query*">PROPAGATION_REQUIRED,readOnly,ISOLATION_DEFAULT,-Exception</prop> <prop key="calc*">PROPAGATION_REQUIRED,readOnly,ISOLATION_DEFAULT,-Exception</prop> <prop key="find*">PROPAGATION_REQUIRED,readOnly,ISOLATION_DEFAULT,-Exception</prop> <prop key="search*">PROPAGATION_REQUIRED,readOnly,ISOLATION_DEFAULT,-Exception</prop> <prop key="*">PROPAGATION_SUPPORTS,ISOLATION_DEFAULT,-Exception</prop> </props> </property> </bean> <!-- Hibernate 配置Hibernate持久层--> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource"> <ref local="dataSource" /> </property> <property name="mappingResources"> <list> <value>sample/dao/hibernate/Branch.hbm.xml</value> <value>sample/dao/hibernate/Dept.hbm.xml</value> <value>sample/dao/hibernate/Employee.hbm.xml</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop> <prop key="hibernate.show_sql">true</prop> </props> </property> </bean> <!-- iBatis 配置iBatis持久层--> <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"> <property name="configLocation"> <value>classpath:/sample/dao/ibatis/sqlmap-config.xml</value> </property> <property name="dataSource"> <ref bean="dataSource" /> </property> </bean> </beans>
base-context.xml文件中配置信息
图18-10
配置说明图01
- 在base-context.xml中配置dataSource,引用jdbc.properties中的配置信息(图①)。
- 配置声明式事务(图②)。
- 配置DAO
在core项目中,configs目录下的ibatis-dao-context.xml中配置Spring中的sqlMapDAOTemplatet及执行数据访问的DAO。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="sqlMapDAOTemplate" abstract="true" class="org.springframework.orm.ibatis.support.SqlMapClientDaoSupport"> <property name="sqlMapClient"> <ref bean="sqlMapClient"/> </property> </bean> <bean id="branchDAO" class="sample.dao.ibatis.BranchDAOImpl" parent="sqlMapDAOTemplate"/> <bean id="deptDAO" class="sample.dao.ibatis.DeptDAOImpl" parent="sqlMapDAOTemplate"/> <bean id="employeeDAO" class="sample.dao.ibatis.EmployeeDAOImpl" parent="sqlMapDAOTemplate"/> </beans>
ibatis-dao-context.xml文件中配置信息
图18-11
在bo-context.xml中配置事务代理。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="branchManager" parent="txProxyTemplate"> <property name="target"> <bean class="sample.bo.BranchManager"> <property name="branchDAO"> <ref bean="branchDAO"/> </property> </bean> </property> </bean> <bean id="deptManager" parent="txProxyTemplate"> <property name="target"> <bean class="sample.bo.DeptManager"> <property name="deptDAO"> <ref bean="deptDAO"/> </property> </bean> </property> </bean> <bean id="employeeManager" parent="txProxyTemplate"> <property name="target"> <bean class="sample.bo.EmployeeManager"> <property name="employeeDAO"> <ref bean="employeeDAO"/> </property> </bean> </property> </bean> </beans>
bo-context.xml中配置信息
图18-12
配置说明图02
- 在ibatis-dao-context.xml中配置sqlMapDAOTemplate和DAO(图中③所示)。
- 配置声明式事务代理DAO(图中④⑤)。
MarmotDataset和dataProvider
在dorado的Dataset数据集中,MarmotDataset属于Marmot框架在ViewModel中的专属数据集对象。打开core项目中视图模型Employee。步骤:【core】—>【src】—>【sample】—>【dorado】—>【Employee】。
图18-13
MarmotDataset与其他Dataset不同之处在于它在数据加载的时候,并不需要调用doLoadData方法,也不需要在ViewModel的实现类或Dataset的监听器中控制加载。而是通过MarmotDataset的dataProvider属性的配置,实现了数据加载的外部化,经由DAO返回的数据加载至MarmotDataset中并最终通过dorado的数据展现控件进行页面展现,这些原本分离的业务处理通过Spring的IOC机制可以全部被"装配"在一起。
- dataProvider属性
dataProvider属性是MarmotDataset特有的属性。该属性指定了MarmotDataset执行数据加载的时候需要的JavaBean对象在Spring配置中的BeanID。
- method属性
MarmotDataset中的method属性指定了调用的数据加载方法名。当多个MarmotDataset的dataProvider属性值指定的BeanID相同时(即都是同一个JavaBean处理数据的加载),不同的MarmotDataset可以通过method属性的不同执行各自的数据加载方法,即通过method属性实现数据加载的方法分派。这使得只需要一个JavaBean就可以实现多个MarmotDataset的数据加载,管理更简洁方便。
- ObjectClazz属性
该属性指定了MarmotDataset数据集的类型,属性值通常是一个POJO。
MarmotUpdateCommand和dataResolver
MarmotUpdateCommand和MarmotRPCCommand两个命令控件类似于UpdateCommand和RPCCommand命令控件,不同之处在于前者是Marmot的专属命令控件。在视图模型Employee中查看MarmotUpdateCommand命令控件。
图18-14
MarmotUpdateCommand命令中其他的属性与UpdateCommand类似,而其中的resolver属性概念类似于MarmotDataset的dataProvider属性。
- resolver属性
该属性指定了MarmotUpdateCommand执行提交由DatasetInfo中指定的MarmotDataset时需要的JavaBean对象在Spring配置中的BeanID。
- method属性
该属性指定了处理由客户端发起的AJAX请求的JavaBean中的方法名。当resolver属性值相同而method值不同时,不论是MarmotUpdateCommand命令提交了Dataset数据集对象还是MarmotRPCComamnd命名的远程调用,利用method属性实现方法分派可以使得这些请求被同一个JavaBean中不同的方法处理。默认情况下,如果此项为空,则会调用execute方法。
使用Spring配置关联
Marmot中的数据处理,例如第一次数据加载、不同条件下的查询结果集加载、修改数据后的提交保存等等,需要编写与之对象的业务逻辑处理代码。在本例中,我们讲解的逻辑处理代码有两部分。打开EmployeeDataProvider.java文件查看数据加载的处理代码。步骤:【core】—>【src】—>【sample】—>【view】—>【EmployeeDataProvider.java】。
package sample.view; import java.util.Map; import org.apache.commons.lang.BooleanUtils; import org.marmot.view.DataSet; import sample.bo.EmployeeManager; import sample.bo.Page; import sample.model.Employee; public class EmployeeDataProvider { private EmployeeManager employeeManager; public void setEmployeeManager(EmployeeManager employeeManager) { this.employeeManager = employeeManager; } public EmployeeManager getEmployeeManager() { return employeeManager; } public void getEmployee(DataSet dataSet) throws Exception { Map parameters = (Map) dataSet.getParameters(); String id = (String) (parameters).get("id"); Employee employee = employeeManager.getEmployee(id); if (employee != null) { dataSet.addRecord(employee); } } public void getEmployeesByDept(DataSet dataSet) throws Exception { Map parameters = (Map) dataSet.getParameters(); String deptId = (String) (parameters).get("deptId"); dataSet.addRecords(employeeManager.getEmployeesByDept(deptId)); } public void query(DataSet dataSet) throws Exception { /** 整理查询条件 */ Map parameters = (Map) dataSet.getParameters(); String value; value = (String) parameters.get("sex"); if (value != null && value.length() > 0) { parameters.put("sex", BooleanUtils.toBooleanObject(value)); } else { parameters.remove("sex"); } value = (String) parameters.get("married"); if (value != null && value.length() > 0) { parameters.put("married", BooleanUtils.toBooleanObject(value)); } else { parameters.remove("married"); } /** 调用业务逻辑 */ Page page = employeeManager.getEmployees((Map) dataSet.getParameters(), dataSet.getPageIndex(), dataSet.getPageSize()); /** 添加数据 */ dataSet.addRecords(page.getList()); /** 指定总记录数 */ dataSet.setRecordCount(page.getTotalCount()); } }
EmployeeDataProvider.java中的数据加载代码
图18-15
同样在【view】目录下打开EmployeeDataResolver.java文件查看提交Dataset数据集处理的代码。
package sample.view; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import org.marmot.view.DataResolver; import org.marmot.view.DataSet; import sample.bo.EmployeeManager; import sample.model.Employee; public class EmployeeDataResolver implements DataResolver { private EmployeeManager employeeManager; public void setEmployeeManager(EmployeeManager employeeManager) { this.employeeManager = employeeManager; } public EmployeeManager getEmployeeManager() { return employeeManager; } public Object execute(Map dataSetMap, Object parameter) throws Exception { return saveAll(dataSetMap, parameter); } public Object saveAll(Map dataSetMap, Object parameter) throws Exception { DataSet datasetEmployee = (DataSet) dataSetMap.get("datasetEmployee"); Collection employees; employees = datasetEmployee.getRecords(DataSet.DELETED); for (Iterator iter = employees.iterator(); iter.hasNext();) { Employee employee = (Employee) iter.next(); employeeManager.delete(employee); } employees = datasetEmployee.getRecords(DataSet.MODIFIED); for (Iterator iter = employees.iterator(); iter.hasNext();) { Employee employee = (Employee) iter.next(); employeeManager.update(employee); } employees = datasetEmployee.getRecords(DataSet.NEW); for (Iterator iter = employees.iterator(); iter.hasNext();) { Employee employee = (Employee) iter.next(); employeeManager.create(employee); } return null; } public Object deleteSelected(Map dataSetMap, Object parameter) throws Exception { DataSet datasetEmployee = (DataSet) dataSetMap.get("datasetEmployee"); int count = 0; Collection employees = datasetEmployee.getRecords(); for (Iterator iter = employees.iterator(); iter.hasNext();) { Employee employee = (Employee) iter.next(); employeeManager.delete(employee); datasetEmployee.setRecordState(employee, DataSet.DELETED); count++; } Map outParameters = new HashMap(); outParameters.put("$message", count + " employee(s) deleted!"); return outParameters; } public Object raiseSalary(Map dataSetMap, Object parameter) throws Exception { DataSet datasetEmployee = (DataSet) dataSetMap.get("datasetEmployee"); Employee employee = (Employee) datasetEmployee.getRecords().iterator() .next(); float originalSalary = employee.getSalary(); float newSalary = originalSalary + 500; employee.setSalary(newSalary); employeeManager.update(employee); Map outParameters = new HashMap(); outParameters.put("$message", employee.getName() + "'s salary raised from " + originalSalary + " to " + newSalary + " !"); return outParameters; } }
EmployeeDataResolver.java中的数据处理代码
图18-16
在configs目录下的view-context.xml文件中定义了ViewModel中的MarmotDataset和MarmotUpdateCommand与其对应的JavaBean相关联的信息。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="branchDataProvider" class="sample.view.BranchDataProvider"> <property name="branchManager"> <ref bean="branchManager" /> </property> </bean> <bean id="deptDataProvider" class="sample.view.DeptDataProvider"> <property name="deptManager"> <ref bean="deptManager" /> </property> </bean> <bean id="employeeDataProvider" class="sample.view.EmployeeDataProvider"> <property name="employeeManager"> <ref bean="employeeManager" /> </property> </bean> <bean id="employeeDataResolver" parent="txProxyTemplate"> <property name="target"> <bean class="sample.view.EmployeeDataResolver"> <property name="employeeManager"> <ref bean="employeeManager" /> </property> </bean> </property> </bean> <bean id="testRPCResolver" class="sample.view.TestRPCResolver" /> </beans>
view-context.xml中的配置信息
图18-17
配置说明图03
- MarmotUpdateCommand的DatasetInfo指定了需要提交的MarmotDataset。可以新建多个DatasetInfo实现一次提交多个MarmotDataset(图①)。
- MarmotDataset的dataProvider属性指定了需要处理数据加载的Java类的BeanID。在view-cnotext.xml中配置(图②)。
- MarmotDataset的method属性指定了处理数据加载的Java类中实际进行处理的方法名(图③)。
- MarmotUpdateCommand的resolver属性指定了需要处理被提交的数据集对象的Java类的BeanID。在view-context.xml中配置(图④)。
- MarmotupdateCommand的method属性指定了处理被提交的数据集对象的Java类中实际进行处理的方法名。默认属性值为空时执行execute方法(图⑤)。
- 处理数据加载的EmployeeDataProvider类和处理被提交的数据集对象的EmployeeDataResolver类在view-context.xml中被装配(图⑥⑦)。
配置web.xml
在web.xml中还需要配置前面所提到的那些xml配置文件,实现应用服务器启动时加载,打开web.xml配置文件查看配置信息。 步骤:【core】—>【web】—>【WEB-INF】—>【web.xml】。
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4"> <!-- Spring Configures --> <context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/configs/base-context.xml, /WEB-INF/configs/marmot-base-context.xml, /WEB-INF/configs/ibatis-dao-context.xml, <!-- 用此行配置替换上一行可进行hibernate的测试 /WEB-INF/configs/hibernate-dao-context.xml, --> /WEB-INF/configs/bo-context.xml, /WEB-INF/configs/view-context.xml, </param-value> </context-param> <!-- Dorado Filter --> <filter> <filter-name>GZIPEncoder</filter-name> <filter-class>com.bstek.dorado.core.GZIPEncodeFilter</filter-class> </filter> <filter> <filter-name>dorado-filter</filter-name> <filter-class>com.bstek.dorado.core.DoradoFilter</filter-class> </filter> <filter-mapping> <filter-name>GZIPEncoder</filter-name> <url-pattern>*.jsp</url-pattern> </filter-mapping> <filter-mapping> <filter-name>dorado-filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- Spring Loader --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- Dorado Serlvet --> <servlet> <servlet-name>dorado-servlet</servlet-name> <servlet-class>com.bstek.dorado.core.DoradoServlet</servlet-class> <load-on-startup>3</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dorado-servlet</servlet-name> <url-pattern>*.d</url-pattern> </servlet-mapping> </web-app>
图18-18
Attachments:
worddava10af75377a11df75f6d8024aec34f26.png (image/png)
worddavf055c163be4ddb45b30cf16431001516.png (image/png)
worddavfa2344c4bd00b6fafb774d708388dc37.png (image/png)
worddav0e996e9bf58386ca22292ca9d79ddcc1.png (image/png)
worddav360390b58e4fb7e46ab0659a1d9accc3.png (image/png)
worddava25cf0bb8138067690ba181bc7733eb0.png (image/png)
worddava1862c1da7207208af64a5e5d74fa10a.png (image/png)
worddavcc1a357ff9552007ca3429c94bbb6ed4.png (image/png)
worddavf8d875b9b1014ba4f1d043f991bc9542.png (image/png)
worddav32a965c5267f99891ab874ac3d9b0099.png (image/png)
worddav0046b102ae169c6f0724d290e6084223.png (image/png)
worddavadf07cfc0d47493a62165ca98e399cf4.png (image/png)
worddavd299ed93ea6224fcf86cfcf52ff600a0.png (image/png)
worddavb8a368e9fe47914a5cb7411955f0d60c.png (image/png)