- 浏览: 793076 次
- 性别:
- 来自: 成都
最新评论
-
天塔上的猫:
技术孵化,任重道远啊!不过大哥能力牛逼啊,相信会有实现的一天的 ...
技术孵化的探索之路 -
SIHAIloveYAN:
谢谢分享,刚刚考上研究生,对我有很大的帮助,希望5年后再回到这 ...
我的2015 -
MUMU影子:
...
技术孵化的探索之路 -
tonyyan:
谢谢分享!
Java源码阅读的真实体会 -
cauchenlu:
http://ez.web126.cn/这个不错,完全颠覆目前 ...
一种快速开发的Java Web架构设计和实现(续)
这是我年初写的一篇文章,当时用webwork+Spring+Hibernate开发一个web应用,一种很流行的J2EE开发模式,在开发了两周后,对Web开发的一个总结,我觉得对新手还是有一定帮助的。很模糊的记得在Javaeye有人写过类似的文章,在此表示感谢了。
发布到这儿,因为觉得Javaeye的blog比其它的好用,以后就在这儿安家啦。
作为一个表示层框架,无论是Struts、Webwork,还是SpringMVC、JSF,它们都是解决同一类问题。
表示层框架,从分层的角度考虑,它的核心是作为一个Front Controller,在Struts里面是ActionSerlvet+RequestProcessor+Action,前两个是框架本身的,只有 Action需要我们处理。它的职责也就是协调用户的输入,将请求dispatch给后端business,由后端business系统处理后,将相应的结果返回给Controller,再由Controller处理返回给用户。
对于开发来说,特别需要注意的是职责分配的问题,这是我们开发过程中最容易犯的毛病,也是最需要注意的地方。Front Controller只是一个Controller,也就是Call别的接口,自己本身不应该有处理业务的职责,它应该尽量的thin。如果不遵守这个原则呢?那带来的将是系统难以测试,难以重用,难以维护。
具体来说,我们的业务系统是可以重用的,可以提供Service接口给Web层调用,也可以提供给其它系统通过Web Services接口调用,还可以给分布式client调用。它们的调用方式,一般有三种:
最普通的调用。在web系统中,就是表示层Controller直接调用服务层。
依赖注入式调用(Dependency Injection)。它需要IoC容器支持,如Spring,picoContainer,它对解耦和测试非常有用
依赖查找式调用(Dependency Lookup)。也就是EJB里面的JNDI,它最大的好处是支持分布式开发和组件开发。
我们一定要牢牢记住表示层的职责。表示层框架很容易变,但系统业务还是相对固定,如果你接触过物流系统,你就会明白什么叫业务了,那时候在表示层里处理业务会非常可怕,因为我的业务要同时支持几种客户端:桌面client、Brower、移动client,难道你需要在每种client里面写业务吗?而且,表示层框架的开发人员可以不需要懂太多的业务就可以利用自己的技术优势,来调用业务相关接口。
下面我再具体谈谈表示层需要处理的几个部分:
整体说明
举个例子,我现在想对updateUser.do?userId=19做出请求,然后在一个UpdateUserAction里处理用户预更新,然后将结果导向到updateUser.jsp页面。这大概是我们所希望的最简单的处理方式吧。
上面那三个元素的相互关系在web框架的配置文件里面定义。现在的framework都倾向于config和metadata oriented,因为这样的框架会比较灵活、好维护,试试直接用JSP和Serlvet开发你就知道要做多少重复工作和hard code了。
在webwork里面,是xwork..xml,在Struts里面,是struts-config.xml,在JSF里面,是faces- config.xml。所以说,框架都是相通的。我这里需要特别指出的是,上面那些文件和文件名都是默认的,实际上,为了支持组件开发和团队协作开发,保持开发模块之间的松耦合,我们应该将配置文件分解成一个个的segment。
对于action,也就是前面提到的Front Controller。 在Struts里面,是通过继承基类的Action,在webwork,是通过实现Action接口。
在Struts里面,通过继承方式来实现Action,那么我们代码是和框架紧密耦合的。而且,只支持JSP,不支持模板语言,如Velocity、 FreeMaker,而这些可以脱离Servlet容器,最大的好处是,我们的网页设计人员可以专心做html界面。分工就意味着效率和质量。但 Struts这种框架就支持不够。
而webwork就很好地做到了这种解耦,action和前端表示完全分离,如表示页面还可以直接发布成pdf文档。
那么,继承基类和实现接口,对于我们开发人员意味着什么呢?灵活性、容易测试,这让我开发更容易一些。
Scenario 1 我们一些简单的CRUD操作,完全可以在一个action里面处理。虽然Struts也可以这样,因为它有一个DispatchAction,但你会发现,项目中,我们经常引入一个BaseAction,而这个BaseAction是继承DispatchAction还是Action,往往很难决择,因为我们这两种需要都有,虽然DispathAction也是继承Action。而webwork的处理就方便多了,你需要验证、国际化、安全等等很多操作,你都可以通过实现一个接口实现。
Scenario 2 我们测试Action的时候,总是要启动容器,启动一般要花将近半分钟,这会让我们很多时间都花在等待之中,由于Action和容器脱离,我们的测试会更迅速和直接。
我现在就按照整个页面流程来分类说明,在一个web框架下开发,或是开发web应用,或者开发Web Framework必须考虑到的各个方面:
1. 表单提取
我们开发web MIS系统,从技术角度考虑,第一步就是在页面输入数据,然后将它们保存到后端数据库。
框架应该自动提取表单数据,将这些String类型的数据转换成对应的数据类型,并封装为值对象(Value Object),提供给Controller,作为Controller的输入。
Struts是通过ActionForm,非常笨拙,而且对类型转换都支持不够。Webwork在这方面做得优雅多了,它将请求参数封装为一个Map对象。其实,请求本来就是key-value对。然后当数据传入到action后,就和Serlvet容器,web脱离了关系,这带来的解耦的好处就是还可以支持多种客户端,支持容器外测试。
具体实现上,Struts通过BeanUtil工具对ActionForm进行反射;webwork是通过一个拦截器Parameters Interceptor来获取,而action实现该接口,然后在配置文件里申明一下就ok了。
2. 表单验证
我们输入数据,一般需要符合一定的规范,如必须输入数字,不能为空,必须为邮政编码等等。
解决这个问题,如果不用framework,我们需要在jsp页面上用javascript验证,还要在servlet里面获取参数,然后验证,对于不合理的数据,需要将之保存,并附上错误说明,然后forword到原来jsp页面显示处理,非常烦琐和机械。
Struts框架原来处理还是挺机械的,主要在ActionForm的validate方法里验证,后来加入一个Validation框架,也就是一个plug-in,非常好用。Webwork也沿用了这一点,两者在验证上都不错。
但我们必须注意的一个问题,那就是验证不通过时,怎么保持原来的数据,特别是下拉框里面的数据,Struts处理很麻烦(难道我没用好?), webwork好用多了,不过有个tips,那就是将select的下拉列表保存在session里,不用每次验证不通过都重新从数据库加载。
另外还有一点,那就是和表单重复提交结合时会出现的问题,struts中,处理不当,就会出现在你验证不通过,修改后再次提交时总是被提示重复提交。 Webwork是通过一个Interceptor截获,处理很自然。不过我建议时提交通过后,用redirect,这样就不存在重复提交的缺陷。你总不希望因为网络慢,你的订单由于刷新而提交两遍,收到两份相通的货物吧。
3. 国际化和resource文件
Web界面是给用户看的。譬如,我们公司内网打算采用一套很知名的blog系统,但它是德国人开发的,但是你总不会希望看到界面是德文吧。这套blog开发商为了全球推广,也不至于为每种语言都开发一套吧,那不累死,维护简直就是恶梦。
我之所以现在要提到国际化,不光是国际化的问题,因为在表单验证时,如果field不通过,都会提示用户,但这些提示语一般都会重用,如create和 update用户时“用户名不能为空!”,我们可以在resource文件里定义一个key: error.user.username.required,然后在各处引用。
Webwork和Struts对这个都处理比较好,这也是一个表示层框架必须处理的。我建议不要在Action-validation.xml文件里hard code这些信息,而是将它们分离出来。
4. 请求路由
当我们将user成功提交后,我们让它由谁来处理呢?这就是请求路由的问题。
这种关系在配置文件里面定义,我上文都提到过。为了方便,往往将多个请求提交到一个action的不同方法,这是我们应该好好利用的。而它们在 webwork里面都可以很好配置。例如,将saveCreatedUser 路由到UserAction的saveCreatedUser方法里。
5. 请求处理
当请求发生,并且路由到正确的action后,我们的action就要处理它了,包括初始化,处理,清场。
关于Action需要注意的问题,我现在还要重申的是:一定要注意它的职责:不要处理它不应该处理的事情。
例如,注册用户时,用户姓名可以重复,但用户登录账号却不能重复。论坛发帖子就没有这样要求。再例如,会员系统中,用户积分达到100就是可以下载,但什么时候规则变了,需要积分150才能。这些规则在哪儿处理呢?最简单当然是在Action里:没有满足条件,就forward到输入页面。当规则很多时,你就很难维护了。反问一下,它是web层关心的问题吗?
在任何框架设计,包括web框架设计时,一般都有一个非常核心的模式,那就是template模式,它和一种称为callback的调用方式相关,也就是那个著名的好莱坞原则:don’t call me, I’ll call you! 具体到我们的web框架,也就是action,如webwork里面的ActionSupport,它们都是这种处理方式,我们不知道我们的Action 是被谁调用的(当然是框架了),但我们这样写,然后在xml一配置,就work well。
我们可以研究一下Struts的ActionSerlvet,特别是ReqeustProcessor,后者就是一个典型的template模式, action是作为里面一个command运行的。Command模式也是用callback调用。关于这两种模式,google一下就清楚了。
Spring就是使用Template和callback模式,对底层实现做了统一封装,其中template负责那些通用的功能,如事务、资源管理、异常处理,callback则完成变化的那部分,如处理具体的数据库statement操作。我们最常用的HibernateCallback和 HibernateDaoSupport就体现了这一点,具体可参照其源码。
另外,对于Action,一定要注意线程安全的问题。Struts的action是非线程安全的,大家可以参考一个RequestProcessor中定义的Map类型的actions字段,而Webwork是线程安全的,因为其ActionContext是 ThreadLocal的,也就是说每个线程都有自己的变量,互不干扰。具体体现是Struts的Action里面不能有字段申明,只能有局部变量。而 Webwork可以,这对于获取页面表单数据非常方便。
6. 请求应答
在Action执行完毕后,我们应该为其导航到结果页面,
在webwork里面,也就是Result Type。它定义了好几种方式。比较有意思的是它处理象freemaker(html模板),XML/XSLT,PDF这些格式输出。而Struts基本上是很单一JSP。
而且webwork还可以自定义Result类型,可以为我们提供Swing、mobile客户端显示。
7. 异常处理
任何操作都有出错的可能,怎么优雅地处理错误,这也是每个框架都应该考虑的。
有一些异常处理最佳实践,《Effective Java》就专门有一章谈到。在OnJava上也有一篇文章:http://www.onjava.com/pub/a/onjava/2003/11/19/exceptions.html,非常值得一读。
1.选择Checked还是Unchecked
2.Exception的封装
3.如无必要不要创建自己得Exception
4.不要用Exception来作流程控制
5.不要轻易的忽略捕获的Exception
6.不要简单地捕获顶层的Exception
Struts和Webwork里面都支持异常处理,webwork是通过Interceptor支持的:ExceptionMappingInterceptor。
在我的项目实践中,我喜欢将业务异常封装在业务层,申明为checked Exception,web的Action必须捕获,获取exception的ErrorCode,此ErrorCode就是resource文件里面的 key,也就是说它支持多语言,如ErrorCode.USER_EXISTED=”error.user.userExisted”。这类信息应该是业务层抛出的。如果将它由action处理,这是一种设计上的错误。
8. 灵活性、扩展性、可插入性
作为框架,就应该保证其灵活,支持不同用户的业务需求;容易扩展其功能,插入系统级的功能。
就Struts而言,在可插入性上还是不错的,这得益于它的plug-in支持,实现其PlugIn接口,然后在其struts-config.xml文件中配置一下,如它的验证框架、网页布局Tiles,内存数据库,都是其典型应用。
另外,以前的Struts还可以扩展它的RequestProcessor,实现一些特有的功能,如日志、安全,因为它预留了一个缺省方法processPreprocess()。
Webwork也是高度可扩展的,它主要是通过实现Interceptor接口。
9. 模块、组件化
在大型web项目中,模块、组件这些概念就非常适用了,因为一个大的工程,可能由不同公司开发,或是不同项目组、不同成员协作开发,最后要很容易地集成在一起。另外,还有第三方公司开发的组件插入进来,如漂亮的web界面组件,如Tree、table等。
Tapestry就是一种基于组件的开发框架,不过我没有研究,呵呵。
但webwork确实可以支持,如xwork.xml 配置的package就是支持模块申明,其附带的FreeMaker就可以将开发好的模块打包成jar文件,在Servlet容器外加载。
JSF对组件支持是相当到位的。它所设计的目标,就是在IDE里面,直接拖拽web组件,象table,tree,就可以形成漂亮的界面,真正实现所见即所得。实现自己的组件,只要实现其UIComponent接口就行了。应该说JSF是一种非常有前途的Web层框架,它会把Web开发真正达到easy。因为直到现在,还没有一种框架能够很容易做到,它的界面开发始终没法和微软相提并论,虽然它有界面布局框架Tiles和SiteMesh,以及模板语言 Velocity、FreeMaker、Servlet2.4支持的EL。
不过遗憾的是,JSF开发工具还没有达到那么完善,除了Sun自己一直、推广的NetBeans IDE。Sun的官方有其demo,用flash演示,还是蛮cool的。
关于Ajax和请求模式
Ajax其实早在五年前就有了,只是没有被人注意罢了,直到2005年google把它应用在google map和gmail上,才开始被人关注。它也是web2.0时代一种重要的技术,ajax强调用户体验(XP)。因为它的本质就是一个异步调用。而我们的一般web页面请求都是同步的,你必须等到服务器全部处理完成。同步变异步,确实是一种革命,虽然它的技术很简单,只是一个XMLHttpRequest 的javascript对象。它让我们的Web版的Rich Client成为可能。Google现在正看到了web office的应用前景,对MS构成巨大威胁,大家可以试试它的Web版的excel和、日历、邮件,不久就会推出正式的web word,很cool。
另外,Ajax更接近实际的web请求,因为一般web请求时,每一次,我们获得的是整个页面内容,无论这个页面有多少数据是冗余的。譬如,我们分页浏览时,整个页面布局是由header,left navigator、footer组成,中间是content,翻页时,应该从服务器返回一个xml的用户列表数据格式,而且不包括html table的tag,这正是ajax另外一个方面:返回的是数据,而不是整个页面。这对于窄带宽,也是非常有益的。
Webwork的2.2.2版本支持ajax,底层是dojo和DWR这两个著名的ajax框架。但是webwork的ajax Tag做得太粗糙,用了ajax后,页面布局,特别是表单位置没法控制,而且对IE浏览器支持不够。我现在几乎都放弃了。
没有好的ajax框架,使得ajax开发起来很困难,也许因为它还不到一周岁吧。
我们现在的web框架,一般都是基于请求的模式,也就是说我们请求时总是会考虑它的目的URL,将提交数据保存在该请求中。这种模式,让我们开发时总在考虑这些所谓的http协议。一种完善的框架,应该尽量去屏蔽这些与底层协议相关的东西。
JSF给我们一种全新的方式,它让我们按照操作桌面应用,如Swing程序的方式处理网络请求,因为它是基于事件的。在Sun的petstore的WAF 框架中就有这种原始的思想。基于事件,让我们开发rich client提供了一种思想,但是,感觉和MS的asp.net相比,还是差很远。
事件驱动有一种核心的模式,那就是Observer模式,所谓的Observer就是listener(只是一个用眼睛,一个用耳朵,呵呵)。 Oberver是一种推(push)模式,也就是说事件Event发生时(如model发生改变),它会通知你,而不是你去取(拉模式)。
在Servlet规范中,也引入了listener的概念,如HttpSessionListener,它对于监视用户上线下线非常有帮助,它们是生命周期lifecycle的范畴。
发布到这儿,因为觉得Javaeye的blog比其它的好用,以后就在这儿安家啦。
作为一个表示层框架,无论是Struts、Webwork,还是SpringMVC、JSF,它们都是解决同一类问题。
表示层框架,从分层的角度考虑,它的核心是作为一个Front Controller,在Struts里面是ActionSerlvet+RequestProcessor+Action,前两个是框架本身的,只有 Action需要我们处理。它的职责也就是协调用户的输入,将请求dispatch给后端business,由后端business系统处理后,将相应的结果返回给Controller,再由Controller处理返回给用户。
对于开发来说,特别需要注意的是职责分配的问题,这是我们开发过程中最容易犯的毛病,也是最需要注意的地方。Front Controller只是一个Controller,也就是Call别的接口,自己本身不应该有处理业务的职责,它应该尽量的thin。如果不遵守这个原则呢?那带来的将是系统难以测试,难以重用,难以维护。
具体来说,我们的业务系统是可以重用的,可以提供Service接口给Web层调用,也可以提供给其它系统通过Web Services接口调用,还可以给分布式client调用。它们的调用方式,一般有三种:
最普通的调用。在web系统中,就是表示层Controller直接调用服务层。
依赖注入式调用(Dependency Injection)。它需要IoC容器支持,如Spring,picoContainer,它对解耦和测试非常有用
依赖查找式调用(Dependency Lookup)。也就是EJB里面的JNDI,它最大的好处是支持分布式开发和组件开发。
我们一定要牢牢记住表示层的职责。表示层框架很容易变,但系统业务还是相对固定,如果你接触过物流系统,你就会明白什么叫业务了,那时候在表示层里处理业务会非常可怕,因为我的业务要同时支持几种客户端:桌面client、Brower、移动client,难道你需要在每种client里面写业务吗?而且,表示层框架的开发人员可以不需要懂太多的业务就可以利用自己的技术优势,来调用业务相关接口。
下面我再具体谈谈表示层需要处理的几个部分:
整体说明
举个例子,我现在想对updateUser.do?userId=19做出请求,然后在一个UpdateUserAction里处理用户预更新,然后将结果导向到updateUser.jsp页面。这大概是我们所希望的最简单的处理方式吧。
上面那三个元素的相互关系在web框架的配置文件里面定义。现在的framework都倾向于config和metadata oriented,因为这样的框架会比较灵活、好维护,试试直接用JSP和Serlvet开发你就知道要做多少重复工作和hard code了。
在webwork里面,是xwork..xml,在Struts里面,是struts-config.xml,在JSF里面,是faces- config.xml。所以说,框架都是相通的。我这里需要特别指出的是,上面那些文件和文件名都是默认的,实际上,为了支持组件开发和团队协作开发,保持开发模块之间的松耦合,我们应该将配置文件分解成一个个的segment。
对于action,也就是前面提到的Front Controller。 在Struts里面,是通过继承基类的Action,在webwork,是通过实现Action接口。
在Struts里面,通过继承方式来实现Action,那么我们代码是和框架紧密耦合的。而且,只支持JSP,不支持模板语言,如Velocity、 FreeMaker,而这些可以脱离Servlet容器,最大的好处是,我们的网页设计人员可以专心做html界面。分工就意味着效率和质量。但 Struts这种框架就支持不够。
而webwork就很好地做到了这种解耦,action和前端表示完全分离,如表示页面还可以直接发布成pdf文档。
那么,继承基类和实现接口,对于我们开发人员意味着什么呢?灵活性、容易测试,这让我开发更容易一些。
Scenario 1 我们一些简单的CRUD操作,完全可以在一个action里面处理。虽然Struts也可以这样,因为它有一个DispatchAction,但你会发现,项目中,我们经常引入一个BaseAction,而这个BaseAction是继承DispatchAction还是Action,往往很难决择,因为我们这两种需要都有,虽然DispathAction也是继承Action。而webwork的处理就方便多了,你需要验证、国际化、安全等等很多操作,你都可以通过实现一个接口实现。
Scenario 2 我们测试Action的时候,总是要启动容器,启动一般要花将近半分钟,这会让我们很多时间都花在等待之中,由于Action和容器脱离,我们的测试会更迅速和直接。
我现在就按照整个页面流程来分类说明,在一个web框架下开发,或是开发web应用,或者开发Web Framework必须考虑到的各个方面:
1. 表单提取
我们开发web MIS系统,从技术角度考虑,第一步就是在页面输入数据,然后将它们保存到后端数据库。
框架应该自动提取表单数据,将这些String类型的数据转换成对应的数据类型,并封装为值对象(Value Object),提供给Controller,作为Controller的输入。
Struts是通过ActionForm,非常笨拙,而且对类型转换都支持不够。Webwork在这方面做得优雅多了,它将请求参数封装为一个Map对象。其实,请求本来就是key-value对。然后当数据传入到action后,就和Serlvet容器,web脱离了关系,这带来的解耦的好处就是还可以支持多种客户端,支持容器外测试。
具体实现上,Struts通过BeanUtil工具对ActionForm进行反射;webwork是通过一个拦截器Parameters Interceptor来获取,而action实现该接口,然后在配置文件里申明一下就ok了。
2. 表单验证
我们输入数据,一般需要符合一定的规范,如必须输入数字,不能为空,必须为邮政编码等等。
解决这个问题,如果不用framework,我们需要在jsp页面上用javascript验证,还要在servlet里面获取参数,然后验证,对于不合理的数据,需要将之保存,并附上错误说明,然后forword到原来jsp页面显示处理,非常烦琐和机械。
Struts框架原来处理还是挺机械的,主要在ActionForm的validate方法里验证,后来加入一个Validation框架,也就是一个plug-in,非常好用。Webwork也沿用了这一点,两者在验证上都不错。
但我们必须注意的一个问题,那就是验证不通过时,怎么保持原来的数据,特别是下拉框里面的数据,Struts处理很麻烦(难道我没用好?), webwork好用多了,不过有个tips,那就是将select的下拉列表保存在session里,不用每次验证不通过都重新从数据库加载。
另外还有一点,那就是和表单重复提交结合时会出现的问题,struts中,处理不当,就会出现在你验证不通过,修改后再次提交时总是被提示重复提交。 Webwork是通过一个Interceptor截获,处理很自然。不过我建议时提交通过后,用redirect,这样就不存在重复提交的缺陷。你总不希望因为网络慢,你的订单由于刷新而提交两遍,收到两份相通的货物吧。
3. 国际化和resource文件
Web界面是给用户看的。譬如,我们公司内网打算采用一套很知名的blog系统,但它是德国人开发的,但是你总不会希望看到界面是德文吧。这套blog开发商为了全球推广,也不至于为每种语言都开发一套吧,那不累死,维护简直就是恶梦。
我之所以现在要提到国际化,不光是国际化的问题,因为在表单验证时,如果field不通过,都会提示用户,但这些提示语一般都会重用,如create和 update用户时“用户名不能为空!”,我们可以在resource文件里定义一个key: error.user.username.required,然后在各处引用。
Webwork和Struts对这个都处理比较好,这也是一个表示层框架必须处理的。我建议不要在Action-validation.xml文件里hard code这些信息,而是将它们分离出来。
4. 请求路由
当我们将user成功提交后,我们让它由谁来处理呢?这就是请求路由的问题。
这种关系在配置文件里面定义,我上文都提到过。为了方便,往往将多个请求提交到一个action的不同方法,这是我们应该好好利用的。而它们在 webwork里面都可以很好配置。例如,将saveCreatedUser 路由到UserAction的saveCreatedUser方法里。
5. 请求处理
当请求发生,并且路由到正确的action后,我们的action就要处理它了,包括初始化,处理,清场。
关于Action需要注意的问题,我现在还要重申的是:一定要注意它的职责:不要处理它不应该处理的事情。
例如,注册用户时,用户姓名可以重复,但用户登录账号却不能重复。论坛发帖子就没有这样要求。再例如,会员系统中,用户积分达到100就是可以下载,但什么时候规则变了,需要积分150才能。这些规则在哪儿处理呢?最简单当然是在Action里:没有满足条件,就forward到输入页面。当规则很多时,你就很难维护了。反问一下,它是web层关心的问题吗?
在任何框架设计,包括web框架设计时,一般都有一个非常核心的模式,那就是template模式,它和一种称为callback的调用方式相关,也就是那个著名的好莱坞原则:don’t call me, I’ll call you! 具体到我们的web框架,也就是action,如webwork里面的ActionSupport,它们都是这种处理方式,我们不知道我们的Action 是被谁调用的(当然是框架了),但我们这样写,然后在xml一配置,就work well。
我们可以研究一下Struts的ActionSerlvet,特别是ReqeustProcessor,后者就是一个典型的template模式, action是作为里面一个command运行的。Command模式也是用callback调用。关于这两种模式,google一下就清楚了。
Spring就是使用Template和callback模式,对底层实现做了统一封装,其中template负责那些通用的功能,如事务、资源管理、异常处理,callback则完成变化的那部分,如处理具体的数据库statement操作。我们最常用的HibernateCallback和 HibernateDaoSupport就体现了这一点,具体可参照其源码。
另外,对于Action,一定要注意线程安全的问题。Struts的action是非线程安全的,大家可以参考一个RequestProcessor中定义的Map类型的actions字段,而Webwork是线程安全的,因为其ActionContext是 ThreadLocal的,也就是说每个线程都有自己的变量,互不干扰。具体体现是Struts的Action里面不能有字段申明,只能有局部变量。而 Webwork可以,这对于获取页面表单数据非常方便。
6. 请求应答
在Action执行完毕后,我们应该为其导航到结果页面,
在webwork里面,也就是Result Type。它定义了好几种方式。比较有意思的是它处理象freemaker(html模板),XML/XSLT,PDF这些格式输出。而Struts基本上是很单一JSP。
而且webwork还可以自定义Result类型,可以为我们提供Swing、mobile客户端显示。
7. 异常处理
任何操作都有出错的可能,怎么优雅地处理错误,这也是每个框架都应该考虑的。
有一些异常处理最佳实践,《Effective Java》就专门有一章谈到。在OnJava上也有一篇文章:http://www.onjava.com/pub/a/onjava/2003/11/19/exceptions.html,非常值得一读。
1.选择Checked还是Unchecked
2.Exception的封装
3.如无必要不要创建自己得Exception
4.不要用Exception来作流程控制
5.不要轻易的忽略捕获的Exception
6.不要简单地捕获顶层的Exception
Struts和Webwork里面都支持异常处理,webwork是通过Interceptor支持的:ExceptionMappingInterceptor。
在我的项目实践中,我喜欢将业务异常封装在业务层,申明为checked Exception,web的Action必须捕获,获取exception的ErrorCode,此ErrorCode就是resource文件里面的 key,也就是说它支持多语言,如ErrorCode.USER_EXISTED=”error.user.userExisted”。这类信息应该是业务层抛出的。如果将它由action处理,这是一种设计上的错误。
8. 灵活性、扩展性、可插入性
作为框架,就应该保证其灵活,支持不同用户的业务需求;容易扩展其功能,插入系统级的功能。
就Struts而言,在可插入性上还是不错的,这得益于它的plug-in支持,实现其PlugIn接口,然后在其struts-config.xml文件中配置一下,如它的验证框架、网页布局Tiles,内存数据库,都是其典型应用。
另外,以前的Struts还可以扩展它的RequestProcessor,实现一些特有的功能,如日志、安全,因为它预留了一个缺省方法processPreprocess()。
Webwork也是高度可扩展的,它主要是通过实现Interceptor接口。
9. 模块、组件化
在大型web项目中,模块、组件这些概念就非常适用了,因为一个大的工程,可能由不同公司开发,或是不同项目组、不同成员协作开发,最后要很容易地集成在一起。另外,还有第三方公司开发的组件插入进来,如漂亮的web界面组件,如Tree、table等。
Tapestry就是一种基于组件的开发框架,不过我没有研究,呵呵。
但webwork确实可以支持,如xwork.xml 配置的package就是支持模块申明,其附带的FreeMaker就可以将开发好的模块打包成jar文件,在Servlet容器外加载。
JSF对组件支持是相当到位的。它所设计的目标,就是在IDE里面,直接拖拽web组件,象table,tree,就可以形成漂亮的界面,真正实现所见即所得。实现自己的组件,只要实现其UIComponent接口就行了。应该说JSF是一种非常有前途的Web层框架,它会把Web开发真正达到easy。因为直到现在,还没有一种框架能够很容易做到,它的界面开发始终没法和微软相提并论,虽然它有界面布局框架Tiles和SiteMesh,以及模板语言 Velocity、FreeMaker、Servlet2.4支持的EL。
不过遗憾的是,JSF开发工具还没有达到那么完善,除了Sun自己一直、推广的NetBeans IDE。Sun的官方有其demo,用flash演示,还是蛮cool的。
关于Ajax和请求模式
Ajax其实早在五年前就有了,只是没有被人注意罢了,直到2005年google把它应用在google map和gmail上,才开始被人关注。它也是web2.0时代一种重要的技术,ajax强调用户体验(XP)。因为它的本质就是一个异步调用。而我们的一般web页面请求都是同步的,你必须等到服务器全部处理完成。同步变异步,确实是一种革命,虽然它的技术很简单,只是一个XMLHttpRequest 的javascript对象。它让我们的Web版的Rich Client成为可能。Google现在正看到了web office的应用前景,对MS构成巨大威胁,大家可以试试它的Web版的excel和、日历、邮件,不久就会推出正式的web word,很cool。
另外,Ajax更接近实际的web请求,因为一般web请求时,每一次,我们获得的是整个页面内容,无论这个页面有多少数据是冗余的。譬如,我们分页浏览时,整个页面布局是由header,left navigator、footer组成,中间是content,翻页时,应该从服务器返回一个xml的用户列表数据格式,而且不包括html table的tag,这正是ajax另外一个方面:返回的是数据,而不是整个页面。这对于窄带宽,也是非常有益的。
Webwork的2.2.2版本支持ajax,底层是dojo和DWR这两个著名的ajax框架。但是webwork的ajax Tag做得太粗糙,用了ajax后,页面布局,特别是表单位置没法控制,而且对IE浏览器支持不够。我现在几乎都放弃了。
没有好的ajax框架,使得ajax开发起来很困难,也许因为它还不到一周岁吧。
我们现在的web框架,一般都是基于请求的模式,也就是说我们请求时总是会考虑它的目的URL,将提交数据保存在该请求中。这种模式,让我们开发时总在考虑这些所谓的http协议。一种完善的框架,应该尽量去屏蔽这些与底层协议相关的东西。
JSF给我们一种全新的方式,它让我们按照操作桌面应用,如Swing程序的方式处理网络请求,因为它是基于事件的。在Sun的petstore的WAF 框架中就有这种原始的思想。基于事件,让我们开发rich client提供了一种思想,但是,感觉和MS的asp.net相比,还是差很远。
事件驱动有一种核心的模式,那就是Observer模式,所谓的Observer就是listener(只是一个用眼睛,一个用耳朵,呵呵)。 Oberver是一种推(push)模式,也就是说事件Event发生时(如model发生改变),它会通知你,而不是你去取(拉模式)。
在Servlet规范中,也引入了listener的概念,如HttpSessionListener,它对于监视用户上线下线非常有帮助,它们是生命周期lifecycle的范畴。
发表评论
-
一个优秀的Java企业应用框架的设计和实现
2013-10-25 17:43 52一个优秀的Java企业应用框架的设计和实现: http:/ ... -
一个Java框架引发的思考:语言、框架、范式转换和软件生产力
2011-09-10 13:26 3691前几天,iteye上的pojo同学,发来了他四年前写的一个框架 ... -
电子商务网站,前后台是否该分离?
2011-08-21 12:44 8032做电子商务网站,一般 ... -
Java源码阅读的真实体会
2011-08-20 19:51 25745刚才在论坛不经意间,看到有关源码阅读的帖子。回想自己前几年,阅 ... -
我理解的互联网应用和企业应用开发
2011-07-12 12:01 3164前段时间,我写过一篇该主题的博客,但写完了,我觉得还是没有谈到 ... -
一个在读学生的疑问及我的回复
2011-06-24 11:39 3067我经常收到类似的站内信,然后花上半个来小时回复(我摆文字真的非 ... -
一位技术人员成长历程
2010-05-26 15:52 126054、坚持了第一个月,再坚持半年,以后的学习速度越来越快,你离 ... -
Java虚拟机技术总结(07年写的,原JavaEye精华帖)
2010-04-17 11:15 8349原文:IBM WebSphere Application Se ... -
IBM WebSphere Application Server 诊断和调优(07年写的,原JavaEye精华帖)
2009-12-19 11:07 8245这是上篇文章的续篇, ... -
JBPM源码浅析
2007-09-13 15:04 16430离职啦,工作交接中, ... -
JBPM阶段性工作总结
2007-09-12 15:20 14425快要离职了,工作交接 ... -
AIX学习总结笔记一
2007-07-03 18:07 8481公司项目用到AIX和Websphe ... -
软件开发的一点感想
2007-06-29 10:53 6053这两天,遇到工作中的两个小问题,加深了我以前对软件开发的看法。 ... -
Java线程安全系列(1)--Servlet线程安全
2007-06-16 23:19 13254刚才search的时候,竟然 ... -
从分布式系统的角度看REST
2007-05-28 20:37 3578原帖:http://www.iteye.com/t ... -
也说说项目成败、企业信息化
2007-05-19 15:25 2595这篇文章是我对nbsp同学 ... -
读HSQLDB的源码想到的
2007-05-17 10:36 9230昨天在论坛看到一篇讨 ... -
Web Services开发体会和项目教训
2007-04-21 14:42 52822去年,在一个大型项目( ... -
Seasar Framework介绍(一)
2007-04-21 00:18 10894近段时间,给公司一项 ... -
Struts的html:options 标签内幕
2007-04-20 18:14 7926最近用一个在日本很流 ...
相关推荐
Flask+Web开发实战的PDF资源提供了一个全面的学习路径,涵盖了从基础到高级的Flask应用开发。无论你是初学者还是有一定经验的开发者,这本书都能帮助你掌握Flask框架,并运用到实际项目中。通过实践,你将理解如何...
"web学习阶段性总结.zip"这个压缩包文件显然包含了一份关于HTML和CSS学习的总结,这将有助于巩固和复习相关知识。以下是这两门技术的核心要点: HTML(HyperText Markup Language)是网页内容的结构标准,它定义了...
在web项目开发中,流程的规范性和有效性是确保项目成功的关键。以下是对这些步骤的详细说明: 1. **SWOT分析**:这是项目启动的第一步,通过对系统的优势、劣势、机遇和挑战进行评估,确定项目的定位和目标。这涉及...
【企业级WEB开发资料】是一份综合性的资源集合,涵盖了企业级WEB开发的多个关键领域。这份资料旨在提供实用的技术开发方案,特别是针对JAVA设计与模式的深入理解,以提升开发人员在WEB应用开发中的专业技能。 在...
它结合了 Java Swing 的界面设计能力和 Web 技术的交互性,使得开发者能够开发出既具有丰富的图形用户界面(GUI)又能在网络上运行的应用程序。Swingweb 旨在简化开发流程,提高应用性能,并增强用户体验。 #### 2....
总的来说,这个Java Web开发总结大全覆盖了从基本的Web概念到核心的Java Web技术,对于初学者和有经验的开发者都是宝贵的资源。通过学习这些章节,开发者将能够熟练地创建、运行和调试Java Web应用,包括处理HTTP...
随着Java Web开发的复杂性增加,出现了许多优秀的开发框架,如Spring、Struts、Hibernate等,它们大大提高了开发效率,降低了维护成本。 - Spring:Spring是一个全面的后端开发框架,提供了依赖注入、AOP(面向切面...
【测试类型】在Web项目开发过程中,测试是一个至关重要的环节,它确保了系统的稳定性和可靠性。Web项目测试总结涵盖了多个方面,包括项目概述、测试情况、测试统计以及测试评价等,旨在全面评估项目的质量并提出改进...
总结来说,这个实验报告覆盖了Java Web开发的关键环节,从基础环境搭建到高级技术应用,旨在培养学生的实际开发技能和解决问题的能力。通过这四个实验,学生不仅可以掌握理论知识,还能获得宝贵的实践经验,为未来的...
要进行JSP开发,首先需要搭建一个运行环境,这通常包括Java Development Kit (JDK)、Web服务器(如Apache Tomcat)以及集成开发环境(IDE,如Eclipse或IntelliJ IDEA)。安装JDK后设置环境变量,接着下载并配置Web...
根据提供的文件信息,“孙卫琴 Tomcat与Java&Web开发技术详解.pdf”,我们可以总结出以下相关的IT知识点: ### 一、Tomcat服务器介绍 #### 1.1 Tomcat概述 Tomcat是由Apache软件基金会(ASF)开发的一款开源的...
【私人Web总结】 ...数据库服务器是一个提供数据存储服务的软件,可以创建多个数据库,每个数据库包含多张表,表是数据的逻辑组织单元,用于存储特定主题的数据。了解这些基本概念对于进行Web测试和开发至关重要。
1. 定义控件类:首先,你需要创建一个新的类,并让它继承自一个现有的Web控件基类,如WebControl或CompositeControl。 2. 添加属性:通过添加公共属性,你可以为控件定义可配置的特性。 3. 实现渲染:重写Render方法...
【测试工程师】在进行【WEB软件测试总结报告】时,主要关注了以下几个方面: 1. **BUG严重程度**:在测试过程中,发现的缺陷主要分为不同的严重级别。次要功能和轻微问题占据了大部分,总计37个,这表明软件在次要...
在本次的Web课程设计中,我负责开发了一个章节自测系统,旨在帮助学生进行阶段性的自我测试和练习。系统的核心架构基于MVC模式,利用JDBC进行数据库连接,并且使用MyEclipse作为集成开发环境。系统主要包含两个部分...
本文通过一个面向质检行业的Web系统实例,阐述了从需求分析到界面设计的全过程。 1. 工作流程: 界面设计始于需求分析阶段,设计师参与客户需求调研,然后在概要设计阶段制定设计方案,并在详细设计阶段完成界面...
总结,WEB开发平台系统V1.0是一个综合性的开发环境,特别适合于电子商务应用的构建。它通过集成化的设计、便捷的项目生成工具和强大的编辑器,降低了开发复杂性,提升了开发效率,同时通过与Java环境的融合,为...
通过本文对Servlet和JSP技术的深入讲解,我们可以看到这两种技术在Java Web开发中的重要地位。Servlet负责处理业务逻辑,而JSP则专注于展示数据。结合使用Tomcat作为部署平台,开发者可以构建出功能强大且易于维护的...