跳至主要內容

Springboot-项目构建

holic-x...大约 26 分钟框架Springboot

Springboot项目-项目构建

单体项目构建

多模块项目构建

参考链接:

Spring Boot 多模块项目创建与配置 :

https://blog.csdn.net/weixin_34220623/article/details/93512305?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1

【1】工程构建计划

参考“信息管理平台-系统整合”构建(参考:若依系统)

mip-信息管理平台

mip-parent:父工程

mip-common: 通用工具类、方法、异常、常量定义

mip-framework:mip系统框架相关、shiro、配置等公共模块

mip-rest:共有服务、接口定义调用

mip-admin:后台管理系统(用于维护多个子系统)

mip-portal:门户网站-统一提供功能入口、放置前端代码

门户网站:

​ 实现方式1:web依赖于其他子模块的实现层,提供统一的controller层(原有思路是通过服务调用的方式,但由于此处设置的概念是)

​ 实现方式2:允许一个项目中存在多个web服务,在门户网站项目中统一进行打包

平台:拆分多个子系统模块(APS、CCIMS、EOAS 每个系统模块管理相应的表和service)

信息管理平台:
mip:父工程(作为版本控制和父工程模块控制)
groupId:com.sz
artifactId:mip
packaging:pom

mip-framework:mip系统框架核心相关、
shiro、
通用工具类、方法、异常、通用常量定义(独立工程:不参与继承、聚合)
groupId:com.sz
artifactId:mip-framework
packaging:jar

mip-rest:通用服务层封装、配置等公共模块(公有服务,提供公共接口调用?)
groupId:com.sz
artifactId:mip-rest
packaging:jar

mip-admin:后台管理系统(用于维护多个子系统)
groupId:com.sz
artifactId:mip-admin
packaging:jar

mip-aps:
groupId:com.sz
artifactId:mip-aps
packaging:jar

mip-ccims
groupId:com.sz
artifactId:mip-ccims
packaging:jar

mip-eoas:
groupId:com.sz
artifactId:mip-eoas
packaging:jar


mip-portal:门户网站?统一提供功能入口、放置前端代码
groupId:com.sz
artifactId:mip-portal
packaging:war


参考:
mip-framework依赖mip-rest
mip-eoas依赖mip-framework
mip-protal门户网站依赖每个子系统

【2】Springboot多模块工程构建思路

​ 为了避免不同工作空间maven仓库资源冲突,此处将eclipse和idea的maven本地仓库区分开来,避免相互之间受影响。参考链接:https://blog.csdn.net/baidu_41885330/article/details/81875395

a.思路1:根据‘MVC分层架构’构建多模块工程

​ 抽离公共common、model、service,结合业务需求拆分成多个可执行的Controller层

​ 参考链接:https://blog.csdn.net/l_wierpuller/article/details/90374421#comments

image-20201004163940583

image-20201004163944324

b.思路2:根据‘系统功能模块拆分’构建多模块工程(参考)

​ 抽离公共模块,根据系统功能需求拆分为多个不同的子模块除却引用公共模块,各自维护自身项目的mvc层,不同子模块可独立管理Controller

​ 页面访问不同子模块的Controller-构建说明:在实际开发过程中不同子模块拆分,相应Controller由各个子模块进行维护,页面可以直接访问Controller层。在多模块拆分工程时,如果要实现页面能够直接访问到不同子模块的Controller可有两种参考实现方式:

其一为在主模块中统一管理Controller(API调用);
其二为不同子模块维护相应的Controller层;

​ 为了便于拆分子模块逻辑代码,在项目多模块框架搭建的时候,子模块可维护自身的MVC架构,项目启动可参考下述方式:

​ 方式1:在主模块配置中引入对子模块的依赖,如此一来,主模块项目启动的时候附带检查依赖的jar并加载,当主模块启动成功之后便可正常通过页面访问不同模块的Controller(前提是该子模块被主模块引入依赖)。此处依赖的配置文件是主模块配置文件

​ 方式2:每个子模块相当于一个子项目,通过引入相应的启动类和配置文件即可启动相应的项目(每个子项目如果要同时启动则需对应不同端口号)。每个子模块单独启动的时候需要依赖其子模块相应的配置文件(application.yml或application.properties文件缺失会导致启动模块出错),然而当主模块引入某个子模块的依赖时,主模块启动的时候依赖的配置文件是主模块的配置文件,子模块配置文件失效。

