我的编程空间,编程开发者的网络收藏夹
学习永远不晚

如何搭建合适的Web框架

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

如何搭建合适的Web框架

如何搭建合适的Web框架,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

之前在Web开发框架推导一文中我们一步步的搭建了一个开发框架。

如何搭建合适的Web框架

在当时的情况下,还算满足需求。但是随着项目的逐渐完善,需求变更的频度逐渐变得比新增需求的频度高,原来框架的弊端越来越明显,所以需要对框架进行升级改进。

我们先来看原来框架的问题,然后基于这些问题,来对框架进行改进。

原框架的问题

代码生成问题

在原框架中,我们基于各种约束,编写了一个代码生成组件,通过这个组件,我们可以针对选中的表来生成Controller,Service,Model,Mapper等一系列的类,也就是说,只要建完表,就可以直接生成一套CRUD,直接就可以启动并测试。这在项目初期看起来很美,但是在需求变动时,还是有很多的局限性。

首先,生成的代码逻辑是固化的。如果稍微有些调整,就需要调整生成代码的组件,然后重新打包,上传到jar仓库,项目修改组件版本,再进行代码生成,整个流程过于繁琐。

其次,为了方便代码的生成,其实是做了不少妥协的:

  • 为了方便在修改表字段以后,能够重新生成,很多类都抽象了一个基类用于操作Model字段。这些基类不能够手动修改,因为每次生成都会覆盖。这实际导致了类的数量的增多。

  • 生成的CRUD固化了,不能手动调整。如果生成的CRUD不满足需求,不能直接在代码上修改。只能拷贝一份进行修改,因为再次生成时会覆盖。这导致了代码的冗余。

  • Param和Result委托了Model,这在Model发生改变时,能在编译期就能知道对应字段的调整。但是也引入了不少问题,我们在「参数传递问题」一节单独讨论。

参数传递问题

当初为了便于代码的生成,决定Param和Result都继承Model,这导致了如下的一些问题:

  • 使得Param和Result都依赖了Model。但是Param和Result是视图层模型,而Model是持久层模型,两者的进化度并不是一致的。但是现在的继承关系导致了在默认情况下视图层模型的进化需要和持久层同步,当然你也可以手动调整Param和Result,但是这又导致了代码生成的优势没有了。

  • Param和Result通过委托的方式来设置字段,也就是说,它们实际是没有字段的,通过getter和setter将值设置到了Model中。这就没法使用lombok来简化getter和setter,使得Param和Result代码行数较多

  • 同时,对于swagger来说,有些注解需要基于字段,导致某些功能无法实现(例如:ModelAttribute),只能基于额外手段来处理(例如:需要通过ApiImplicitParams来实现字段文档)。

  • CRUD都是基于同一个Param和Result,导致前端的接口会显示很多无用的字段,加大前端理解接口的难度

Service层问题

Service层有如下问题:

  • Service层的职责过重,包括了事务处理、参数设置、业务逻辑

  • 导致Service中的代码是面条代码,不利于业务逻辑的理解

  • 同时事务注解是直接加在类上的,Spring的默认事务机制会导致类似如下代码的逻辑调用不会抛出期望的异常

// 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的问题

在面试的时候,我经常会问下面的一些问题:

  • Java里面接口的作用是什么?

  • 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的组合要高于代码生成组件的:

  • 首先,当文件结构调整时,只需要修改FileTemplate,并将配置文件导出给项目组成员即可。

  • 同样的,当LiveTemplate调整时,也只需要修改对应的LiveTemplate,并将配置文件导出给项目组成员即可。

  • 其次,想生成哪个文件,只要针对这个文件生成即可

  • 第三,通过FileTemplate生成完整的文件后,可以通过LiveTemplate快速的进行模块化的编码

  • 最后,FileTemplate可以设置为项目级别,即每个项目可以有独立的FileTemplate

具体的操作流程,在下面演示。

独立业务逻辑

