310 likes | 506 Views
JCF 数据通用操作开发框架. Java Command Framework Struts+Spring(SLSB)+Hibernate(SSH 版 ) 何文强 亿迅科技 2006.07. JCF 数据通用操作开发框架. 迅速开发出原型系统才能实现软件开发人员和用户的流畅沟通。 原有 JCF 框架代码臃肿,大量 try , catch 以及安全,事务方面的重复代码。
E N D
JCF数据通用操作开发框架 Java Command Framework Struts+Spring(SLSB)+Hibernate(SSH版) 何文强 亿迅科技 2006.07
JCF数据通用操作开发框架 • 迅速开发出原型系统才能实现软件开发人员和用户的流畅沟通。 • 原有JCF框架代码臃肿,大量try,catch以及安全,事务方面的重复代码。 • 引入EJB框架,提高了软件的可扩展性和可伸缩性,但是降低了开发效率,不利于测试,不能快速地开发出原型系统 。 • 如何在软件质量和开发效率两个矛盾中寻找到一个平衡点?从而快速且有质量地开发出原型系统?这正是本开发框架力图解决的问题。
纯Struts+EJB开发框架的缺点 • 无法快速开发出原型系统。 • Web层和EJB层存在过强的依赖性和耦合性。 • 不利于扩展和维护
基于模型Model驱动开发模式 • 一旦确定数据模型,该数据模型的增删改查功能可自动完成; • 如果需求变化,只要更改相应的数据模型。
Spring IOC • Inversion of Control,即反转模式,著名的好莱坞理论:你呆着别动,到时我会找你。 • 也称为Dependency Injection模式,将依赖关系先剥离,然后在适当时候再注射进入。 • IoC模式实现了调用者和被调用者之间关系在某处完全分离,目前解耦程度最高的模式。
Spring AOP • Authentication 权限Caching 缓存Context passing 内容传递Error handling 错误处理Lazy loading 懒加载Debugging 调试logging, tracing, profiling and monitoring 记录跟踪 优化 校准Performance optimization 性能优化Persistence 持久化Resource pooling 资源池Synchronization 同步Transactions 事务
Spring 抽象服务 • 支持JDBC • Hibernate • JDO • OJB • 远程调用 • Webservice • EJB • Mail • Spring MVC 其中对Hibernate的支持是一大亮点。
Hibernate 符合Java习惯的关系数据库持久化 • JDBCHibernate 是一种新的ORM映射工具,它同时提供了从Java 类到数据表的映射和数据查询、恢复等机制,实现数据层对象的持久性. 相对于使用JDBC 和SQL 来手工操作数据库,使用Hibernate ,可以大大减少操作数据库的工作量. Hibernate 可以和多种Web 服务器以及应用服务器良好集成. • QBC • HQL • JDBC
引入Spring 好处 • 极大的提高系统了可测试性,使用本地Datasource不用启动容器就进行测试,可以实现测试先行(TDD),部署到测试或者生产环境可以换用容器管理的Datasource 。 • 有效的减少了代码量(1/3),不用写try、catch和ServiceLocator、Singleton模式等,提高了开发效率。 • 拥有比EJB的CMT更好的声明式事务支持。 • 同时支持EJB和POJO两种调用模式,符合公司原来的开发习惯。 • Dao( Hibernate )用Spring来管理。 • Command交由Spring来管理,利用Spring AOP可以为Command实现安全和事务等服务,Command只关注于业务流程本身。
对EJB的支持 • publicabstractclass SessionFacade extends AbstractStatelessSessionBean{ • publicvoid setSessionContext(SessionContext ctx) { • super.setSessionContext(ctx); • setBeanFactoryLocator(ContextSingletonBeanFactoryLocator.getInstance( • "classpath*:beanRefContext.xml")); • setBeanFactoryLocatorKey("applicationContext-main"); • } • protectedvoid onEjbCreate() throws CreateException ; • } • ICommandObject command = ((ICommandObject)getBeanFactory().getBean(commandName[i]));
对分页的支持 • DetachedCriteria,可以脱离Hibernate环境在Web层构造动态的查询条件。 • CriteriaQuery封装对分页的支持。
Client • String curPage = "0"; • String myaction="cmsRight.do?";//struts Action • String myform="forms[0]"; //struts form • CriteriaQuery cq=new CriteriaQuery(CmsRight.class,curPage,myaction,myform); • cq.setPageSize(20); //每页记录数 • cq.addOrder("asc","rightId"); • cq.like("rightId","0%");//0 • cq.like("rightBox","r%");//1 • cq.add(cq.or(cq, 0, 1)); • PageSupport ps=BeanFactory.getBizDelegate().findRights(cq, state); • //采用QBC生成的SQL语句:select this_.right_id as right1_0_, this_.right_box as right2_0_0_, this_.right_desc as right3_0_0_, this_.right_url as right4_0_0_ from cms_right this_ where (this_.right_id like ? or this_.right_box like ?) order by this_.right_id asc limit ?
BizDelegate • public PageSupport findRights(CriteriaQuery cq, IState state) { • logger.debug("FindRights delegate."); • if (DelegateUtil.isNullParam(cq, "CriteriaQuery", state)) { • returnnull; • } • Request req = new Request(); • req.setCommandName(ServiceConsts.SERVICE_FIND_RIGHTS); • req.setValue(CriteriaQuery.class.getName(), cq); • try { • Response resp = getDelegate().execute(req); • DelegateUtil.setIState(state, resp); • return (PageSupport) (resp.getValue(PageSupport.class.getName())); • } catch (Exception e) { • DelegateUtil.handleException(e, "queryAccept", state); • } • returnnew PageSupport(); • }
AbstractBizDelegate • publicabstractclass AbstractBizDelegate • { • private DelegateType delegate; • publicvoid setDelegate(DelegateType delegate) { • this.delegate = delegate; • } • public DelegateType getDelegate() { • return delegate; • } • publicsynchronizedboolean init(String jndiName) • { • return delegate.init(jndiName); • } • }
BizDelegate 接口 • publicinterface DelegateType extends Serializable{ • publicboolean init(String jndiName); • public Response execute( Request request ) throws JCFException; • public Object execute(String paramName, Object paramValue,String[] commandName, String retParamName, IState state) throws JCFException; • public Object execute(String[] commandName,String retParamName, IState state) throws JCFException; • } • publicclass POJODelegate implements DelegateType • publicclass EjbDelegate implements DelegateType
ApplicationContext-Service.xml • <bean id="BizDelegate" class="com.gsta.bnet.bizservice.BizDelegate"> • <property name="delegate"> • <ref bean="POJODelegate" /> • </property> • </bean> • <bean id="POJODelegate" parent="baseTransactionProxy"> • <property name="target"> • <bean class="com.gsta.bnet.bizservice.POJODelegate"> • </bean> • </property> • </bean> • <bean id="EjbDelegate" parent="baseTransactionProxy"> • <property name="target"> • <bean class="com.gsta.bnet.bizservice.EjbDelegate"/> • </property> • </bean>
Spring 事务 • <bean id="baseTransactionProxy" • class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" • abstract="true" lazy-init="true"> • <property name="transactionManager" ref="transactionManager"/> • <property name="transactionAttributes"> • <props> • <prop key="save*">PROPAGATION_REQUIRED,-ClientException</prop> • <prop key="delete*">PROPAGATION_REQUIRED,-ClientException</prop> • <prop key="update*">PROPAGATION_REQUIRED,-ClientException</prop> • <prop key="find*">PROPAGATION_REQUIRED,readOnly,-ClientException</prop> • <prop key=“execute*”>PROPAGATION_REQUIRED,-JCFException,+XXXExeception</prop> • </props> • </property> • </bean>
POJODelegate • int i = 0; • for (; i < commandName.length; i++) { • ICommandObject command = (ICommandObject) ContextServiceLocator • .getInstance().getBean(commandName[i]); • try { • command.execute(params, response); • } • catch (JCFException jcfe) { • logger.debug("运行Command "+command +"时抛出JCFException异常"); • //break; • throw jcfe; • } • catch (Exception e) { • logger.debug("运行Command "+command +"时抛出Exception异常"); • break; • } • }
EJBDelegate • public Response execute(Request request) throws JCFException { • Response resp=null; • try { • SessionFacade sf=this.getSessionFacade(); • logger.debug("EjbDelegate execute,执行SessionBean的execute方法: "+sf); • resp=sf.execute(request); • } catch (Exception e) { • DelegateUtil.handleException(e, "execute", null); • e.printStackTrace(); • } • return resp; • }
Command Fightright • publicvoid execute(Map params, Map response) throws JCFException • { • logger.debug("SaveRights Command : "); • CriteriaQuery cq = (CriteriaQuery) params • .get(CriteriaQuery.class.getName()); • if (cq == null) { • String msg = "FindRights 数据库错误 ,CriteriaQuery is null"; • BizLog.error(msg); • thrownew JCFException(ErrorCode.PARAM_ERR, msg); • } • PageSupport ps = (PageSupport)dao.find(cq,true); • response.put(PageSupport.class.getName(), ps); • }
Command 在Spring中的配置 • <bean id="FindRights" class="com.gsta.bnet.bizservice.command.FindRights"> • <property name="dao"> • <ref bean="BaseDao" /> • </property> • </bean> • 设值子接入 • private BaseDao dao; • publicvoid setDao(BaseDao dao) { • this.dao = dao; • }
Dao 在Spring中的配置 • <bean id="BaseDao" class="com.gsta.bnet.common.dao.BaseDao"> • <property name="sessionFactory"> • <ref bean="sessionFactory" /> • </property> • </bean>
publicinterface Dao { • publicabstractvoid update(Object o); • publicabstractvoid delete(Object o); • publicabstractvoid saveOrUpdate(Object o); • publicabstractvoid delete(String fullEntityName, String id); • publicabstractvoid save(Object o); • publicabstractboolean delete(Class c, String id); • publicabstract Object loadById(Class c, Serializable id); • publicabstract Object getById(Class c, Serializable id); • publicabstract List findAll(Class entity); • publicabstract List find(String strHQL); • publicabstract List find(final String strHQL, finalint offset, • finalint limit); • publicabstract PageSupport find(final HqlQuery hqlquery); // HqlQuery • publicabstract PageSupport find(final CriteriaQuery cq, • finalboolean isOffset); //QBCQuery • publicabstract List find(final CriteriaQuery cq); • publicabstract List findByExample(final Object example, • final Class instance); • publicabstractint getAllCount(final CriteriaQuery cq); //得到总行数 • publicabstractint getAllCount(final Class c); • publicabstractint getAllCount(String entityName); • }
BaseDao • publicvoid update(Object o) { • getHibernateTemplate().update(o); • } • publicvoid delete(Object o) { • getHibernateTemplate().delete(o); • } • publicvoid saveOrUpdate(Object o) { getHibernateTemplate().saveOrUpdate(o); …………………………………. • } • //spring管理Hiberbate的Session,保证每次调用都会正确的开启和关闭Session,并会自动参与事务。
Srping对Struts Action的支持 • 使用 Spring 的 ActionSupport 类整合 Structs • 使用 Spring 的 DelegatingRequestProcessor 覆盖 Struts 的 RequestProcessor • 将 Struts Action 管理委托给 Spring 框架 • 参考 • http://www-128.ibm.com/developerworks/cn/java/j-sr2.html
Spring Datasource 配置 <!-- <bean id="dataSource" • class="org.apache.commons.dbcp.BasicDataSource"> • <property name="driverClassName"> • <value>com.mysql.jdbc.Driver</value> • </property> • <property name="url"> • <value>jdbc:mysql://localhost:3306/cms</value> • </property> • <property name="username"> • <value>root</value> • </property> • <property name="password"> • <value>gmhewq</value> • </property> • </bean> --> • <bean id="dataSource" • class="org.springframework.jndi.JndiObjectFactoryBean"> • <property name="jndiName"> • <value>mysql5cms</value> • </property> • <property name="jndiEnvironment"> • <props> • <prop key="java.naming.factory.initial">weblogic.jndi.WLInitialContextFactory</prop> • <prop key="java.naming.provider.url">t3://127.0.0.1:7001</prop> • </props> • </property> • </bean>
Spring SessionFactory配置 • <bean id="sessionFactory" • class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> • <property name="dataSource"> • <ref bean="dataSource" /> • </property> • <property name="hibernateProperties"> • <props> • <prop key="hibernate.dialect"> • org.hibernate.dialect.MySQLDialect • </prop> • <prop key="hibernate.show_sql">true</prop> • </props> • </property> • <property name="mappingResources"> • <list> • <value> • com/gsta/bnet/bizservice/model/CmsRight.hbm.xml • </value> • </list> • </property> • </bean>
Hibernate xml配置文件 • <hibernate-mapping> • <class name="com.gsta.bnet.bizservice.model.CmsRight" table="cms_right"> • <id name="rightId" type="string"> • <column name=“right_id” length=“50” />//主键生成策略 • <generator class="com.gsta.bnet.common.util.UIDGenerator"> • <param name="separator">-</param> • </generator> • </id> • <property name="rightBox" type="string"> • <column name="right_box" length="50" not-null="true" /> • </property> • <property name="rightDesc" type="string"> • <column name="right_desc" not-null="true" /> • </property> • <property name="rightUrl" type="string"> • <column name="right_url" not-null="true" /> • </property> • </class> • </hibernate-mapping>
主要工作 • 利用Spring和Hibernate改造JCF框架,以支持快速开发。
下一步工作 • 考虑分布式事务和缓存。 • 封装Spring ApplicationContext或者是BeanFacatory,对其所支持的组件进行分类。 • 编写一个XML文件传入容器,按步骤执行组件的execute方法。 • 定义一套业务异常方便控制Command的操作流程。 • 加入Spring对JMS 、web service、定时器,完成类似工作流系统的功能。 • 引入spring acegi安全机制。