​ 为了避免不同子模块配置文件带来的潜在影响,建议在主模块中统一配置入口、统一启动入口,可结合实际开发需求创建不同的配置文件用于切换不同的开发环境

【3】工程构建说明

工程搭建步骤说明	
1.创建一个maven工程作为父工程(POM统一管理)
2.创建相应的子模块的工程
3.构建多模块maven依赖配置关系
4.抽离系统公共模块,提供公有Service层供子模块调用
5.根据实际业务需求构建子系统业务模块

Springboot官方学习文档:

https://docs.spring.io/spring-boot/docs/2.0.2.RELEASE/reference/htmlsingle/#boot-documentation

参考链接:

​ https://blog.csdn.net/qq_33206732/article/details/87552244

​ https://blog.csdn.net/zcf980/article/details/83040029

SpringCloud基础教程:https://blog.csdn.net/hellozpc/article/details/83692496

a.父工程构建:mip-parent

image-20201005154928850

image-20201004161533176

image-20201004161538707

​ 填写完项目信息之后选择Next,直到finish,将mip作为一个管理项目,所以不需要src,直接删除即可,同时修改对应的pom文件

​ 官方默认配置:通过parent继承实现依赖springboot

image-20201004161612621

​ Springboot启动异常:在项目pom.xml文件中引入了druid-spring-boot-starter,该版本的jar依赖了RelaxedPropertyResolver,可以通过继承spring-boot-starter-parent实现

​ Spring boot java.lang.NoClassDefFoundError: org/springframework/boot/bind/RelaxedPropertyResolver

​ 如果不使用parent作为maven单继承操作依赖springboot

​ 参考链接:https://blog.csdn.net/weixin_38218338/article/details/88721051

b.子模块构建

​ 在mip项目下创建子模块:选中项目路径new module

image-20201004161745801

​ 以此类推搭建多个系统模块,随后创建依赖关系(实际pom内容设置参考实际项目的属性设定)

c.构建多模块maven依赖配置关系

(1)子模块pom设定参考

image-20201004161857635

​ 子模块的packing属性参考实际需求设定

​ “继承传递”的特性是基于父工程使用<dependencies>直接引入jar的基础上,如果使用了<dependencyManagement>则视为声明依赖版本,子工程则需要根据自身需求引入jar而无需关注jar版本

​ 如果A依赖B、B依赖C,则A可以引用C的内容

(2)父工程pom设定参考

image-20201004161958333

(3)工程测试

​ 工程搭建完成可创建controller进行测试:在mip-portal中引入对子模块mip-eoas的依赖,在mip-eoas中创建MyTest方法供调用

​ 测试点1:测试本地项目是否跑通

​ 测试点2:测试子模块之间的调用

image-20201004162035900

image-20201004162039017

image-20201004162043055

image-20201004162046090

Springboot项目配置

【1】Springboot项目热加载

参考链接:

​ 实现热部署方法:http://www.360doc.com/content/18/0208/17/19179788_728638832.shtml

​ devtools实现热部署:https://www.cnblogs.com/lspz/p/6832358.html

​ springboot实现热部署:https://blog.csdn.net/chachapaofan/article/details/88697452

​ 热部署说明:https://blog.csdn.net/qq_37598011/article/details/80778915

在开发过程中为了便于测试,借助Springboot配置devtools实现Springboot项目热部署

步骤 1:引入devtools相关jar

image-20201004171501518

步骤2:在启动类所在模块配置application.yml中配置devtools相关属性

image-20201004171514994

步骤3:修改IDEA配置

​ 当修改了Java类后,IDEA默认是不自动编译的,而spring-boot-devtools又是监测classpath下的文件发生变化才会重启应用,所以需要设置IDEA的自动编译:

File->Settings->Compiler->Build Project automatically

image-20201004171550070

ctrl + shift + alt + /,选择Registry,勾上 Compiler autoMake allow when app running

image-20201004171606442

image-20201004171610163

