ASP.NET又称为ASP+,不仅仅是ASP的简单升级,而是微软公司推出的新一代脚本言语。ASP.NET基于.NETFramework的Web开发渠道,不光吸收了ASP以前版别的最大优点并参照Java、VB言语的开发优势加入了许多新的特征,同时也修正了以前的ASP版别的运转错误。
ASP.NET具有开发网站应用程序的全部解决方案,包括验证、缓存、状态管理、调试和部署等全部功用。在代码编撰方面特征是将页面逻辑和业务逻辑分隔,它分离程序代码与显现的内容,让丰富多彩的网页更简单编撰。同时使程序代码看起来更洁净、更简单。

web

web开发框架

在当时的情况下,还算满意需求。可是随着项意图逐步完善,需求改变的频度逐步变得比新增需求的频度高,本来结构的弊端越来越显着,所以需求对结构进行升级改善。
咱们先来看本来结构的问题,然后根据这些问题,来对结构进行改善。
原结构的问题
代码生成问题
参数传递问题
Service层问题
测验依靠问题
Mapper.xml的问题
代码生成问题
在原结构中,咱们根据各种束缚,编写了一个代码生成组件,经过这个组件,咱们能够针对选中的表来生成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的默许事务机制会导致相似如下代码的逻辑调用不会抛出希望的反常
//PostServicepublicStringsavePost(Postpost){postRepository.save(post);for(PostDiscussdiscuss:post.getDiscuss()){//这儿是抓不到RuntimeException反常的,会是一个TransactionRollBack的反常discussService.save(discuss);}}//discussServicepublicStringsavePost(PostDiscussdiscuss){thrownewRuntimeException(“保存失败”);}
测验依靠问题
中心的事务逻辑在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以及ScriptedExtensions来进行生成。虽然这样的办法,不能够一次性生成多个文件,可是因为生成逻辑基本是一次性的,所以影响不是很大。在初次生成代码时,代码生成组件的功率是高于FileTemplate、LiveTemplate以及ScriptedExtensions的组合,可是后期调整的灵活性,显着是FileTemplate、LiveTemplate以及ScriptedExtensions的组合要高于代码生成组件的:
首要,当文件结构调整时,只需求修正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不依靠于其它任何层,所以能够脱离数据库和容器来进行测验。使得测验的功率不会随着项意图开发而越来越低
4a24aeea2a5757b122a82f22f75c9266.png
结构改善细节
现在现已知道了,如何对结构进行改善,咱们现在就开始着手进行改造。其实首要的改造是对代码生成办法的改造,也便是编写FileTemplate、LiveTemplate和ScriptedExtensions。下面临这三个功用进行简略的阐明,先说ScriptedExtensions。
ScriptedExtensions
先来解释一下,什么是ScriptedExtensions。咱们都知道,现在的IDE都是插件式的,也便是说,咱们能够经过开发商供给的插件开发包来开发插件,扩展现有的IDE功用。可是编写插件需求特定的开发环境,假如是一个很简略的功用,还要费力去搭开发环境,挺费事的。所以IDEA供给了ScriptedExtensions,能够理解为一个简化版的插件,便是能够经过脚本来扩展IDE功用。
IDEA供给了Database功用,能够衔接数据库进行相关操作。当你衔接了数据库,在表上右击时,能够看到ScriptedExtensions这个选项,里边有一个功用是能够根据表来生成POJO的groovy脚本。
可是功用比较low:
包名是写死的:com.sample
没有生成table注释
没有根据lombok来简化getter和setter
不过好在,咱们能根据这个脚本来自行修正,在方才的ScriptedExtensions菜单里,有个GotoScriptsDirectory选项,点击后,能够进入脚本目录。
c9d8a07bb6f2204ff91a5f2dd4838be2.png
直接对这个groovy文件Ctrl+c,Ctrl-v,仿制一份,重命名一下,根据这个脚本进行修正即可。详细怎样修正,依照自己的需求来,里边首要便是根据表信息对String的拼接而已。
FileTemplate
FileTemplate是IDEA供给的生成文件的模板,你在点击菜单的File->New…今后,出现的各种文件,都是根据FileTemplate来完成的。咱们自定义的Controller、Service、Domain等类,都能够经过FileTemplate来简化创立。
详细运用办法为,按下Ctrl-Alt-S呼出设置菜单,点击Editor->FileAndCodeTemplate,在里边新增Template即可。
85ef6a20bd0af852e3320a5f0faaec2e.png
几点阐明:
下面的描述中列出了默许的一些参数以及作用
你也能够自定义变量,自定义的变量假如没有赋值,在创立时会有输入框提示输入内容
模板是根据Velocity的,所以假如你了解Velocity,那就能够直接上手
EnableLiveTemplate选项是在FileTemplate激活LiveTemplate变量,不过需求运用#[[]]#包裹。可是关于创立Java,这个功用有bug,并不能定位到需求的位置,所以暂时没运用
创立完成后,就能够在New菜单中看到这个模板了。
LiveTemplate
LiveTemplate实际便是CodeSnippet。创立办法和FileTemplate相似。按下Ctrl-Alt-S呼出设置菜单,点击Editor->LiveTemplate,在里边新增Template即可。
f3ff3f79879ee442a8f20811dc99d281.png
几点阐明:
这儿的变量是运用$$包裹
每个变量便是一个占位符,在运用tab展开后,能够手动输入值
右下角的Editvariables,用于对变量赋值,IDEA供给了一些办法、也能够设置默许值
下面的change链接,能够挑选LiveTemplate生效的位置,比如只在Java类声明处生效
编码流程
创立了上面的几个模板后,编码流程如下:
在表上右击,经过ScriptedExtensions来生成Model
经过FileTemplate来快速生成Controller、Service、Domain等类
经过LiveTemplate来快速编写代码

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。