文章目录
有理解不深刻、不恰当的地方欢迎指出。
项目新建
新建一个Maven项目,删掉src
文件夹,就作为父项目。
子项目建立在这个之下。
项目结构
现在只做登录验证,其它子项目只是建起来不写什么。
选择SpringCloud Alibaba 版本
当前最新版本为
2021.0.4.0
在 github 的wiki
里可以看到对版本依赖的描述:https://github.com/alibaba/spring-cloud-alibaba/wiki
最终确定版本:
- SpringCloud: 2021.0.4.0
- SpringBoot: 2.6.11
- Sentinel: 1.8.5
- Nacos: 2.0.4
- RoketMQ: 4.9.4
(说明中没有明确指出2021.0.4.0
版本到底用什么版本的Dubbo
,自己不会,暂时不管这个。)
统一管理项目依赖
我的想法是这样的:
1、父项目的pom
文件中,使用properties
规定版本号、dependencyManagement
把可能用到的依赖写进去。
2、使用SpringCloud
,每个子项目(服务)导入依赖时,只指定依赖名,而不需要指定版本号。
在子项目中:
创建一个启动类加上启动类注解和扫描组件的注解:
(注意: 此处我使用的是JDK11,主机装的是JDK1.8,需要改成使用JDK11开发。)
关于启动失败的报错分析:
1、BaseMapper 启动错误
报错信息:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.cat.auth.mapper.UserMapper' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1801) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1357) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1311) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:656) ~[spring-beans-5.3.22.jar:5.3.22]
... 71 common frames omitted
Disconnected from the target VM, address: '127.0.0.1:8710', transport: 'socket'
Process finished with exit code 1
错误信息主要在于:
Caused by:
org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean
of type ‘com.cat.auth.mapper.UserMapper’ available:
expected at least 1 bean which qualifies as autowire candidate. Dependency annotations:
{@org.springframework.beans.factory.annotation.Autowired(required=true)}
原因没有找到 BaseMapper 对应的实现,没法注入,实际上我在子项目中导入的是:
<!-- mybatis-plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
通过百度和试验验证:
仅仅导入 mybatis-plus
的依赖,虽然支持BaseMapper
接口继承,但实际上没有对应的实现类。
不使用mybatis-plus
依赖,改成直接使用mybatis-plus-boot-starter
。
mybatis-plus-boot-starter
提供了基本的Mapper实现。
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus-boot-starter.version}</version>
</dependency>
刷新依赖再启动就不报错了。
2、SLF4J 报错
报错信息:
SLF4J: No SLF4J providers were found.
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#noProviders for further details.
SLF4J: Class path contains SLF4J bindings targeting slf4j-api versions prior to 1.8.
SLF4J: Ignoring binding found at [jar:file:/D:/Program%20Files/apache-maven-3.8.6/repository/ch/qos/logback/logback-classic/1.2.11/logback-classic-1.2.11.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#ignoredBindings for an explanation.
之前忘了导入sl4j
及相关的依赖,sl4j
使用需要保持以下三个依赖:
(1)slf4j-api
(2)slf4j-reload4j (原 slf4j-log4j12)
(3)log4j-core (原 log4j)
或者两个依赖的版本:
(1)slf4j-api
(2)slf4j-simple
关于sl4j
的使用,可以参考官网给出的使用手册:
https://www.slf4j.org/manual.html
(有时间单独写一篇短文介绍一下)
我选择的版本是全部最新版:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.5</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-reload4j</artifactId>
<version>2.0.5</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.19.0</version>
</dependency>
引入后启动仍旧有爆红信息:
log4j:WARN No appenders could be found for logger (org.springframework.boot.env.OriginTrackedYamlLoader).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
根据提示,大概能知道意思:
log4j:WARN Please initialize the log4j system properly.
也就是需要我们初始化log4j
的一些设置。
在这个子项目的resource
目录下,新建一个log4j.prope
文件:
复杂的配置这里不多写,先把项目跑起来不报错再说。
log4j.properties
的内容(根据功能需要,还会继续修改):
log4j.rootLogger=WARN, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
3、使用Maven Helper检查依赖冲突
IDEA里直接搜索Maven Helper
安装,重启IDEA后,打开pom
文件,发现pom
文件下发多出一个选择:
从上图中可以看出,有时候各种依赖本身都会依赖一些别的项目,很容易发生版本间的冲突。
这个工具可以帮助扫描当前的pom
中依赖版本的冲突问题。
右键冲突的版本,Exclude
就可以自动帮忙在pom
文件里生成忽略信息:
然后只要刷新一下maven
,就可以了。
(Maven Helper
工具生成的<exclusion>
标签,是在我们检查的这个子项目的pom
文件中,我们应该把这一段复制到父项目的pom
中。子项目不用引入。)
上图中:
因为依赖的
mybatis-plus-boot-starter
和mybatis-plus
版本太高,甚至连spring-core
等多个包都和我引入的spring-boot-starter-web
有依赖冲突。
本来以为降低一下版本就可以了,结果发现mybatis-plus-boot-starter
许多版本,没有一个能契合spring.boot-web.version 2.6.11版本
。
只能将标红的都exclude
。
不过还是要说:
- 有时候,有合适的对应版本的依赖能够契合,当然优先选择降低或者调高到对应版本。
- 如果不好找对应版本或者确实需要兼容,才选择
exclusions
。exclusions
标签只在父项目dependencyManagement
管理就可以,子项目依旧不用引入。
4、启动项目不打印日志
在解决依赖冲突过程中发现一个问题:
1、本身mybatis-plus-boot-starter
与我引入的spring-boot-starter-web
存在sl4j-api
版本的依赖冲突,这个依赖冲突十分严重,直接导致控制台无法输出springboot的日志。
实际上程序已启动成功,接口也能正常访问,但控制台就是没有springboot的日志。
解决上述依赖的办法是:
在mybatis-plus-boot-starter
的<exclusions>
内加入
<exclusion>
<artifactId>slf4j-api</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
前提是,不能在父项目或者子项目的
pom
文件中,引入包含新的sl4j-api
在内的sl4j三件套
。
2、而在父项目或者子项目的pom
文件中,
引入包含新的sl4j-api
在内的sl4j三件套
之后。
不管子项目的依赖中有没有指定sl4j三件套
,控制台都无法正常输出日志。
而且上述的依赖冲突在Maven Helper
中是看不到的,将被隐藏,
可能工具以为不会冲突,实际上不是。
最终经过多次试验得出的解决方案是:
1、在父项目的pom
文件中排除掉slf4j-api
,也就是加上:<exclusion> <artifactId>slf4j-api</artifactId> <groupId>org.slf4j</groupId> </exclusion>
2、父项目的
pom
文件中:
slf4j-api
与slf4j-reload4j
(本身依赖了slf4j-api)都不能引入。
只需要引入log4j-core
一项就能解决前面说的sl4j
报错的问题。
并且不会影响springboot打印日志。<dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>${log4j-core.version}</version> </dependency>
4、Dependency not found
关于父项目的pom
文件中,我加入上述的sl4j
依赖,爆红无法下载,重启IDEA也没办法。
始终提示Dependency 'xx.xx' not found
最后我的解决办法是:
1、先将完整的依赖,加到子项目的pom
文件中,父项目不加依赖。
2、刷新maven
,子项目下载依赖成功后,maven仓库文件夹里就有这个包了。
3、移除子项目依赖中的版本号,像前面一样把依赖放到父项目的dependencyManagement
中管理版本。
无报错启动的SpringBoot依赖
解决掉上面的所有问题后:
项目终于没问题了(哭死……)
父项目管理依赖:
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<junit.version>4.13.2</junit.version>
<lombok.version>1.18.24</lombok.version>
<spring.cloud.version>2021.0.4</spring.cloud.version>
<spring.boot.version>2.6.11</spring.boot.version>
<spring.boot-web.version>2.6.11</spring.boot-web.version>
<mybatis-plus.version>3.5.0</mybatis-plus.version>
<mybatis-plus-boot-starter.version>3.5.0</mybatis-plus-boot-starter.version>
<jedis.version>4.3.1</jedis.version>
<mysql.version>8.0.25</mysql.version>
<slf4j-api.version>2.0.5</slf4j-api.version>
<slf4j-reload4j.version>2.0.5</slf4j-reload4j.version>
<log4j-core.version>2.19.0</log4j-core.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<!-- springCloud -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2021.0.4</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- SpringBoot Web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${spring.boot-web.version}</version>
</dependency>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!-- mybatis-plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<!-- mybatis-plus-starter 提供BaseMapper的实现 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus-boot-starter.version}</version>
<exclusions>
<exclusion>
<artifactId>slf4j-api</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- Jedis 操作Redis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>${jedis.version}</version>
</dependency>
<!-- slf4j 三件套只需要log4j-core就不会报错了-->
<!-- <dependency>-->
<!-- <groupId>org.slf4j</groupId>-->
<!-- <artifactId>slf4j-api</artifactId>-->
<!-- <version>${slf4j-api.version}</version>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.slf4j</groupId>-->
<!-- <artifactId>slf4j-reload4j</artifactId>-->
<!-- <version>${slf4j-reload4j.version}</version>-->
<!-- </dependency>-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j-core.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
子项目 cat-auth 中的依赖:
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
OpenJDK11手动生成jre文件夹
先下载一个JDK11,因为JDK11初始状态是没有JRE的。
然后在JDK11的/bin
目录下,打开powershell
或者管理员终端
,执行:
./jlink --module-path jmods --add-modules java.desktop --output jre
与Linux下生成jre
文件夹一样,生成的jre
同样在bin
下面:
与之前部署Kafka
中部署JDK11一样,把jre
文件夹挪到与bin
同级。
IDEA中需要指定JDK的地方
Maven下: 除了指定mavne
目录外,还需要指定JDK
为项目模块指定JDK:
为每个子项目指定JDK:
如果指定子项目JDK出现JDK11自己变回JDK1.8的情况,可以尝试先手动清理掉每一个项目的maven包(clean
),刷新Maven或者清除缓存重启IDEA。