​ 配置完成,启动项目进行测试,如果热部署不生效,则在pom.xml中配置下述属性:(有时候模块重新启动可能有些延迟,修改完文件之后耐心等待或者是重新访问页面触发Controller操作)

image-20201004171624042

【2】Springboot项目配置文件说明

a.yml配置文件出错导致项目启动失败

Springboot启动报错:Failed to load property source from location 'classpath:/application.yml'

​ 排查1:中文乱码问题:修改环境或者是去除中文yml文件注释

​ 排查2:yml语法格式问题:检查yml语法是否出错

​ 排查3:所引用的application.yml文件是通过把其他类型的文件后缀名直接改为yml生成的,这时就需要把application.yml中的内容全部复制,然后删除,再新建一个application.yml文件,将复制的内容拷贝进去再运行项目就不会报错了

image-20201004171716269

​ 此外,当application.yml文件中出现飘红或者是警告,考虑是否当前所有工程模块没有引入相关的依赖(检查继承传递、依赖定义是否正常引用),如果引用jar不正常则相关配置会飘红或者是找不到属性配置的依据

image-20201004171725896

b.yml配置文件与properties配置文件

​ 当application.properties和yml文件在并存时(同一目录下),application.properties优先级更高,若application.properties中没有指定属性,再去读yml中的值

file:./config/ -- file指的是项目文件夹->根目录下的/config目录下的配置文件
file:./ ->根目录下的配置文件
classpath:/config/ --classpath指的是resources文件夹下->类路径下的/config目录下的配置文件
classpath:/ ->类路径下的配置文件

​ 优先级由高到低,高优先级的配置会覆盖低优先级的配置;Springboot会从这四个位置全部加载主配置文件, 如果高优先级中配置文件属性与低优先级配置文件不冲突的属性,则互补配置

​ 如果同一个配置属性,在多个配置文件都配置了,默认使用第1个读取到的,后面读取的不覆盖前面读取到的(根据优先级进行限定)

image-20201004171910982

c.Springboot引入外部配置文件(子项目配置文件拆分管理)

​ 在构建springboot多模块项目的时候,每个子项目往往需要维护自身项目的一些自定义参数,但是这些配置参数不建议全部冗余到主配置文件或同一个文件中。主配置文件主要搭建项目基础框架和属性,每个子模块可相应维护自己的配置文件。具体步骤简单说明如下:

​ 引入外部配置文件属性可以分为常规属性配置和类型安全的配置,

步骤1:在当前子模块项目创建自定义的配置文件 config.properties、user. properties

image-20201004172004045

步骤2:创建一个静态常量类用于映射配置文件,加载配置属性

(必须确保启动类所在包路径能够扫描到所有的注解,否则部分注解可能由于没有扫描到导致注解失效)

​ 如果不指定@PropertySource则默认查找application.properties配置文件

​ 需要注意的是@PropertySource注解只支持properties文件,而不支持yml文件(无法解析占位符)。如果要使用yml文件,则其命名必须为‘application-xxx.yml’,且需要在主配置文件中进行声明引用,否则定义无效

  • 常规属性获取:

image-20201004172037278

  • 类型安全的配置:

​ 常规属性配置虽然使用@Value就可以实现注入配置属性,但是如果需要注入的属性地方很多,那么到处的@Value就显得格外麻烦。虽然可以使用一个Bean将所有配置文件属性注入,然后在使用的时候通过Bean.get属性就可以获取,但是还是要给每个属性@Value注解。可以考虑参考下述思路,将相关的配置文件整合在一个配置类中,然后在使用的时候注入组件,直接通过构造器操作字段属性(setter、getter)

image-20201004172131425

image-20201004172137346

​ 属性配置文件定义说明:

​ Java系统属性(System.getProperties()),Spring启动的时候,默认会把系统的很多属性都默认加载进来。因此在自定义key的时候,应该去避免和系统自带的key重名,否则不起作用

image-20201004172154433

​ 多模块springboot项目构建加载外部配置文件先后顺序问题

​ 如果启动类所在模块指定路径恰好有指定了同名配置文件,则优先加载启动类所在模块的配置文件;如果没有则查找当前子模块配置文件

​ 为了尽可能减少配置文件带来的冲突,一般在配置文件外层再嵌套一层文件夹(与子系统相关)

