如何搭建合适的Web框架?( 二 )

  • Service、DAO为什么要编写接口 , 再去实现这个接口?
  • 接口和实现在相同的模块下 , 反正都要重新打包的 。多写个接口不是多写了好几行代码吗?
  • 和上面类似的问题 , Mybatis里面 , 声称将sql独立到了Mapper.xml文件中 , 使得可以不需要编译直接修改sql 。但Mapper.xml都是和Class放在一起的 , 改了还是需要重新打包 , 而且Mybatis是不能动态加载Mapper.xml的 , 那把sql独立到XML里 , 到底有什么优势?
  • 对于最后一个问题 , 我的答案是 , 对于大部分项目来说 , 没什么优势!项目易不易于部署、扩展 , 不在于你使用的框架 , 而在于你的设计 。
    就以Mapper.xml来说 , Mybatis将sql与代码分离了 , 但是你在项目里还是将Mapper.xml和代码放在同一个模块下 , 那这个优势就没有了 。既然没有这个优势 , 我们还有必要单独写Mapper.xml文件吗?我的选择是 , 那就不写了 , 直接使用Mybatis提供的注解 。
    同时为了解决Service层对DAO层(这里也就是对Mybatis)的强依赖 , 对框架进行了一些改进 , 解耦Service和DAO层 。具体见下面的改进方案 。
    框架改进方案为了解决上面这些问题 , 对框架进行了如下调整:
    • 分离Param、Result和Model
    • 替换代码生成
    • 独立业务逻辑
    • Model层优化
    分离Param、Result和Model
    上面已经提到了Param、Result和Model强耦合会有很多问题 , 所以这里就将Param、Result和Model分离开 。每个都是独立的Bean , 这就解决了上面几个问题 。但是引入了两个新问题:
    • 首先 , 很明显的 , 增加了手动编码的量 。当一个表修改了字段 , 需要修改三个类甚至更多的类
    • 其次 , 增加了数据传递之间的代码 。即Param传递到Model , 需要对字段赋值 。如果一个字段一个字段的设值 , 会增加很多无聊的代码 。而使用反射的话会对性能有一些影响
    那如何解决这两个问题呢?首先 , 纯手撸肯定是不可能的 。需要提供一些自动化手段 。
    对于赋值来说 , 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的组合要高于代码生成组件的: