之前在Web开发框架推导一文中我们一步步的搭建了一个开发框架。
成都创新互联是创新、创意、研发型一体的综合型网站建设公司,自成立以来公司不断探索创新,始终坚持为客户提供满意周到的服务,在本地打下了良好的口碑,在过去的10年时间我们累计服务了上千家以及全国政企客户,如软装设计等企业单位,完善的项目管理流程,严格把控项目进度与质量监控加上过硬的技术实力获得客户的一致赞扬。
在当时的情况下,还算满足需求。但是随着项目的逐渐完善,需求变更的频度逐渐变得比新增需求的频度高,原来框架的弊端越来越明显,所以需要对框架进行升级改进。
我们先来看原来框架的问题,然后基于这些问题,来对框架进行改进。
代码生成问题
在原框架中,我们基于各种约束,编写了一个代码生成组件,通过这个组件,我们可以针对选中的表来生成Controller,Service,Model,Mapper等一系列的类,也就是说,只要建完表,就可以直接生成一套CRUD,直接就可以启动并测试。这在项目初期看起来很美,但是在需求变动时,还是有很多的局限性。
首先,生成的代码逻辑是固化的。如果稍微有些调整,就需要调整生成代码的组件,然后重新打包,上传到jar仓库,项目修改组件版本,再进行代码生成,整个流程过于繁琐。
其次,为了方便代码的生成,其实是做了不少妥协的:
参数传递问题
当初为了便于代码的生成,决定Param和Result都继承Model,这导致了如下的一些问题:
Service层问题
Service层有如下问题:
- // PostService
- public String savePost(Post post) {
- postRepository.save(post);
- for(PostDiscuss discuss : post.getDiscuss()) {
- // 这里是抓不到RuntimeException异常的,会是一个TransactionRollBack的异常
- discussService.save(discuss);
- }
- }
- // discussService
- public String savePost(PostDiscuss discuss) {
- throw new RuntimeException("保存失败");
- }
测试依赖问题
核心的业务逻辑在Service中,测试还是需要依赖于Spring,当项目越来越大时,启动项目的时间越来越长,可能要1分钟甚至更长。这就导致单元测试效率越来越低。
Mapper.xml的问题
在面试的时候,我经常会问下面的一些问题:
对于最后一个问题,我的答案是,对于大部分项目来说,没什么优势!项目易不易于部署、扩展,不在于你使用的框架,而在于你的设计。
就以Mapper.xml来说,Mybatis将sql与代码分离了,但是你在项目里还是将Mapper.xml和代码放在同一个模块下,那这个优势就没有了。既然没有这个优势,我们还有必要单独写Mapper.xml文件吗?我的选择是,那就不写了,直接使用Mybatis提供的注解。
同时为了解决Service层对DAO层(这里也就是对Mybatis)的强依赖,对框架进行了一些改进,解耦Service和DAO层。具体见下面的改进方案。
为了解决上面这些问题,对框架进行了如下调整:
分离Param、Result和Model
上面已经提到了Param、Result和Model强耦合会有很多问题,所以这里就将Param、Result和Model分离开。每个都是独立的Bean,这就解决了上面几个问题。但是引入了两个新问题:
那如何解决这两个问题呢?首先,纯手撸肯定是不可能的。需要提供一些自动化手段。
对于赋值来说,Spring提供了BeanUtils来简化处理,虽然是基于反射来设值的,但是对于现阶段来说,这点性能损耗还是没什么影响的。但是,BeanUtils对于不同类型的属性不能进行拷贝,假设我有一个Domain对象Book,里面有个字段Author,现在我要赋值给BookResult,其中有个字段AuthorResult,此时BeanUtils是无法赋值的。所以我编写了一个基于Gson的工具类来处理,性能测试10000次的属性拷贝BeanUtils需要500多毫秒,基于Gson的工具类只需要300毫秒左右。
对于表字段的生成,如果使用的是IDEA的话,IDE默认提供了一个脚本,可以从表来生成POJO!我们可以使用这个脚本来生成Model,然后将字段拷贝到Param和Result中,来简化字段的编写。我对这个脚本进行了修改,以符合项目需求。主要增加了lombok的支持,新增了类注释和字段注释。
替换代码生成
对于上面代码生成组件的问题,我调整了代码生成的方式。不再基于组件来生成,而是基于IDEA本身的FileTemplate、LiveTemplate以及Scripted Extensions来进行生成。虽然这样的方式,不能够一次性生成多个文件,但是由于生成逻辑基本是一次性的,所以影响不是很大。在初次生成代码时,代码生成组件的效率是高于FileTemplate、LiveTemplate以及Scripted Extensions的组合,但是后期调整的灵活性,明显是FileTemplate、LiveTemplate以及Scripted Extensions的组合要高于代码生成组件的:
具体的操作流程,在下面演示。
独立业务逻辑
针对Service和测试的问题,将原来的Controller、Service和Model三层,拆分为四层:
这样Service的职责减轻了,同时不再有事务嵌套的问题。
Model层优化
上面提到,框架中最终放弃了Mapper.xml,转而使用Mybatis的注解来实现持久化操作。改用注解,规避了XML代码的编写,但是并没有解决框架对Mybatis的强依赖。所以这里在Domain中新增了Repository接口层,此层用于定义Domain的持久化操作,而Model层中对Repository进行实现,这里的实现就是Mybatis实现。这样做有两个好处:
现在已经知道了,如何对框架进行改进,我们现在就开始着手进行改造。其实主要的改造是对代码生成方式的改造,也就是编写FileTemplate、LiveTemplate和ScriptedExtensions。下面对这三个功能进行简单的说明,先说ScriptedExtensions。
Scripted Extensions
先来解释一下,什么是Scripted Extensions。我们都知道,现在的IDE都是插件式的,也就是说,我们可以通过开发商提供的插件开发包来开发插件,扩展现有的IDE功能。但是编写插件需要特定的开发环境,如果是一个很简单的功能,还要费劲去搭开发环境,挺麻烦的。所以IDEA提供了Scripted Extensions,可以理解为一个简化版的插件,就是可以通过脚本来扩展IDE功能。
IDEA提供了Database功能,可以连接数据库进行相关操作。当你连接了数据库,在表上右击时,可以看到Scripted Extensions这个选项,里面有一个功能是可以基于表来生成POJO的groovy脚本。
但是功能比较low:
不过好在,我们能基于这个脚本来自行修改,在刚才的Scripted Extensions菜单里,有个Go to Scripts Directory选项,点击后,可以进入脚本目录。
直接对这个groovy文件Ctrl+c,Ctrl-v,复制一份,重命名一下,基于这个脚本进行修改即可。具体怎么修改,按照自己的需求来,里面主要就是根据表信息对String的拼接而已。
FileTemplate
FileTemplate是IDEA提供的生成文件的模板,你在点击菜单的File->New...以后,出现的各种文件,都是基于FileTemplate来实现的。我们自定义的Controller、Service、Domain等类,都可以通过FileTemplate来简化创建。
具体使用方式为,按下Ctrl-Alt-S呼出设置菜单,点击Editor->File And Code Template,在里面新增Template即可。
几点说明:
创建完成后,就可以在New菜单中看到这个模板了。
LiveTemplate
LiveTemplate实际就是CodeSnippet。创建方式和FileTemplate类似。按下Ctrl-Alt-S呼出设置菜单,点击Editor->Live Template,在里面新增Template即可。
几点说明:
编码流程
创建了上面的几个模板后,编码流程如下:
本文通过对原框架问题的梳理及解决,来对框架进行升级改造,以适应项目的发展和推进。
文章名称:如何搭建合适的Web框架?
文章起源:http://www.gawzjz.com/qtweb2/news37/25837.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联