d.Springboot中引入多个配置文件(适配不同开发环境)

​ 多配置文件覆盖:

​ https://www.cnblogs.com/young0393/p/10189461.html

​ https://blog.csdn.net/qq_42714869/article/details/83030097

​ https://blog.csdn.net/hanpenghu/article/details/84071979

​ 一般在使用springboot时会用到多个环境下的配置文件,例如

application-dev.yml:开发环境 
application-uat.yml:用户验收测试环境 
application-prod.yml:生产环境

​ 了解多个配置文件加载顺序和特性:配置文件以application.yml为基础,dev等配置文件在application.yml的基础上进行补全或者覆盖变量

  • spring.profiles.active是用来激活springboot多文件配置的

    在springboot中多环境配置文件名需要满足application-xxx.properties的命名规则;

    其中的xxx正是spring.profiles.active需要指定的配置文件名

  • 修改application.properties主配置文件的spring.profiles.active标签,引入副配置文件

  • 加载多个配置文件spring.profiles.active = xxx,xxx

例如:spring.profiles.active = test,database

Springboot项目构建常见问题

【1】环境搭建问题

a.Springboot启动异常

异常1:没有正常引入springboot相关配置文件

​ Springboot启动异常:在项目pom.xml文件中引入了druid-spring-boot-starter,该版本的jar依赖了RelaxedPropertyResolver,可以通过继承spring-boot-starter-parent实现

Spring boot java.lang.NoClassDefFoundError: org/springframework/boot/bind/RelaxedPropertyResolver

如果不使用parent作为maven单继承操作依赖springboot

异常2:pom:1.0-SNAPSHOT and 'parent.relativePath' points at no local POM

​ 在引入父工程的pom依赖时,springboot启动报错。参考现有搭建的工程目录,在继承父工程的时候relativePath指向父工程的pom.xml配置文件相对路径

image-20201004162402409

​ 如果没有正常指向,则pom.xml文件飘红报错

image-20201004162411139

异常3:Springboot2.x对web的支持报jackson错误

NoClassDefFoundError: Could not initialize class com.fasterxml.jackson.databind.ObjectMapper

参考解决方案:

image-20201004162510879

暂定取消对jackson的依赖,后续根据项目需求引入相关json处理jar

b.项目访问404

异常:This application has no explicit mapping for /error, so you are seeing this as a fallback.

参考学习链接:https://www.cnblogs.com/todayforever/p/12584318.html

image-20201004162619362

Springboot启动正常,但访问Controller异常:

排查点1:Application启动类所在包位置不对

spring-boot会自动加载启动类所在包下及其子包下的所有组件,一般将Application类放在最外侧,即包含所有子包

Application启动类直接放在了src/main/java包下面,这个在编译器就会报错(Spring Boot Application in default package)

Application启动类范围小于组件的位置范围(Application启动类所在包及子包不包含要访问的Controller导致组件没有正常加载)

排查点2:springboot的配置文件问题

application.yml或application.properties中关于视图解析器的配置问题

当pom文件下的spring-boot-starter-parent版本高时使用:

spring.mvc.view.prefix/spring.mvc.view.suffix

当pom文件下的spring-boot-starter-parent版本低时使用:

spring.view.prefix/spring.view.suffix

排查点3:控制器的URL路径书写问题,或者是没有注入Controller(检查注解配置)

@RequestMapping(“xxxxxxxxxxxxxx”),实际访问的路径与”xxx”不符合

c.Springboot版本更新兼容问题

参考链接:https://blog.csdn.net/kmesky/article/details/102984592

Springboot2.2前后引用的测试jar依赖不同,且部分2.2之后的版本与mybatis-plus兼容性需要考虑

image-20201004162828037

image-20201004162832236

image-20201004162836522

image-20201004162840000

d.新建子模块,Maven Projects中是显示灰色

​ 删掉了指定模块,随后后重新新建了一个模块,发现maven依赖配置构建完了之后maven projects项是灰色的,检查maven配置,去除Ignored Files中pom.xml勾选,点击apply应用,恢复正常

image-20201004162909511

​ 如果子模块右键新增也没有package选项,刷新一下maven依赖和子模块工程再次查看即可

