-
Notifications
You must be signed in to change notification settings - Fork 242
TechFeature
以下列举介绍框架中涉及到的主要技术选型设计原则,各技术组件具体版本信息请参考技术组件列表
核心模块级功能设计文档快速链接:
- 基于角色控制的权限设计 - 基于RBAC模型的基础权限管理设计实现
- 数据操作审计 - 基于Hibernate Envers的专业数据操作审计支持
- 报表功能展示 - 基于JasperReport的报表功能展示
- 定时任务动态配置管理 - 基于Spring Schedule & Quartz的支持集群和实时动态的定时任务配置监控
- 查询/分页/排序/分组汇总统计 - 强大而灵活的查询功能支持
- Grid组件功能 - 功能强大丰富的表格Grid组件封装增强
- 工作流引擎 - 基于Acitiviti的工作流引擎以支持业务流程处理
同时,强烈建议访问阅读SpringSide开源项目的技术选型说明和技术参考文档, 其中有不少内容和本文档内容有交叉,可有效辅助对以下部分技术说明的理解。
MVC Framework: 在Spring MVC横行的时代,依旧选择了Struts2,详见 Spring MVC vs Struts
Javascript Framework: 大量JQuery、Bootstrap等相关的Javascript插件整合应用。
Chart/Plot: 对于一些客户需要很炫的在线图表功能,虽然Flash不失为一个选择,但是更倾向于类似JQuery Flot这样的Javascript插件。
Grid/Table: 对于企业应用具有一个功能强大的表格Grid组件,无论对于开发和用户体验来说,都能起到事半功倍的效果。经过多个项目经验积累,框架选择了目前主流的JQuery jqGrid插件。该Grid组件功能非常丰富强大,除了一些分页、多字段排序等基础功能外,还包括诸如TreeGrid、SubGrid、AdvancedSearch、Group、ColumnChooser等众多高级特性,具体可参考其官方示例jqGrid Demo。
CSS Framework: 最热火的Twitter Bootstrap,提供了简便的布局能力和基本的页面美化。 并结合lesscss-maven-plugin实现构建过程自动基于less文件定义生成对应css文件支持。
Embedded Resource: 为了组件封装的目的尝试把JS、CSS和JSP等文件以Jar方式加载,或许有人用过Struts2 Embedded JSP Plugin, 不过如果你的项目的JEE Server(如Tomcat7+, Tomcat6不支持)支持新版的Servlet3.0 JSR315规范那就方便了,直接把相关JS、CSS和JSP等文件放到Jar文件的META-INF/resources目录下即可, 详见开发框架common-service的src/main/resources/META-INF/resources目录即一目了然,终于可以优雅的jar文件方式提供组件分发了。 当然如果你的项目应用服务器版本较低不支持这个特性也不用急,只需简单把resources目录下相关文件直接拷贝到常规的webapp目录下就行了。
JavaScript/CSS Compressor: 选择YUI Compressor。 并结合yuicompressor-maven-plugin实现构建过程对JS、CSS文件进行minify compressor处理。 这样有个好处是整个开发过程本地加载都是未经压缩处理的原始文件内容方便进行Debug问题对比分析,之后由Continuous Integration持续集成服务自动化处理相关资源优化,实现开发效率和运行效率的兼顾。 详见common-service工程pom.xml中文件定义。
REST: 虽然在Spring MVC vs Struts中自己已经提到对于企业应用来说REST意义不是那么明显,但是框架中还是有意以struts2-rest-plugin引入REST支持, 基本没有任何用到资源转换映射的特性,之所以引入主要是看上对于JSON响应输出的便捷支持, 并且借鉴SpringMVC里面的思想扩展添加NegotiationContentTypeHandlerManager实现根据Accept头信息动态选择对应的响应输出格式。
Struts2 Enhancement: 基于Struts2选型的扩展增强,详见Struts2 Enhancement
其他有关Web层技术选型可参考Web前端类组件列表
Spring Framework:对于这位JEE业界的主角就不用多说了。本开发采用最近的Spring3.1版本,也尽可能的运用其最新特性:
- 尽量采用以Annotation注解方式进行Bean组件的定义管理
- Spring Cache缓存支持,虽然Hibernate层面有强大的一级二级缓存支持,对于一些业务计算密度大的Service方法进行Spring Cache处理可以进一步优化系统运行效率。 示例可参考PrivilegeService中缓存受控权限列表的@Cacheable("SpringSecurityCache")注解方法
- Spring Task/Async任务/异步操作支持,只需简单的Annotation注解定义就可以获得强大的计划任务、异步调用等支持。示例可参考UserService中异步记录用户登录日志的@Async注解方法
在这里额外啰嗦一句,尤其注意在同一类中进行Transaction或Cache方法调用导致AOP失效的问题,没有理解到这一点常常会让开发人员以为遇到灵异事件, 具体可参考TRANSACTIONS, CACHING AND AOP: UNDERSTANDING PROXY USAGE IN SPRING
Security Framework: 虽然现在Apache Shiro以其优雅简洁而越发引入关注,不过鉴于自己对Spring Security多个项目的经验积累熟悉程度以及其功能强大的体验, 而且现在也收编到SpringSource名门麾下,那就它了吧。验证码那自然是主流的JCaptcha,并进行一定程度的样式扩展定义。
Report Support: 把Excel导出操作也看成是报表输出的一种常见形式,对此Apache POI是少不了的,在此基础上还选择了JXLS可以比较方便的以模板的形式进行Excel数据的导出导入操作,比起直接的POI API操作更简洁。 对于更专业复杂的报表需求,那自然需要专业的报表引擎和工具来支持,框架选择自己熟悉的JasperReport及其最新可视化建模工具Jaspersoft Studio,结合Struts集成、中文字体扩展、设计工具等整合,基本可以解决大部分企业报表需求。 同时可以再整合JasperReports Server实现一整套报表设计和部署运行服务。
Workflow Support: 整合集成最新的Activiti工作流引擎,开发阶段采用Eclipse插件进行流程设计, 框架提供一些基础管理功能,更强大完整的管理功能可借助部署activiti-explore实现在线的流程设计和管理;为了降低工作流与业务系统的耦合度,可以再借助activiti-rest以REST方式实现工作流引擎与业务流程的交互。
ORM Framework: 从封装程度来说,Hibernate > MyBatis > SpringJDBC,SpringJDBC应该只能算作是对JDBC的增强封装还算不上ORM,至于Hibernate和MyBatis(以前的iBatis),关于上述几者的对比讨论网上一搜一大把。 自己也是两种类型的项目都多次经历,经过权衡考虑,最终选择了JPA+Hibernate组合,几点理由:
- 一般来说封装程度越高性能损耗越大,不过借助Hibernate成熟的一二级缓存、懒加载等机制从很大程度可以弥补或超越MyBatis在性能上的优势
- 项目风险的可控性:采用MyBatis毫无疑问对整个团队开发人员对于SQL水平提出了较高的要求,而现实是一般项目团队中开发人员诸多是刚入行的新手,对此要求有点勉为其难甚至可能因为缺少严格的Review机制而蔓延成灾难; 而采用Hibernate一般只需项目团队中几个核心设计人员整体把控对象模型定义和优化策略设计,可以有效的把数据访问层性能风险控制在更小的范围
- Hibernate高效的设计和开发效率的确很诱人,便捷的Entity Annotation+hbm2ddl基本可以省却了专门的数据建模工具,当然对于大型项目需要一个完整的数据模型视图也可以基于Hibernate生成的数据结构逆向生成数据模型
- 随着JPA规范的流行,既能提升架构的规范性同时还能降低对特定ORM框架的依赖,Hibernate作为ORM家族的主角和JPA友好实现使其成为首选
- 尤其再加上Spring-Data-JPA,实现进一步提升DAO层开发效率,而且其方法名自解释数据访问逻辑的设计思想,也无形中提升了开发编码的规范性和清晰度
Query/Pagination/Sort: 框架基本打通前端UI到后端数据访问的动态参数/分页/排序整个环节,基本只需要少量的按照参数名称规则,对于Grid表格数据查询基本不用任何编码,即可实现非常灵活而强大的动态数据访问支持。基本流程是把Web前端传入的按照约定的参数集合转换为结构化查询对象,然后传入业务层组装为基于JPA Criteria语法的Spring JPA Data识别的动态查询对象,最终由Hibernate转换为底层数据库查询SQL语句。
Group/Aggregate: 除了基本的增删改查数据访问,对于企业应用系统还有一种很常见的分组聚合统计,例如需要把明细库存信息按照库存地/商品等不同维度进行分组汇总统计显示。为了简化此类需求的开发,框架做了一个基于JPA Criteria的进一步封装,前端层面只需简单传入需要分组和聚合规则的属性列表,即可返回与之对应便于用于JSON序列化的Map结构数据,最方便的是即便是聚合属性也能像常规的对象属性查询一样支持动态参数/分页/排序等特性。
Cache: 框架中在Spring和Hibernate层面都引入了Cache处理以最大化提升数据访问性能,采用主流的Ehcache,生产环境集群部署采用distribution配置模式。当然如果还需要进一步提升缓存效率和内存资源利用率,可以考虑引入中央式缓存架构。
Data Historical Audit:对于企业应用比较常见一个需求就是对于关键数据的变更过程进行历史版本记录以便支持对业务操作的追踪审计,通俗说就是:什么人在什么时间操作了什么数据,一方面可以防止用户对于业务操作的抵赖情况,一方面可以在遇到数据问题时有据可查。 Hibernate Envers对此提供了支持,基本思想就是每次数据保存操作时依靠Hibernate Event Listener方式自动把涉及的业务数据复制一份到对应的审计表中。 框架对此进行扩展设计,提供通用的审计数据列表和版本对比查看功能界面。
对于测试,无论如何强调其重要性都不为过,但是在具有中国特色的项目开发实施过程中要充分保证测试的完整和质量不是件容易的事,好像这已经超出开发框架探讨的范畴了。 不过实施的力度如何,还是建议项目团队至少做好以下三个方面:基础的Unit单元测试,每日构建的自动化测试,无法替代的人工功能测试。
Unit Testing: 典型的JUnit4+Spring-Test组合。基本的CRUD就不用逐一编写单元测试代码了,DAO层来说相对优先级低因为一般的DAO层问题都会传导到Service层, Web层测试就更加繁琐了有条件也可以考虑基于主流的Mock组件编写单元测试代码。因此Service应该是重点,一般建议对关键的、复杂的业务逻辑方法编写足够的单元测试代码以保证健壮性。 而且需要强调:所有单元测试代码都需要在自动化构建环境按计划运行,因此必须每个保证单元测试的独立可重复运行原则,不能简单在本地开发环境运行通过就认为没有问题。 具体可参考框架测试代码样例,同时框架简单的封装了一个以反射和随机方式构建测试Entity对象实现的帮助类,详见TestObjectUtils.java
Smoke Testing: 借助持续集成的自动化构建和测试过程,实现基本的应用部署冒烟测试,具体可参考showcase的pom.xml中的smoke profile定义和示意性的冒烟单元测试代码IndexSmokeMock.java。 通过此步骤可以确保持续构建生成的war包应用是基本可运行的应用,避免由于编译构建成功但是实际运行失败的应用部署到人工测试环境,从而减少不必要的人工测试中断影响。
Automation Testing: 如果项目组中条件允许,可以类似IndexSmokeMock单元测试编码方式,通过Selenium的FireFox插件录制一系列各业务功能的自动化测试脚本,然后配置到持续集成环境的自动化测试运行。 理论上自动化程度越高,所需投入的成本越大,但是同时会带来对人工测试的成本降低作用,但一般来说自动化测试和人工测试基本无法相互代替,需要在项目过程中摸索评估出一个相对平衡的方案。
JSON (De)Serialization:主要用在Web序列化输出JSON响应,Struts默认的JSON支持太弱了,Jackson功能强大,基于注解方式非常便捷,注意是2版本,Struts默认支持为Jackson 1版本,对此进行扩展增强,详见代码Jackson2LibHandler
Joda Time: 本来打算框架中直接采用以Joda Time日期时间类型作为Entity对象属性类型定义,后来发现在数据存取层面诡异的时区问题,而且还涉及一系列繁杂的JPA、JSON等数据类型兼容Annotation处理,干脆还是退回到标准的java.util.Date。 Joda Time的主要作为方便的日期时间工具类来用,如常用的日期加减比较等操作。
Logging: 最Fashion的Slf4j+Logback组合,再加上log4j-over-slf4j和jcl-over-slf4j兼容其他需要Log4J和Common Logging的第三方组件。
SQL Tracking: Hibernate虽然有个show_sql支持,不过其输出的一堆问号的预编译语句对于开发调试基本没啥太大意义。只有看到实实在在的数据库执行SQL语句才是王道。 目前框架引入log4jdbc-remix/log4jdbc主要看中其输出比较的SQL和ResultSet比较优雅直观些,并且额外扩展增强详见ExtSlf4jSpyLogDelegator实现及相关代码和配置。 此外P6Spy也是个不错的选择,尤其是结合SQL Profile或IronTrack SQL和Log4J的SocketAppender可以实现很全面的SQL性能跟踪调优分析。
Others:Apache Commons系列; [Guava]是(http://code.google.com/p/guava-libraries/) Google的帮助工具类等方便实用的组件运用在框架代码中随处可见
Eclipse IDE:既然走的Spring路线,那自然首选Spring Tool Suite
Source Version Control: 主流的源代码版本控制机制,SVN/GIT等大可根据自身项目情况选择即可
Apache Maven 3: 整个项目采用Maven进行工程依赖管理,目前熟悉在用Apache Maven3.0.X系列
Sonatype Nexus: 按照Maven风格管理配置的大型团队项目,如果让所有开发人员都在线去下载更新相关资源库组件就太低效了,因此在项目内部搭建Maven私服就显的很有必要了。 Sonatype Nexus提供的开源免费版本基本够用,当然如果要求更高可以选择付费专业版本。
Continuous Integration:对于大型团队开发项目,搭建自动化构建的持续集成环境那就更是非常有必要了。既能提早及时有效的发现开发过程中的Bug反馈,又能极大的规范和简化应用部署发布流程。 Jenkins(以前的Hudson),搭配丰富的插件,功能强大,方便好用。
Sonar (Code Quality Review): 对于一个人员众多大型的应用系统开发,一套有效的自动化代码质量检测评审工具既可以提升和规范整个团队的代码质量,也可以大幅减轻人工评审的工作量。SonarQube™ software (previously known as “Sonar”) is an open platform to manage code quality. 。当然,除了工具层面的自动化评审,定期的人工评审机制对于项目质量的保证还是很有必要的。
Unix/Linux Shell Scripts: 绝大部分情况J2EE应用都会部署在Unix/Linux操作系统环境,通过编写一些常用的Shell脚本可以有效的提高应用更新的效率和简化人工操作流程,尤其是在开发环境可以实现全自动更新部署。
以下首先列举本框架在自己开发过程中的相关环境以及实际在生产环境配置运行过的环境说明,鉴于Java多元化运行环境支持和Hibernate通用数据库支持,应该是能支持绝大部分主流J2EE运行环境的,具体可自行测试部署。
-
JDK:JDK6,理论应该JDK5+都可。注意:目前已知JDK8报错,暂时还没进行兼容性分析处理。建议采用JDK6或JDK7
-
System:主流支持Java运行的操作系统皆可部署运行,目前已在CentOS Server/Ubuntu Server等主流Linux操作系统生产环境运行
-
J2EE Server:vfabric-tc-server-developer-2.7.2.RELEASE(基于Tomcat7)或Jetty,其他测试运行过的包括Tomcat 7,Weblogic 10g
-
Database: 开发样例采用H2 Database嵌入数据库,其他测试过包括MySQL5,Oracle 10g,SQL Server 2008