上周EasyJWeb-1.0m3版本发布,收到几封来信,其中有两封提到EasyJWeb相对于struts2这个web MVC框架有哪些优势。这两天在编《EasyJWeb实用开发指南》,因此,整理了一下其中的一些内容,对其中的一些关键作了一个简单的比较,希望对于想了解EasyJWeb及Struts2这两个框架的朋友有所帮助。
一、总体概述
1、都是基于java的开源web mvc框架,而且都是基于请求转发模型的mvc框架,这一点与jsf这种基于组件模型的框架不同。
2、EasyJWeb是在综合struts1.x、webwork、Tapestry、springmvc、rails等框架发展而来,是EasyJF开源团队的一个项目,开发成员全部是中国人;而struts2是在webwork2的基础上发展而来,当然也参考了很多mvc框架,是apache的一个开源项目,开发成员来自世界各地。
3、EasyJWeb表示层主要推Velocity、CommonTemplate这样的模板引擎,而Struts2视图层主要推jsp2。当然,两者都可以表示层切换到其它一些视图技术,只需要增加相应的结果处理引擎即可。
4、EasyJWeb的文档、代码注释、提示信息等主要以中文为主;而struts2是以英文为主。
5、都是一个能让你快速开发企业级java web应用的框架。
宏观的东西不多说,大的用法大家可以从两个框架与JPA+Spring结合实现的添删改查实例进行简单的对比分析。你可以直接通过下面的链接了解更多的内容:
开始EasyJWeb 源码下载
实现一个简单的添删改查 源码下载
Easyjweb+Spring2+JPA 实现一个基本CRUD应用示例 英文版
Struts 2 + Spring 2 + JPA + AJAX
Struts2官方文档
Migrating Struts Apps to Struts 2
二、配置
1、零配置
EasyJWeb与struts2都支持零配置,这里的零配置就是指只需要修改web.xml,而不需要写任何EasyJWeb或Struts2的配置文件,零配置的情况下需要为框架指明到哪儿去扫描Controller(Action)类。分别如下:
EasyJWeb的web.xml
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
Struts2的web.xml
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
2、惯例代替配置
EasyJWeb中大量使用了惯例代替配置的机制,把应用程序按模块进行划分,惯例代替配置包含页面视图模板的查找,多国语言属性文件的查找、依赖注入等,已经在很多项目中成功应用。struts2也使用了一些惯例代替配置,但不知道能否用于实际开发。
3、框架配置文件
两个框架都可以有自己的配置文件,通过配置文件来提高系统的可维护性。EasyJWeb的配置文件中可以定义系统中的模块Module(相当于控制器或Action)、页面模板视图Page等MVC框架特有的属性,另外还可以配置业务组件<bean>、拦截器、异常处理器、及依赖注入,配置将要支持远程Web调用服务的Ajax业务组件等;EasyJWeb的配置文件功能更广,初学有一点大杂烩的感觉。
Struts2的配置文件同样可以用来配置Action、页面导向、拦截器,也可以配置业务组件Bean等,这一点跟EasyJWeb非常类似。采用分包及拦截器链的方式组织应用程序中的各个部件。
EasyJWeb配置文件中配置Bean
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
Struts2配置文件中配置Bean
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
三、控制器Action
两个框架的控制器在默认情况下都是线程安全的,而且都不依赖于具体的类。EasyJWeb默认的处理器实现要求Actionn必须实现IWebAction接口,而Struts2可以不需要。如下:
EasyJWeb中的Action
![](http://img.e-com-net.com/image/product/0fb6e2b4c32f479da39f54e5c8b4890d.gif)
![](http://img.e-com-net.com/image/product/5d71ea316b96431990b91a03b2f090bb.gif)
![](http://img.e-com-net.com/image/product/9e7f8c1d826f487fb4c8138af539c3e4.gif)
![](http://img.e-com-net.com/image/product/7c85a012ce3449989f24337e8e369d5f.gif)
![](http://img.e-com-net.com/image/product/676e9d2fc4ab4565a433d97564e8b037.gif)
![](http://img.e-com-net.com/image/product/676e9d2fc4ab4565a433d97564e8b037.gif)
![](http://img.e-com-net.com/image/product/676e9d2fc4ab4565a433d97564e8b037.gif)
![](http://img.e-com-net.com/image/product/422034fff1bc4f568d8d1890a6b7b3f4.gif)
![](http://img.e-com-net.com/image/product/1ba03523890140d392c6b3d7a94787f9.gif)
Struts2中的Action
![](http://img.e-com-net.com/image/product/0fb6e2b4c32f479da39f54e5c8b4890d.gif)
![](http://img.e-com-net.com/image/product/5d71ea316b96431990b91a03b2f090bb.gif)
![](http://img.e-com-net.com/image/product/9e7f8c1d826f487fb4c8138af539c3e4.gif)
![](http://img.e-com-net.com/image/product/7c85a012ce3449989f24337e8e369d5f.gif)
![](http://img.e-com-net.com/image/product/676e9d2fc4ab4565a433d97564e8b037.gif)
![](http://img.e-com-net.com/image/product/422034fff1bc4f568d8d1890a6b7b3f4.gif)
![](http://img.e-com-net.com/image/product/1ba03523890140d392c6b3d7a94787f9.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
当然,这个祼体Action基本上没任何作为,真正的Struts2版本的HelloAction可以写成如下:
![](http://img.e-com-net.com/image/product/0fb6e2b4c32f479da39f54e5c8b4890d.gif)
![](http://img.e-com-net.com/image/product/5d71ea316b96431990b91a03b2f090bb.gif)
![](http://img.e-com-net.com/image/product/676e9d2fc4ab4565a433d97564e8b037.gif)
![](http://img.e-com-net.com/image/product/9e7f8c1d826f487fb4c8138af539c3e4.gif)
![](http://img.e-com-net.com/image/product/7c85a012ce3449989f24337e8e369d5f.gif)
![](http://img.e-com-net.com/image/product/676e9d2fc4ab4565a433d97564e8b037.gif)
![](http://img.e-com-net.com/image/product/422034fff1bc4f568d8d1890a6b7b3f4.gif)
![](http://img.e-com-net.com/image/product/9e7f8c1d826f487fb4c8138af539c3e4.gif)
![](http://img.e-com-net.com/image/product/7c85a012ce3449989f24337e8e369d5f.gif)
![](http://img.e-com-net.com/image/product/676e9d2fc4ab4565a433d97564e8b037.gif)
![](http://img.e-com-net.com/image/product/676e9d2fc4ab4565a433d97564e8b037.gif)
![](http://img.e-com-net.com/image/product/676e9d2fc4ab4565a433d97564e8b037.gif)
![](http://img.e-com-net.com/image/product/422034fff1bc4f568d8d1890a6b7b3f4.gif)
![](http://img.e-com-net.com/image/product/1ba03523890140d392c6b3d7a94787f9.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
另外,还需要在struts2的配置文件中增加大致如下的配置来指明这个success字符对应的文件路径:
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
但实际应用中,EasyJWeb的Action大多数都直接继承AbstractPageCmdAction,因为这个基础控制器提供了很多非常强大的功能,比如按惯例查找页面、灵活页面跳转及视图切换,动态特性的命令方法。同样为了使用Struts2中的很多功能,比如拦截器、依赖注入等都需要Action实现指定的接口,更多的时候直接继承ActionSuport类。
也就是说,一个半祼或全祼的Action在实际应用中很少用到。
四、依赖注入
两个框架都实现了依赖注入,都能自动往Action中自动注入所需要的业务组件。EasyJWeb的依赖注入直接依靠他内置的IoC容器,而Struts2的依赖注入依靠拦截器ActionAutowiringInterceptor进行注入。EasyJWeb的依赖注入是真正实现不要任何配置就能自动注入应用程序中各层(业务层、持久层等)中用到的业务组件的,你可以通过这个简单的添删改查实例来看见效果。
两者都可以直接借助第三方的IoC容器如Spring。下面是在EasyJWeb中使用Spring容器,需要在EasyJWeb的配置文件中加入下面的配置:
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
Struts2可以使用代理的方式,先在web.xml文件中通过下面的配置启动spring容器:
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
然后在struts的配置文件使用指定struts.objectFactory为spring即可。
<constant name="struts.objectFactory" value="spring" />
另外一点区别是,EasyJWeb的Action都是由EasyJWeb的IoC容器管理,不需要用其它容器来管理,因为EasyJWeb的IoC容器会把其它容器中的业务组件注入到Action的相应属性中,你可以把业务组件同时放在EJB容器、Spring容器、或者Guice容器中。
关于如何在EasyJWeb中使用Guice容器,请参考>>
五、数据的处理
两个框架都抛弃了Struts1.x中那种需要借助ActionFrom来处理数据的机制,而采用更为先进的注入方式。EasyJWeb中的WebForm中提供了一个toPo方法,用来处理数据注入。
比如,为了在Action中注入Person对象:
EasyJWeb的Action代码中直接使用toPo方法手动注入,如:
![](http://img.e-com-net.com/image/product/0fb6e2b4c32f479da39f54e5c8b4890d.gif)
![](http://img.e-com-net.com/image/product/5d71ea316b96431990b91a03b2f090bb.gif)
![](http://img.e-com-net.com/image/product/676e9d2fc4ab4565a433d97564e8b037.gif)
![](http://img.e-com-net.com/image/product/676e9d2fc4ab4565a433d97564e8b037.gif)
![](http://img.e-com-net.com/image/product/9e7f8c1d826f487fb4c8138af539c3e4.gif)
![](http://img.e-com-net.com/image/product/7c85a012ce3449989f24337e8e369d5f.gif)
![](http://img.e-com-net.com/image/product/676e9d2fc4ab4565a433d97564e8b037.gif)
![](http://img.e-com-net.com/image/product/422034fff1bc4f568d8d1890a6b7b3f4.gif)
![](http://img.e-com-net.com/image/product/9e7f8c1d826f487fb4c8138af539c3e4.gif)
![](http://img.e-com-net.com/image/product/7c85a012ce3449989f24337e8e369d5f.gif)
![](http://img.e-com-net.com/image/product/676e9d2fc4ab4565a433d97564e8b037.gif)
![](http://img.e-com-net.com/image/product/676e9d2fc4ab4565a433d97564e8b037.gif)
![](http://img.e-com-net.com/image/product/676e9d2fc4ab4565a433d97564e8b037.gif)
![](http://img.e-com-net.com/image/product/422034fff1bc4f568d8d1890a6b7b3f4.gif)
![](http://img.e-com-net.com/image/product/1ba03523890140d392c6b3d7a94787f9.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
对应的表单是普通的html表示,如下所示:
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
Struts2中则不需要写代码,只需要把要注入的数据在Action中准备好即可,如:
![](http://img.e-com-net.com/image/product/0fb6e2b4c32f479da39f54e5c8b4890d.gif)
![](http://img.e-com-net.com/image/product/5d71ea316b96431990b91a03b2f090bb.gif)
![](http://img.e-com-net.com/image/product/676e9d2fc4ab4565a433d97564e8b037.gif)
![](http://img.e-com-net.com/image/product/676e9d2fc4ab4565a433d97564e8b037.gif)
![](http://img.e-com-net.com/image/product/676e9d2fc4ab4565a433d97564e8b037.gif)
![](http://img.e-com-net.com/image/product/9e7f8c1d826f487fb4c8138af539c3e4.gif)
![](http://img.e-com-net.com/image/product/7c85a012ce3449989f24337e8e369d5f.gif)
![](http://img.e-com-net.com/image/product/676e9d2fc4ab4565a433d97564e8b037.gif)
![](http://img.e-com-net.com/image/product/422034fff1bc4f568d8d1890a6b7b3f4.gif)
![](http://img.e-com-net.com/image/product/676e9d2fc4ab4565a433d97564e8b037.gif)
![](http://img.e-com-net.com/image/product/9e7f8c1d826f487fb4c8138af539c3e4.gif)
![](http://img.e-com-net.com/image/product/7c85a012ce3449989f24337e8e369d5f.gif)
![](http://img.e-com-net.com/image/product/676e9d2fc4ab4565a433d97564e8b037.gif)
![](http://img.e-com-net.com/image/product/676e9d2fc4ab4565a433d97564e8b037.gif)
![](http://img.e-com-net.com/image/product/422034fff1bc4f568d8d1890a6b7b3f4.gif)
![](http://img.e-com-net.com/image/product/9e7f8c1d826f487fb4c8138af539c3e4.gif)
![](http://img.e-com-net.com/image/product/7c85a012ce3449989f24337e8e369d5f.gif)
![](http://img.e-com-net.com/image/product/676e9d2fc4ab4565a433d97564e8b037.gif)
![](http://img.e-com-net.com/image/product/676e9d2fc4ab4565a433d97564e8b037.gif)
![](http://img.e-com-net.com/image/product/676e9d2fc4ab4565a433d97564e8b037.gif)
![](http://img.e-com-net.com/image/product/422034fff1bc4f568d8d1890a6b7b3f4.gif)
![](http://img.e-com-net.com/image/product/9e7f8c1d826f487fb4c8138af539c3e4.gif)
![](http://img.e-com-net.com/image/product/7c85a012ce3449989f24337e8e369d5f.gif)
![](http://img.e-com-net.com/image/product/676e9d2fc4ab4565a433d97564e8b037.gif)
![](http://img.e-com-net.com/image/product/422034fff1bc4f568d8d1890a6b7b3f4.gif)
![](http://img.e-com-net.com/image/product/9e7f8c1d826f487fb4c8138af539c3e4.gif)
![](http://img.e-com-net.com/image/product/7c85a012ce3449989f24337e8e369d5f.gif)
![](http://img.e-com-net.com/image/product/676e9d2fc4ab4565a433d97564e8b037.gif)
![](http://img.e-com-net.com/image/product/422034fff1bc4f568d8d1890a6b7b3f4.gif)
![](http://img.e-com-net.com/image/product/1ba03523890140d392c6b3d7a94787f9.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
对应的表单如下所示:
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
当然,Struts2关于数据转换方面提供了很多可供选择,比如也可以实现ModelDriven接口提供getModel来按指定的规则注入模型数据。
对于关联对像的加载及注入,比如Person中的Department属性,EasyJWeb只需要在属性上加上一个@POLoad标签即可,而struts2则不能。
六、其它
1、验证处理
EasyJWeb提供了一个基于注解标签实现的灵活框架,可以直接在要验证的数据对象(一般是模型对象)中直接添加验证标签来实现验证,另外在Action中加入自定义的验证内容也非常容易,只需要使用addError方法即可。当前EasyJWeb-1.0m3只支持通过注解的方式验证。
Struts2的验证框架结合了Strut1.x及webwork,可以直接使用验证标签来标注验证,也可以使用xml文件来配置验证规则及验证目标对象。
EasyJWeb的验证标签:
@Validator(name=”string”,value=”blank;trim;required;min:5;max:10;minMsg:最少不能少于5个字符;maxMsg:最大不能超过10字符”)
更多参考:http://www.easyjf.org/html/20070822/12867758-1954570.htm
Struts2的验证配置,
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
![](http://img.e-com-net.com/image/product/ff68a22582454f78825e64e5346ca758.gif)
更多参考:http://struts.apache.org/2.x/docs/validation.html
2、ajax支持 Struts2提供对dojo的全面支持及封装,提供了一套富组件的支持,并且可以在自定义标签中指定form以ajax方式提交表单等,功能较为完善。
EasyJWeb则提供了一个类似DWR框架的Ajax实现,可以用于直接把业务层对象发布到客户端通过json调用,对于Ajax提交及页面部分刷新等则直接在页面中调用EasyAjaxUtil这个实用工具中的ajaxSubmit、loadPage等方法实现。相对来说EasyJWeb的Ajax支持还有待进一步完善。
3、开发效率
EasyJWeb的目标在于提高开发效率,整个项目除了核心MVC部分以外,在easyjweb-ext-xx.jar包中还提供了一些通用业务逻辑,如Crud应用、添删改查、基于JPA+Spring2的泛型DAO支持、分页处理引擎等,可以在程序中直接使用;另外在easyjweb-generator-xx.jar包中提供了基于模板的代码生成引擎,可以快速生成基于EJS(EasyJWeb+JPA+Spring2)的Crud应用。
Struts2有着众多的第三方支持,官方网站上提供了一些应用骨架可以直接使用,另外还可以使用AppFuse等这个第三方框架生成基于Struts2的应用。
4、文档
Struts2的文档非常全,也比较系统,关于struts2的书也可以在市场上买到,但EasyJWeb在这方面由于参与贡献的人少,因此文档及教程相对来说就如很多网友说的:“还存在很多问题”,这里也邀请广大的国内开源爱好者一起来参与完善EasyJWeb的文档完善。
另外,EasyJWeb及Struts2都还具有其它自己很多独特的优点。总的来说,对于框架的选择应该是多方面考虑的,没有绝对的谁好或者谁坏,更应该是顺手适用才行,如果你愿意,继续使用Struts1.x两三年也没问题。由于本人对Struts2应用得不够多,所以文中一些不足或偏颇之处,还请各位朋友不吝赐教。
by EasyJF开源 大峡