e.替换包名后springboot项目启动失败

错误: 找不到或无法加载主类 cn.sz.isd.mip.MipAdminApplication

image-20201004165319042

​ 批量替换包名后启动报错,与Idea环境配置文件缓存相关,需要相应修改

【2】Maven工程依赖管理问题

<dependencies><dependencyManagement>的区别说明

​ 在父工程的pom.xml文件中的 <dependencies> 里引入的依赖其子项目会继承,即只要在父pom的<dependencies>里引入的东西,子项目就可以直接用(继承传递)

<dependencyManagement> 负责管理子项目的依赖版本。在<dependencyManagement>中引入的依赖,子项目不会继承,子项目要用到的依赖还是要子项目自己去进行<dependencies>引入,但子项目在引用时无须指定版本号的,版本号在父pom的</dependencyManagement> 里定义进行统一管理。

​ 不同子项目根据实际业务需求所引入的jar不同,因此为了避免jar引入冲突,统一在父工程的pom.xml文件中用<dependencyManagement>声明版本号统一进行jar管理,但不引入jar(如果使用<dependencies>直接引入jar,子工程继承时容易引起jar冲突,需避免这种情况)

​ 可针对上述情况:在父工程的pom中使用<dependencyManagement>声明jar版本号,但没有在mip-portal中引入Springboot相关jar,因此工程更新后则报错(没有引入Springboot相关jar);取消<dependencyManagement>则恢复正常

image-20201004163141342

​ 父工程pom依赖管理参考

image-20201004163152248

​ 子系统根据实际需求引入jar,避免继承传递导致jar冲突

image-20201004163203540

​ 统一管理项目的版本号,确保应用的各个项目的依赖和版本一致,才能保证测试的和发布的是相同的成果,因此,在顶层pom中定义共同的依赖关系。同时可以避免在每个使用的子项目中都声明一个版本号,这样想升级或者切换到另一个版本时,只需要在父类容器里更新,不需要任何一个子项目的修改(除非引用jar版本升级涉及到代码引用的调整);如果某个子项目需要另外一个版本号时,只需要在dependencies中声明一个版本号即可。子类就会使用子类声明的版本号,不继承于父类版本号。

​ 如果需要实现继承依赖传递,在父工程的pom.xml中指定<dependencies>即可,参考配置如下:

image-20201004163232780

image-20201004163239647

a.IDEA的Background Tasks一直处于Process Running

​ 问题描述:在Maven更新依赖的时候,进程一直卡住,Background Tasks一直处于processing running状态,导致项目无法更新

​ 参考网上内容:

​ 1>设置maven的配置

File--->Settings(Ctrl+Alt+S)--->Build--->Build Tools--->Maven--->Runner--->VM Options框中 -DarchetypeCatalog=internal 

​ 2>创建Maven项目时设置其属性

创建项目的时候,在Properties属性面板中添加一项:archetypeCatalog = internal

​ 实际解决:在setting.xml中配置maven镜像路径,还是选择用本地路径作为存储仓库(将localRespository换成本地路径进行管理,从指定的镜像路径中加载jar到本地仓库。考虑是调用远程仓库数据传输较慢,导致进程卡死)

​ 与本机连接网络问题相关,可根据实际需求调整maven仓库路径和镜像路径(默认为maven官方中央仓库)

b.IDEA更新maven卡在finished

​ IDEA 2018.2.5 ×64、maven-3.5.2

​ 在构建mip-eoas子模块进行测试的时候,由于之前测试时引入了mip-admin子模块,后续清理代码的时候发现有依赖项无法清理(MavenàReImport也无效,反而将此前下载的maven仓库资源给清理掉了),检查Maven本地仓库,发现有打包不完全的mip-admin

image-20201004163502887

image-20201004163510159

​ 项目一直卡在处理maven依赖的问题解决,在能排除网络、仓库镜像等原因后还无法解决的话,可以换个idea、maven版本试试。

​ 参考网上说法,卡在maven骨架构建,调整maven参数:File--->Settings(Ctrl+Alt+S)--->Build--->Build Tools--->Maven--->Runner--->VM Options框中 -DarchetypeCatalog=internal