针对Service和测试的问题,将原来的Controller、Service和Model三层,拆分为四层:

  • Controller负责前端数据的接收和返回,以及统一异常处理

  • Service负责事务以及Domain层逻辑的组装。这里就不会出现事务嵌套问题,也就不会导致抓不到期望的异常的问题

  • Domain负责业务逻辑

  • Model负责数据持久

这样Service的职责减轻了,同时不再有事务嵌套的问题。

Model层优化

上面提到,框架中最终放弃了Mapper.xml,转而使用Mybatis的注解来实现持久化操作。改用注解,规避了XML代码的编写,但是并没有解决框架对Mybatis的强依赖。所以这里在Domain中新增了Repository接口层,此层用于定义Domain的持久化操作,而Model层中对Repository进行实现,这里的实现就是Mybatis实现。这样做有两个好处:

  • 依赖倒置:原来是Domain依赖Model层,而现在是Model层依赖Domain层,这样当我要把Mybatis替换掉时,Domain完全无感知。

  • 独立测试:因为现在Domain不依赖于其它任何层,所以可以脱离数据库和容器来进行测试。使得测试的效率不会随着项目的开发而越来越低

如何搭建合适的Web框架

框架改进细节

现在已经知道了,如何对框架进行改进,我们现在就开始着手进行改造。其实主要的改造是对代码生成方式的改造,也就是编写FileTemplate、LiveTemplate和ScriptedExtensions。下面对这三个功能进行简单的说明,先说ScriptedExtensions。

Scripted Extensions

先来解释一下,什么是Scripted  Extensions。我们都知道,现在的IDE都是插件式的,也就是说,我们可以通过开发商提供的插件开发包来开发插件,扩展现有的IDE功能。但是编写插件需要特定的开发环境,如果是一个很简单的功能,还要费劲去搭开发环境,挺麻烦的。所以IDEA提供了Scripted  Extensions,可以理解为一个简化版的插件,就是可以通过脚本来扩展IDE功能。

IDEA提供了Database功能,可以连接数据库进行相关操作。当你连接了数据库,在表上右击时,可以看到Scripted  Extensions这个选项,里面有一个功能是可以基于表来生成POJO的groovy脚本。

但是功能比较low:

  • 包名是写死的:com.sample

  • 没有生成table注释

  • 没有基于lombok来简化getter和setter

不过好在,我们能基于这个脚本来自行修改,在刚才的Scripted Extensions菜单里,有个Go to Scripts  Directory选项,点击后,可以进入脚本目录。

如何搭建合适的Web框架

直接对这个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即可。

如何搭建合适的Web框架

几点说明:

  • 下面的描述中列出了默认的一些参数以及作用

  • 你也可以自定义变量,自定义的变量如果没有赋值,在创建时会有输入框提示输入内容

  • 模板是基于Velocity的,所以如果你熟悉 Velocity,那就可以直接上手

  • Enable Live  Template选项是在FileTemplate激活LiveTemplate变量,不过需要使用#[[]]#包裹。但是对于创建Java,这个功能有bug,并不能定位到需要的位置,所以暂时没使用

创建完成后,就可以在New菜单中看到这个模板了。

LiveTemplate

LiveTemplate实际就是CodeSnippet。创建方式和FileTemplate类似。按下Ctrl-Alt-S呼出设置菜单,点击Editor->Live  Template,在里面新增Template即可。

如何搭建合适的Web框架

几点说明:

  • 这里的变量是使用$$包裹

  • 每个变量就是一个占位符,在使用tab展开后,可以手动输入值

  • 右下角的Edit variables,用于对变量赋值,IDEA提供了一些方法、也可以设置默认值

  • 下面的change链接,可以选择LiveTemplate生效的位置,比如只在Java类声明处生效

编码流程

创建了上面的几个模板后,编码流程如下:

  • 在表上右击,通过Scripted Extensions来生成Model

  • 通过FileTemplate来快速生成Controller、Service、Domain等类

  • 通过LiveTemplate来快速编写代码

关于如何搭建合适的Web框架问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注编程网行业资讯频道了解更多相关知识。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

如何搭建合适的Web框架

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

