2022年SSH开发新实施方案书之基于SSH开发架构的重新分层.docx
-
资源ID:12799468
资源大小:308.71KB
全文页数:23页
- 资源格式: DOCX
下载积分:4.3金币
快捷下载
会员登录下载
微信登录下载
三方登录下载:
微信扫一扫登录
友情提示
2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
|
2022年SSH开发新实施方案书之基于SSH开发架构的重新分层.docx
SSH 开发新方案之基于 SSH 开发架构的重新分层现代的企业开发中,越来越多地引入了多层架构设计模式;Struts+Spring+Hibernate 一下简称为 SSH>就是其中之一, SSH 架构是当前特别火的架构,许多金融、电信工程,大型门户网站均挑选该架构作为业务支撑架构,开发流程也已经特别成熟;但是该结构开发起来,照旧存在一些问题;分析这些问题,得先从SSH 架构的组成说起;SSH 为 Struts+Spring+Hibernate 的组成方式, Struts 实现 MVC ,Spring 负责架构的结合, Hibernate 进行数据的长久化;通常其分层开发的结构图 以一个业务新增为例>如下:这样的结构,满意了一般的业务需要,但是对于当前日益复杂化的WEB2.0 的开发,却存在不少问题,归纳起来主要有以下几点的不足:A>DAO 和服务层简洁显现职责不明,由于根据MVC 规律,业务代码应当写在Struts Action 里,但是其事务的供应,却是配置在 Service 层;为了一组在规律上完整的数据操作业务规律,需要涉及两个层<Serveice、Action )来进行编写,遇到判定的情形下,为了保证完整的事务操作,就需要将业务代码移到Service 层完成,而通常习惯了在Struts Action 里调用多次Service 而产生多个事务而在显现Exception 时导致出错时操作之前调用的Service 事务的业务数据没有回滚;B> 当需要返回的数据供AJAX 使用,操作 JSON 或 XML 的的大量使用时;开发起来会很费劲,一段同样的业务代码,为了使用 AJAX 和 XML 可能需要重新编写一次,或者在同一个ACTION 里通过标志来判定,对分层结构造成了比较糟糕的破坏;假如设计得不好,为了使用JSON 和 XML 仍得额外增加大量的配置,严峻降低了开发效率;因此,为了克服这些缺点,本人对于SSH架构,进行了实现了重新的分层,共享了业务代码;简化了开发、增强了与23 / 19AJAX 技术、 MXL 技术的结合;供应了一种更高效的开发模式;其开发的结构图如下:看到这个架构图有人可能会问,Struts Action 类的编写去哪了呢?答案正是这个架构的优点,由于业务代码统一实现IbusinessService 接口,使得只需要相对固定的几个Struts Action 类调用 Service 层的方法,便可以完成工作;包括JSON 格式输出, XML 输出及 WebService 输出均调用 Service 层方法来完胜利能;这样便实现了业务代码的分别,以及与前端框架的极大解耦;结合 spring+hibernate与 jdbc的事务问题背景 :我们是一家工作流公司,客户选购我们的产品后,将其嵌入其工程中;我们的工作流采纳的是 spring+hibernate的方式,客户工程就是 jdbc 直接进行数据库操作;问题 :客户在其数据库操作过程中需要调用我们的工作流接口,这样就需要将我们的工作流操作与他们的业务操作置于同一个事务中;我们的服务采纳的都是spring的声明式事务,而客户采纳的是对connection进行事务处理;如何保证事务的一样性?想到的解决方案一 :使用 jta事务,用 tomcat+jotm供应事务治理器;为什么一开头就想到要使用 jta事务?实际上我们和客户都是使用的同一个数据库,为了便利,各自使用了不同的数据库连接方式,使用jta的话的确有 bt 的意思在里面;但是事实上是我们的第一反应都是jta ;最终没有采纳该方法的缘由也很简洁:我没有将jotm配置胜利!汗一个;想到的解决方案二 :将客户的这些特定代码用spring治理起来;由于要修改客户部分代码, 这个方案遭到了客户的剧烈反对;于是舍弃;想到的解决方案三 :客户数据库操作与我们的服务使用同一个数据库连接;然后编程处理事务;存在两种方式:一种是把客户的连接传给我们,另一种就是把我们的连接传给客户;第一种方式对我们的影响太大,所以最终打算采纳后一种方式:从hibernate session中猎取 connection然后传递给客户;接下来查看一下HibernateTemplate的 execute>方法,思路就很简洁了:猎取定义的sessionFactory->创建一个新的 session并打开 ->将 session与当前线程绑定 ->给客户代码返回connection->打开事务 ->客户使用我们传递的connection 进行数据库操作->我们不带声明事务的服务操作->提交事务 ->解除绑定;实际要留意的地方是: 1 、将 session与当前线程绑定使用的TransactionSynchronization Manager.bindResource>方法,这样在 HibernateTemplate里才能找到session;2 、我们的服务肯定要把声明式事务完全干掉,否就会有commit;3 、我们服务调用完毕后肯定要flush session,否就客户代码不会感知数据库里的数据变化;最终解决:使用了spring里常用的模板和回调;代码如下:publicclassTransactionTemplate protectedfinalLog logger = LogFactory.getLogTransactionTemplate.class > ;privateFlushMode flushMode = FlushMode.ALWAYS;publicObject executeTransactionCallback callback> / 第一猎取 sessionFactorySessionFactory sessionFactory = SessionFactory> Framework.getEngine>.getContainer>.getComponent"sessionFactory">;/ 创建一个新的 session并打开logger.debug"Opening single Hibernate Session in TransactionTemplate "> ;Session session = getSessionsessionFactory>;/ 将 session与当前线程绑定TransactionSynchronizationManager.bindResourcesessionFactory,newSess ionHoldersession>>;/ 猎取数据库连接Connection conn = session.connection>;Object result =null ;Transaction transaction =null ;try/ 开头处理事务transaction = session.beginTransaction>;tryresult = callback.doInTransactionconn>;catchRuntimeException ex> doRollbacksession, transaction>;throwex ;catchError err> doRollbacksession, transaction>;throwerr ;/ 假如数据库操作过程中没有发生反常就提交事务mit>;catchWorkflowException e> logger.error"数据库操作失败,事务回滚也失败!"> ;throwe ;catchRuntimeException ex> logger.error"数据库操作失败,事务被回滚!"> ;throwex ;catchError err> logger.error"数据库操作失败,事务被回滚!"> ;throwerr ;finally/将 session与当前线程解除绑定TransactionSynchronizationManager.unbindResourcesessionFactory>;doClosesession>;returnresult;protectedSession getSessionSessionFactory sessionFactory> Session session = SessionFactoryUtils.getSessionsessionFactory,true > ;FlushMode flushMode = getFlushMode>;if flushMode .=null > session.setFlushModeflushMode>;returnsession;privatevoiddoRollbackSession session, Transaction transaction> logger.debug"数据库操作反常,开头回滚事务"> ;trytransaction.rollback>;logger.debug"回滚事务胜利! "> ;catchException e> logger.error"回滚事务失败! "> ;thrownewWorkflowException"回滚事务失败! "> ;finally session.clear>;privatevoiddoCloseSession session> logger.debug"开头关闭连接 "> ;trysession.close>;catchException e> logger.error"关闭连接失败! "> ;thrownewWorkflowException"关闭连接失败! "> ;publicFlushMode getFlushMode> returnflushMode;publicvoidsetFlushModeFlushMode flushMode> this .flushMode = flushMode; b5E2RGbCAPpublicinterfaceTransactionCallback Object doInTransactionConnection conn>; p1EanqFDPw调用伪代码:publicvoidmethodA>TransactionTemplate transactionTemplate=newTransactionTemplate>;transactionTemplate.executenewTransactionCallback> publicObject doInTransactionConnection conn> / 客户代码client.method1"1">;/ 我们代码 直接使用our.method2>;/ 客户代码client.method3"l">;returnnull ;>;荣浩原创,转载请注明出处:)DXDiTa9E3dposted on 2007-10-09 15:11ronghao阅读 5090>评论 5>编辑 保藏 所属分类 :工作日志 RTCrpUDGiT高并发测试下的一些问题及解决测试在 sqlserver2000上进行,对工作流操作的相关方法在单元测试里进行多线程并发;测试发觉 sqlserver显现死锁的情形相当多,一些典型的情形:1 、对同一张表先insert再 update是很快会引起死锁的,不管操作的是否是同一记录解决方法:对于同一记录,需要调整hibernate的映射策略,使得一次insert完成操作;对于不同的记录需要在代码中手动flush,使得 update先于 insert;2 、对两张表进行多次update操作时,两张表交替update也会很快引起死锁解决方法:在代码中手动flush ,保证对两张表的update不会显现交替的情形;3 、部分大范畴扫描的select和 update混合也会导致死锁解决方法:优化sql ,尽量削减 sql 语句,通过给 po 增加长久化字段的方式削减关联查询经过优化,大部分情形下数据库死锁的情形得以防止,另外古怪的是通过大事探查器在死锁时并未发觉锁升级的大事;但是在一些特别情形下< 例如多个并发汇聚的直接联合),死锁照旧发生;最终不得不对方法进行synchronized关键字同步,这个通过synchronized flush完成;业务方法不必同步,最终批量操作数据库时进行同步;换 oracle进行测试,在未synchronized的情形下,未发生死锁情形;由此可见sqlserver 与 oracle锁实现机制存在很大的差别;对sqlserver鄙视之;另,同事说,sqlserver2005 后性能和机制发生了很大的变化,未测试;补充一下我的一个最简洁情形下的测试用例:PO : 5PCzVD7HxApublicclassTestPO String id; String name;intnum;. jLBHrnAILg映射文件 hibernate3:<hibernate-mappingdefault-access="field">< classtable="WFMS_TESTPO" name="com.eway.workflow.test.po.TestPO"><id name="id" column="ID"><generatorclass ="uuid" /></id><property name="name" column="NAME" type="string"/><property name="num" column="NUM" type="integer"/></class ></hibernate-mapping>xHAQX74J0X被测试方法 < 都配置有事务):publicvoidtestSaveintnum> TestPO po =newTestPO>;po.setName"ronghao">;po.setNumnum>theadTestDao.savepo>;po.setName"haorong">;publicvoidtestSaveByJdbcintnum> String sql = "insert into WFMS_TESTPO ID,NAME,NUM> values .,'RONGHA O',.>";Object params =newObjectnum,num;jdbcTemplate.updatesql, params>;sql="update WFMS_TESTPO set name='haorong' where id=.";params =newObjectnum;jdbcTemplate.updatesql, params>;LDAYtRyKfE测试用例:publicvoidtestSave>throwsException TheadtestTemplate template =newTheadtestTemplate>;template.executenewTheadtestCallback> publicvoiddoInTheadintsuquence> /theadTestManager.testSavesuquence>;theadTestManager.testSaveByJdbcsuquence>;, 10>;Zzz6ZB2Ltk测试结果:不论是hibernate仍是 jdbc ,并发情形下都很快就会引起sqlserver2000的死锁,换用两种数据库驱动jtds和 jturbo死锁的情形没有变化;结论 : sqlserver2000数据库的 lock配置策略,不支持,或者数据库本身,就不支持对不同的行做同时操作< 或者支持不完善),所谓的行锁支持很不完善,死锁情形特别简洁发生;补充:我对数据库的一些实现机制也并不是很明白,所以这里也只能列显现象而不能说明死锁的根本缘由;另外感谢Alex的争论;荣浩原创,转载请注明出处:)dvzfvkwMI1posted on 2021-06-19 13:34ronghao阅读 2586>评论 22>编辑 保藏 所属分类 :工作日志 rqyn14ZNXIFeedBack:# re:高并发测试下的一些问题及解决 未登录 2021-06-19 15:02 | Alexxd ,你配置了事务了嘛?回复 更多评论# re:高并发测试下的一些问题及解决2021-06-19 17:55 | flybean1 、死锁,仍是锁堵塞,这是个问题;2 、悲观并发、乐观并发生来以久,各有优缺点,搞清晰再来鄙视;回复 更多评论EmxvxOtOco# re:高并发测试下的一些问题及解决 未登录 2021-06-20 09:14 | Alex1 、对同一张表先 insert再 update是很快会引起死锁的,不管操作的是否是同一记录2 、对两张表进行多次update操作时,两张表交替update也会很快引起死锁3 、部分大范畴扫描的select和 update混合也会导致死锁假如连这些问题都解决不了,你觉得是数据库问题,仍是你的问题呢?别拿那么多名词出来吓人,这个招数我上学校的时候用来恐吓老师的,现在已经不用了;就捡最终一个说吧,乐观锁,假如你掌握不了,仍是就不要用了,您仍就是老老实实的本分点,使用数据库本地供应的锁功能吧,牺牲点数据库的性能,也总比你数据更新失败要好,假如你非要使用hibernate的乐观锁,请掌握好,内存中的数据和数据库中的数据一样性;回复更多评论SixE2yXPq5# re:高并发测试下的一些问题及解决 未登录 2021-06-20 09:28 | ronghaoAlex我想你并没有弄明白问题的关键;乐观锁和悲观锁的作用是防止多个事务对同一数据操作产生冲突的两种策略;而我的问题是多个线程< 即多个事务)并发操作不同的数据;不知道明不明白意思;ps: 以前我也把这两者的概念常常混淆;回复更多评论6ewMyirQFL# re:高并发测试下的一些问题及解决2021-06-20 09:29 | BeanSoft说不定是滥用 Hibernate导致的后果回复 更多评论# re:高并发测试下的一些问题及解决 未登录 2021-06-20 09:34 | ronghaoBeanSoft我倒真的认为是数据库的缘由;一个简洁的例子:很简洁的po :String id;String name;两个字段,执行操作:TestPO po=new TestPO>;po.setName"ronghao">;dao.savepo>;dao.flush>;po.setName"haorong">;配置事务,单元测试两个线程并发,sqlserver2000下立刻死锁;回复更多评论kavU42VRUs# re:高并发测试下的一些问题及解决 未登录 2021-06-20 09:39 | ronghaoBeanSoft当然,我并没有用 jdbc直接测试 回复 更多评论# re:高并发测试下的一些问题及解决 未登录 2021-06-20 10:12 | Alexronghao假如不是多线程,那么配置事务仍有何用,假如全部操作都在同一个流水线上,那么配置事务不是铺张人民的感情嘛?回复更多评论y6v3ALoS89# re:高并发测试下的一些问题及解决 未登录 2021-06-20 10:18 | Alex使用 hibernate乐观锁假如导致你储存失败,简洁点说,就是你的两个线程或者多个线程所掌握的内存中的数据和数据库中数据集已经不一样了;假如使用悲观锁,导致你储存失败,那么说明你事务配置的问题,或者至少说明你测试用例的事务配置有问题,要不你直接试试jdbc并且硬编码事务看看;否就 sqlserver2000真的不要玩了,两个线程都是死锁;回复更多评论M2ub6vSTnP# re:高并发测试下的一些问题及解决 未登录 2021-06-20 10:20 | Alex同时操作同的记录集合,一方面要看你数据库使用什么lock 策略,一方面仍要看你代码的掌握;回复 更多评论0YujCfmUCw# re:高并发测试下的一些问题及解决 未登录 2021-06-20 10:21 | Alex同时操作不同的记录集合,一方面要看你数据库使用什么lock 策略,一方面仍要看你代码的掌握.回复 更多评论eUts8ZQVRd# re:高并发测试下的一些问题及解决 未登录 2021-06-20 10:21 | ronghaoAlex你的说法没有错;我想问题的缘由在于死锁的缘由你我的懂得有差异;你懂得的是对数据库表同一记录并发操作引起数据库死锁,这个明显是应用程序应当掌握和防止的;而我的意思是并发操作某一动作,例犹如时启动100个工作流流程,这个尽管操作的是同一张表但是明显是针对不同的记录,此时,乐观锁、悲观锁都是没有意义的;当然,我对数据库的一些实现机制也并不是很明白,所以这里也只能列显现象而不能说明死锁的根本缘由;回复更多评论sQsAEJkW5T# re:高并发测试下的一些问题及解决 未登录 2021-06-20 10:26 | ronghaoAlex补充说明一下,在我的测试中,不会显现两个线程相互修改冲突的情形,甚至select也不会冲突,由于流程实例 ID 一开头就将全部的数据区分开来;我是并发启动多个流程,然后并发提交这些流程;回复 更多评论GMsIasNXkA# re:高并发测试下的一些问题及解决 未登录 2021-06-20 10:31 | Alex上面我也说了,假如你直接使用hibernate的乐观锁,那么最细粒度的数据其实是由你自己来掌握的, 只要保持内存中的当前的数据在需要储存时和数据库中的储存相同的version就可以了,然后不管有多少个线程 insert或者 update,只要每个线程都满意这个要求,就能储存胜利了,当然,假如你的数据库的 lock 配置策略,不支持,或者数据库本身,就不支持对不同的行做同时操作< 或者支持不完善), 所谓的行锁,那么确定会像你所说的那样发生死锁;回复更多评论TIrRGchYzg# re:高并发测试下的一些问题及解决 未登录 2021-06-20 10:37 | Alexronghao假如每个线程只处理某一个或一些独立流程id 相关的数据,而没有交叉数据,那么仍会显现这种现象;1. 使用 jdbc做这种测试,排除是否是hibernate的使用或者 hibernate本身对 2000支持的问题问题; <jdbc驱动也很关键;)2. 查阅 sql2000对行锁的支持程度;回复更多评论7EqZcWLZNX# re:高并发测试下的一些问题及解决 未登录 2021-06-20 10:45 | ronghaoAlex哈哈,正如你说的,我想问题在这里:当然,假如你的数据库的lock配置策略,不支持,或者数据库本身,就不支持对不同的行做同时操作<或者支持不完善),所谓的行锁,那么确定会像你所说的那样发生死锁;这也是我想表达的;我想有时间应当请个专业的DBA 来,我也查过了 SQLSERVER的锁机制,但是详细到这里懂得仍是存在问题;另外你对乐观锁的懂得也很到位;假如是多个事务同时提交一个流程,乐观锁就会起作用;回复更多评论lzq7IGf02E# re:高并发测试下的一些问题及解决 未登录 2021-06-20 10:46 | ronghaoAlex好的,感谢你的看法;我会用jdbc做这个测试;回复更多评论# re:高并发测试下的一些问题及解决2021-06-20 16:30 | BeanSoft是呀 JDBC 先测试下比较好排除法假如JDBC也不行那八九成是 SQL Server问题坊间的传言都认为SQL Server好多地方不如 Oracle回复 更多评论zvpgeqJ1hk# re:高并发测试下的一些问题及解决2021-06-21 19:45 |鬼狗pk 的这么热闹丫,我想可能先要搞清晰的是行锁,页锁和表锁这些基本概念,搞清晰不同数据库的锁机制,然后再来谈乐观锁仍是悲观锁会比较简洁懂得;我估量楼主缺少在 sybase ,db2 下的工作体会,所以才会这么兴奋;不同数据库的设计本身是有相当大差异的,很难说好坏,我印象中,缺省情形下对锁的处理比较不伤脑筋的就是oracle了,其他的不管是sybase仍是 db2 都不是缺省就可以很轻松做到高并发的,但是处理的好,至少db2可以做到不输给 or acle 的高并发;至于 sql server, tpc 网站上去翻一下,可以发觉sql server也是常客;但是早期 oracle的开发,嗯,我觉得在许多方面其实倒不如db2 这样的数据库省事,比如大表和小表在sql 中的位置,都会显著影响sql 性能;再比如 sql 是简洁好,仍是复杂好,这2 个数据库也是相反的;这只能说明不同数据库的机制是有很大差异的,用好一个数据库需要点时间对他进行比较深化的懂得;现代程序员往往被各种框架屏蔽了底层,有时候也不是什么好事,以前工程中就有特地组织DBA 对程序员进行数据库方面的培训,目的也就是为了补偿这个问题;对于锁的问题,在 oracle9i&10g编程艺术那本书里,作者有很深化的介绍,也列举了其他数据库的处理情形;作者从其他数据库转向使用oracle的时候,对这个问题,貌似和楼主一样震动,呵呵;当年我也有个工程,被 db2的锁机制,搞的的死去活来,呵呵;简洁的说,摇身要是高牢靠性数据库都只是知道写sql 这么简洁,人家DBA 仍怎么活?回复更多评论NrpoJac3v1# re:高并发测试下的一些问题及解决2021-06-21 19:50 |鬼狗另外不知道 lz 用的 jdbc是什么版本? sqlserver 2000的官方版本问题多多,印象中诸多特性都不支持;回复更多评论1nowfTG4KI# re:高并发测试下的一些问题及解决2021-06-22 15:24 | ronghao鬼狗呵呵,你的看法特别中肯;回复 更多评论