​ 变更maven仓库配置之后,重新更新依赖,配置项还是飘红

image-20201004163524150

检查项目Librarys配置,清理所有飘红的maven依赖重新导入

image-20201004163536127

清理所有模块此前产生的target文件,随后再次尝试更新依赖

image-20201004163548032

重启idea,再次清理更新尝试

image-20201004163611125

​ Maven本地仓库替换之后出错,更新配置(reimport导入的是maven配置的仓库,但在maven Projects中刷新更新的时候还是保留之前的配置导致maven引入出错)

image-20201004163622082

c.Maven实现多模块工程构建测试出错

​ 多模块工程构建,父子工程pom.xml配置文件检查。父工程检查jar版本管理、子模块加载是否正常;子工程检查继承父工程、引入maven依赖是否正常

​ 可在Maven Projects窗口中查看多模块工程的maven依赖是否正常构建

image-20201004163645579

image-20201004163650538

​ 检查父工程的配置和子工程的依赖配置是否一致(由于不小心注释了mip的groupId和version导致项目maven依赖构建失败出错)

​ 父工程要指定完整的项目配置,子工程pom检查继承依赖的父工程groupId和version引用是否正确

image-20201004163702042

image-20201004163707804

【3】多模块工程构建常见问题

a.模块之间的调用问题

​ 使用maven构建多模块项目时,解决模块之间调用的问题(通过maven引入依赖)

​ 服务层之间的调用:抽离公共接口,引入对方的依赖随后进行调用。maven多模块之间的调用也是通过dependency的,和调用其他外部的依赖没区别。

没有父模块:如果没有父模块,每个子系统都是完全分离的多个模块,只能先编译好底层的模块(比如service模块为一个jar),然后再引入到controller模块中去(就和引用一个第三方的jar一样)。通常的做法是建立一个本地仓库,编写service的团队写好后mvn install到本地仓库去,编写controller的团队在pom里正常引用这个service模块

存在父模块:如果是存在父模块的,比如同时包括controller和service模块

​ 在父模块的pom中声明子模块:

<modules>
	<module>controller</module>
	<module>service</module>
</modules>

​ 在子模块中声明父模块:

<parent>
	<groupId>xxxxx</groupId>
	<artifactId>xxxparent</artifactId>
	<version>1.0</version>
</parent>

​ 在执行的时候,maven会自动去分析pom的关系,并确保service先编译(因为controller的pom中引用了service模块)

​ 按照这种思路,便可将项目拆分多模块,抽离公共模块,模块之间调用通过maven配置进行控制

​ 参考链接:https://blog.csdn.net/weixin_38492276/article/details/82260094

​ 允许页面访问到相应的模块的controller:在主工程中启动类的放置位置必须保证能够扫描到当前路径下所有的包,也就意味着项目模块命名要规范

​ 例如com.sz.mip 下(但是启动类不能够直接放在src/main/java下),之后相关类扫描会自动扫描com.sz.mip.相关jar。在这里注意所有模块子包命名要基于‘com.sz.mip.’,否则扫描不到组件。但是controller的名字和接口路径映射要避免重名,否则项目启动报错

​ 如果是基于微服务概念,不同模块、子系统直接的调用,则需要通过接口远程调用(不同项目发布不同路径)

b.SpringMVC Controller命名冲突的问题

解决页面访问不同子模块的controller问题(Controller、Mapping映射不能重名)

org.springframework.beans.factory.BeanDefinitionStoreException: 
Failed to parse configuration class [com.sz.mip.MipPortalApplication]; nested exception is org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'userController' for bean class [com.sz.mip.framework.controller.UserController] conflicts with existing, non-compatible bean definition of same name and class [com.sz.mip.portal.UserController]

​ 在一个工程下构建多个子项目,必须要遵循一套编码规范,否则由于包名定义或者是controller层定义命名冲突导致项目启动报错或者触发未知的错误,因此一定要养成良好的编程习惯和编码规范!

image-20201004164529518

image-20201004164534973

问题分析:由于所有的模块(子系统)是构建在一个父工程的基础上的,而SpringMVC的Controller 是采用类似键值对(key/value)的映射方式处理的。而当中的键,默认是用cotroller的类名(非全类名)作为键。因此,如果不同包下面的两个Contoller 重名的话,就会导致SpringMVC的容器管理中的controller map中的key重复,从而导致冲突