如何搭建合适的Web框架

如何搭建合适的Web框架,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。之前在Web开发框架推导一文中我们一步步的搭建了一个开发框架。在当时的情况下,还算满足需求。但是随着项
2023-06-16

如何搭建基于.NET平台的Web框架

这篇文章主要介绍了如何搭建基于.NET平台的Web框架,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。一.技术分析1.web数据传输ExtJS作为前端UI展现层,传输数据格式为
2023-06-17

如何手工搭建ABP框架Web项目

本篇文章为大家展示了如何手工搭建ABP框架Web项目,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。ABP是 ASP.NET Boilerplate Project 的简称。ABP是基于DDD(领域驱
2023-06-04

springboot创建的web项目如何整合Quartz框架

这篇“springboot创建的web项目如何整合Quartz框架”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“spring
2023-07-02

vue的webpack框架如何搭建

本篇内容主要讲解“vue的webpack框架如何搭建”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“vue的webpack框架如何搭建”吧!1、想要使用vue,我首先该怎么做?想要学习vue,我第
2023-07-04

eclipse如何搭建springboot框架

要在Eclipse中搭建Spring Boot框架,可以按照以下步骤进行操作:1. 首先,确保已经安装了Java Development Kit(JDK)和Eclipse IDE。可以从官方网站下载并安装它们。2. 打开Eclipse ID
2023-10-08

如何搭建Java中的SSM框架

这篇文章主要介绍了如何搭建Java中的SSM框架,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。安装相关文件:MyEclipse界面:测试项目简单增删改:ssm+mysql+e
2023-05-30

如何搭建一个AmazeUI框架

如何搭建一个AmazeUI框架?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。1.获取Amaze UI 1.1下载文件首先打开百度输入:Amaze UI -->找到Amaz
2023-06-09

如何挑选最适合项目的PHP框架?

根据您的项目需求和偏好,选择适合的 php 框架。laravel 适合小型到中型项目,因为它易于使用且功能丰富。symfony 适合大型、复杂的项目,因为它提供了灵活性、可扩展性和企业级功能。具体选择还取决于项目类型、性能、开发体验、社区支
如何挑选最适合项目的PHP框架?
2024-05-23

PHP 框架定制指南:创建真正适合您需求的框架

定制 php 框架可满足特定应用需求。步骤包括:确定所需功能:数据模型、路由、验证、缓存选择可定制的基础框架,如 laravel 或 symfony创建自定义组件:模型、控制器、路由覆盖框架文件:自定义路由行为创建应用配置文件:存储特定应用
PHP 框架定制指南:创建真正适合您需求的框架
2024-04-30

Flutter应用框架搭建屏幕适配的方法

本篇内容主要讲解“Flutter应用框架搭建屏幕适配的方法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Flutter应用框架搭建屏幕适配的方法”吧!因移动设备的多样性,特别是 Android
2023-06-29

如何选择最适合你的手机CSS框架?

手机CSS框架的选择指南:如何找到最适合你的?随着移动设备的普及和用户对移动应用和网站的需求增长,构建适配手机屏幕的页面变得越来越重要。使用CSS框架可以简化开发流程,并确保我们的页面在不同设备上都能够良好显示。然而,有许多不同的手机CS
如何选择最适合你的手机CSS框架?
2024-01-16

Android模块化框架如何搭建

搭建Android模块化框架可以按照以下步骤进行:1. 创建一个新的Android项目:使用Android Studio创建一个新的项目作为模块化框架的基础。2. 定义模块的结构:根据业务需求,定义模块的结构,包括模块间的依赖关系、通信方式
2023-10-11

如何选择适合你的Golang框架:选型指南

Golang框架选型指南:如何选择适合你的框架?导语:随着Go语言的迅速发展,越来越多的开发者开始选择Golang作为他们的首选编程语言。作为一门简洁高效的静态语言,Go在处理高并发、网络编程和云原生应用等方面表现出色。然而,由于Gola
如何选择适合你的Golang框架:选型指南
2024-01-24

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录