springboot 多模块分层开发、改造(搭建、运行、打包)
1.情景展示
在JavaWeb开发过程中,我们通常会基于springmvc分层思想对整个项目进行分层开发:
常见的就是分为model(域模型层)、dao(数据库访问层)、service(业务逻辑层)、controller(控制器层)、web(表现层),这样分层之后,各个层之间的职责会比较明确,后期维护起来也相对比较容易。
通常我们会将其维护到一个模块当中,也就是一个项目就是一个模块,把不同的层用包进行区分,如下图左侧部分。
但是,随着项目越来越复杂,每个层的规模也逐渐增大,在一个模块中进行开发,会给测试和维护带来不便,对于大型项目来说,一般会将每个层放到自己的模块中,然后每个层建立联系,单独维护。
对于后期开发维护人员来说,右面这种分模块的方式更直观,看着比单模块舒服很多。
好处不多说,用了才知道。
2.分层梳理
下面两张图片方便大家对于即将分开的模块之间的关系有着重要的指导意义。
按照上面的思路,确定好哪些包需要移到哪些模块,下面就着手迁移啦。
3.分模块搭建/改造
新建模块
选中项目,右键--》New--》Module
下一步
给模块起个名字
关于名字,如果项目名称不长的话,建议使用“项目名称-模块名称”的方式,这样更加直观;
当然了,这是建议,直接取模块名称也是完全没有问题的。
我们先来了解一下,新建模块的结构:
说白了,这就是maven的标准目录(因为还没有Java文件,所以还没生成target目录,idea会帮我们完成的)。
第一步:迁移公共类(如果没有就忽略);
base目录,我放的是基本工具类等公共需要用到的东西
将这个base目录直接拖拽到bill-base模块java目录下
在To package里输入包名路径,路径构成一般为:
com.公司名称.项目名称.原来的包名,这有这样,才能保证不同模块的路径前缀是一致的。
不存在的包名会被创建
创建成功后,class连同包名都会完成迁移
如果出现上面这种原来的被没有删除的情况,手动删除即可。
我们知道,基本工具类一般情况下,是需要jar包依赖的,迁移成功后如果报错的话:
鼠标悬浮上去,在idea中,点击添加jar包,会自动将jar包依赖增加到对应的pom文件中。
注意:
由于是基础工具类,其它模块不一定会用到这个模块,即使需要用到,也不一定就需要用这里面的jar包,所以,我们可以把bill-base里的依赖设置成可选依赖,这样,其它模块需要对应jar包时,需要重新引入依赖;也不宜引起jar包冲突。
第二步:迁移实体类;
新建model模块
同样,关键在于迁移的包名(要把po这个包放到哪里)
第二关键点:下图提示,是在告诉我们,哪里用到了po包里的Java类
不要理会,强制迁移。
迁移成功
在这里,po层就显得有些多余了,重命名,将其删除即可。
第三步:迁移dao层;
新建dao模块;
迁移dao层;
强制迁移;
如果出现多余的包名,通过重命名将其删除。
我们知道,dao层又叫持久层,SQL映射也在这层完成,所以,我们只迁移dao层是远远不够的,还可以将对应的SQL.xml迁移过来。
迁移SQLMap.xml文件;
拖拽迁移,并新建一个mapper文件夹
容易出错的地方:
错误目录长这个样子,最终导致在启动项目后,对应SQL无法执行的问题。
如果出现删除原来目录导致新生成的目录也随之消失的情况,只能还原,只拖动xml完成迁移了。
更改sqlMapper.xml的命名空间(与dao层相对照)
改对了,下面就不会再报红了。
还没结束,还需要完成jar包依赖的迁移;
首先是模块依赖;
按照依赖对照关系,dao肯定需要依赖model。所以,在bill-dao的pom.xml中添加对model的依赖。
补充:在子模块中,我们可以指定父pom文件访问路径,这样方便我们跳转及识别。
其次才是jar包依赖。
将父pom.xml中的关于mybatis,数据库连接池,mybatis-plus等相关jar包依赖
重新导包
最后一步:重新编译项目。
注意:这里,只重新编译bill-dao模块,因为还没有迁移完毕,重新构建整个项目的话,报错信息会出现一大坨,但我们根本无法修改。
说明:要想只编译bill-dao模块,需要鼠标通过点击选中这个模块,再进行Build选项时才会出现编译这个模块的选项。
你会发现一堆bill-dao模块的报错信息,不要怕。
双击错误信息,会直接跳转到报错的java类。
改成正确引用路径即可。
挨个把所有bill-dao模块的报错信息改完就行了。
第四步:迁移service层;
如果我们像往常一样进行迁移
这里会出现一个问题:
如果不是新建的目录(一个不存在的目录)的话,将会迁移失败。
必须这样做,才能迁移成功:
选中java目录,右键新建package
选中service下的所有子包。
强制迁移。
迁移成功,但vo包没有迁移过去。
引入模块依赖,导包;
构建bill-service模块
这里分两种情况:
一种是向上依赖,像原来的dao层和po层已经被我们迁移了出来,改下路径就行了;
另一种是向下依赖,service层依赖web层,这种向下串层的行为在模块化后是不被允许的,
像:模块A依赖模块B,模块B又依赖于模块A,这种互相依赖是不被允许的,强制引入,在最终打包的时候会导致打包失败;只能进行单向或单方依赖。
所以,解决办法就是把service层需要的web层的相关包全部迁移到service模块。
迁移完成
这里需要注意的是:
按理说,dto是需要放在web模块的,但是,由于service模块需要用到,所以,我只将dto里部分文件进行了迁移(最好不要这样搞)。
迁移jar包依赖;
大部分的jar包依赖都集中在service模块。
这里需要提醒的是:
虽然校验和knife4j严格意义上来说,是属于web模块的东西,但是,web和service两个模块其实是不能完全撇清的,剪不断理还乱。
既然service层要用,索性干脆把这类jar包全部从web层搬到service层,这样,web模块在引入service模块后,也就引入了这些jar包依赖。
对于程序的运行,不受丝毫影响。
完成jar包迁移后,重新导包,重新编译bill-service模块,也许就会报错了。
如果项目中使用了Lombok插件,就会报错。
原因是:我们刚才将Lombokjar包依赖从父pom文件中迁移到了bill-service子pom文件,身为同级的bill-model自然就找不到啦。
所以,我们需要将lombok依赖从bill-service,迁移到bill-model。
前面也说了,只要其它同级模块引入这个模块,其它模块就也能直接使用Lombok注解,无需重新引入jar依赖。
第五步:迁移web层。
鉴于上面相同目录导致迁移失败的问题,我们还是手动创建包名好了。
总之,在idea中进行迁移会引发各种各样的路径问题,真是能恶心死人,只能自己逐个排查或这等报错再改啦。
迁移完毕
bill项目下的src变得空空如也,直接将这个src删除即可。
也许,我们的项目所有模块都会变成这个吊样,真是想骂街:
都被强制加一个web包。
只能通过重命名后再将web目录删除。
需要提醒一点:
启动类是放在项目根目录下的,即:和web同级,别像我一样,改着改着改懵了,把它们也放到了web目录下,
导致的结果就是:
启动项目后,一直报错:找不到注入的service模块类,A component required a bean of type...
添加模块依赖;
说明:
第一,引入的模块,必须指定版本号,不能省略<version>标签;
第二,版本号的值可以跟随项目通过,通过${project.version} 取值。
迁移jar包;
把父pom文件中所剩下的jar包依赖全部迁移到bill-web的pom文件中(父pom.xml中最好一个jar包依赖都不要留)。
bill-web的pom文件,除了模块依赖,通常情况下只有单元测试和springboot相关依赖。
重新编译bill-web目录,解决报错路径问题。
修改启动类注解扫描包;
dao路径改成正确的
修改日志配置文件关于dao层的引用
修改拦截器关于控制层路径引用
迁移项目构建工具;
将父pom.xml打包方式设为pom;
项目公共属性配置,也在父pom文件中进行,子pom文件通过${}引入即可。
如果需要多环境支持,在父pom中添加profile即可。
父pom文件,还可以配置maven中央仓库
模块出错
如果创建出来的模块或者在迁移过程中导致java或resources目录发生了变化:变成了普通目录,就需要将该模块删除,重新创建。
删除模块
第一步:remove module
选中要删除的模块,右键,选择“Remove Module”。
从项目移除成功后,文件夹将会变色;
右键--》删除即可。
但是,如果再次重建这个模块时(模块名称一致),出现模块已存在的情况时,可以这样做:
关闭项目,然后从磁盘中删掉项目,从svn或git上重新将整个项目下载下来再重新新建模块(重头再来)。
4.关于View层能否从Web层剥离出来的探究
剥离步骤:
第一步:创建view模块,并将web/main目录下的webapp目录迁移到view/main下
第二步:web模块引入view模块依赖
此时,要跳转的页面路径已经找不到了。
第四步:重新导包并启动项目;
项目启动正常
浏览器访问跳转到jsp的请求
经过以上测试发现:无法将前端界面从web模块进行剥离。
也就是说:要想由控制层Controller来决定最终跳转的页面的话,页面和Controller需要在同一个模块里。
5.运行
改造完毕后,还是像不分模块之前那样,直接用main方法启动类启动项目即可。
根本不需要所谓的在pom.xml中指定唯一的main方法入口。
可能会出现这种情况:
解决办法:
点击这个启动类,选择“Edit Configurations”
打开配置页面
在这里,我们会看到底部错误信息提示:在bill模块中找不到这个启动类。
实际上,bill是一个项目而不是模块,我们只需要将模块指定成该启动类所在模块即可。
展开“Environment”界面,在“Use classpath of module”中进行模块切换即可。
如果能成功启动还能看到原来的执行效果,那么项目多模块的重构就完成了。
(通过idea,重构的多模块项目,还有一个需要修改的地方,见第七部分)
6.打包
要想打包,需要确定三个问题:
第一,打成什么样的包(war还是jar)?
第二,哪个模块作为主模块(不是父模块),之所以这样叫,是因为,其它同级或子级模块都将会被它包含在该模块中。
对应前后端交互的项目,我们通常会将web模块作为主模块进行打包。
在web模块对应的pom.xml中指定packaging,如果设置该标签,与普通项目一样,将默认被打成jar包。
添加构建工具;
指定构建工具,并引入springboot自带的maven插件。
注意:其它模块也是允许有自己的构建工具。
虽然,service模块也指定了maven编译插件,但是,web还是主模块,并没有受到影响。
这就让我很疑惑了,idea是怎么选取web作为主模块的?
为了测试这个问题,我将dao里也加上了springbootmaven插件
打包失败:dao模块没有程序入口
通过以上实验,大致了解到:
当pom.xml引入springbootmaven插件后,在打包时,该插件会在该模块中寻找启动类。将程序入口作为主模块也就成了顺理成章之事了。
所以,一般情况下,引入springbootmaven插件的模块将会被作为主模块。
第三,选择哪个模块进行打包?
通过上面得知:
既然,web会被识别为主模块,那我们直接对它进行打包不就行啦?
执行package命令,结果却打脸:
web模块所依赖的这些同级模块,竟被从maven仓库中下载它们所对应的jar包,结果可想而知。
所以,不能用主模块完成整个项目的打包。
在idea中,通过一个带(root)的maven模块完成项目打包。
也只有通过它才能完成整个项目的打包,下面的子模块只能完成对自己模块的打包。
通过root会分别对每个模块进行打包,这是与没有分模块开发的项目,在打包时最大的区别。
打开右侧的maven视图
打jar包
在web模块对应的pom中指定成jar包。
clean,package
日志输出如下:
jar包展示
打war包
方式同上
war包展示
我们可以看到,其它模块都被打成了jar包,因为我们没有在对应的模块的pom文件中指定打包形式。
我觉得这样挺好的,提高了代码的安全性,让别人不能通过项目一下就全揽了所有代码。
如果你还配置了多环境,勾选上指定环境再打包就可以了。
7.多模块引发的404问题
2022年2月24日17:32:15
使用idea将项目分离成多模块项目后,当我们去访问webapp目录下所有的文件时,都将得到一个结果:404。
解决办法,见文末推荐。
当然,如果你不涉及需要访问网页的话,可以不用管这个问题。
写在最后
哪位大佬如若发现文章存在纰漏之处或需要补充更多内容,欢迎留言!!!
相关推荐:
本文来自博客园,作者:Marydon,转载请注明原文链接:https://www.cnblogs.com/Marydon20170307/p/14241740.html