​ 在使用注解 @Controller 时候,如果不使用命名,而SpringMVC会默认把类名的头一个字母小写,然后放到一个map中。例如在两个子模块中都定义TestController,虽然全类名不同,但在使用了@Controller 注解却没有进行命名。在SpringMVC在扫描Controller的时候,会把他们都默认解析为 testController,然后以这个testController为键(key), 放到一个全局的map中。因此,就会出现两个键完全一样的Controller。由于SpringMVC不使用覆盖的方式处理具有相同键的不同全类名的Controller,扫描的时候就会包上面的错误。

解决方式:遵循编码命名规范,按照指定编码规则,给自己的Controller重命名,尽量避免Controller、映射路径重名的情况:

image-20201004164609387

image-20201004164614012

http://localhost:8080/test/getDateByLocal、http://localhost:8080/test-eoas/getDateLocal

c.多模块项目启动问题

​ 结合多模块工程构建思路分析,在根据‘系统模块拆分’构建多模块工程的时候,Controller层命名冲突可能存在两种分析情况

情况分析1:模块之间没有构建相互依赖的关系

​ 如果模块之间并没有构建相互依赖的关系,项目启动依赖所启动的主模块的配置,不会检查其他未被依赖的子模块的内容,也就是说当未被主模块依赖的子模块之中若存在与主模块同名的Controller或映射路径的时候,项目还是可以正常启动(此时无法校验未被依赖的子模块的正确性,但并不代表程序不存在隐藏的bug),访问指定的Controller则以启动的主模块配置为参考

情况分析2:模块之间构建了相互依赖的关系

​ 例如子模块A中依赖了子模块B,当子模块A启动的时候会相应检查关联依赖的子模块B,如果存在同名Controller或者映射路径,且程序并没有进行重命名处理的时候,此时项目启动报错(Controller命名冲突)

​ 综上所述,如果在构建多模块工程的时候,只保留一个主模块(主启动类),若需要页面同时访问到不同子模块的工程,则需要在主模块(例如mip-portal)中引入对子模块的依赖(在项目启动的时候能够相应检查依赖项),当主模块正常启动之后便直接能通过页面访问不同子模块的Controller层;再者,为了方便模块调试,可能会考虑在构建多模块工程的时候每个子模块对应相应的启动类,当项目测试的时候启动测试自身的项目即可(当引入了公共子模块,maven会自动构建其依赖关联关系)

​ 但无论针对上述哪种实现方式,在项目打包的时候要根据不同的构建方式进行处理,否则可能出现打包失败的问题

d.多模块项目打包可能遇到的问题

项目打包遇到的问题:

​ 1>打包时需使用:mvn clean package -Dmaven.test.skip=true 忽略测试进行打包。测试代码不会影响项目发布,但是会影响项目的打包

​ 2>项目打包报错:

Non-resolvable parent POM for demo:demo-base:0.0.1-SNAPSHOT: Could not find artifact demo:demo:pom:0.0.1-SNAPSHOT and 'parent.relativePath' points at no local POM

​ 解决方法:修改父项目,子Module:demo-base,demo-dao,demo-service,demo-web的 pom 文件,删除<parent></parent>标签的这句 <relativePath/> <!-- lookup parent from repository -->

​ 3>项目打包报错:

[ERROR] Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:1.5.16.RELEASE:repackage (default) on project demo-base: Execution default of goal org.springframework.boot:spring-boot-maven-plugin:1.5.16.RELEASE:repackage failed: Unable to find main class -> [Help 1]

​ 原因:这是 demo-base 找不到主类的问题。因为此项目为多模块项目,但并不是每一个子模块都需要打成可执行的 Jar 包,如此项目中实际需要打成可执行的Jar 包的只有demo-web,且我们在构建项目之前已经将出demo-web外的项目的启动类即主类删了。所以此处会报错。

​ 解决方法:修改处demo-web外的项目:父项目demo,demo-base、demo-dao、demo-service 的 pom 文件,删除其中关于打包的配置。

image-20201004165144423

评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v3.1.3