SpringBoot自定义starter
1.需求
2. 代码实现
3. 用到的注解
4.遇到的问题
1.需求
目前Java项目框架一般都是以SpringBoot作为脚手架来搭建的,具体什么原因就不用我在这里多说了吧。为了方便我们使用呢,它也封装了很多相关的starter组件,只要我们在项目中引入就行了。因为我们项目中用的是第三方插件Jongo来操作数据库MongoDB 的,所以这里我就尝试着吧Jongo封装成一个自定义starter。
2. 代码实现
1.首先我们需要创建一个mudule。我这里取名为spring-boot-starter-mongodb-jongo,大致如下:
pom.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.8.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-boot-starter-mongodb-jongo</artifactId>
<version>1.0-SNAPSHOT</version>
<name>spring-boot-starter-mongodb-jongo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.12.3</version>
</dependency>
<dependency>
<groupId>org.jongo</groupId>
<artifactId>jongo</artifactId>
<version>1.4.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.4.2</version>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
</plugins>
</build>
</project>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
pom文件设置了SpringBoot的版本,引入了Jongo和Mongo的一些依赖,版本的话可以自行修改。因为创建module时默认引入的是SpringBoot的插件,打包的时候会自动去寻找SpringBoot的启动类,所以这里需要把插件修改为maven 的一个插件maven-surefire-plugin。
接下来是配置代码:
首先定义一个属性类JongoAutoProperties,为了接收我们配置的一些mongodb的属性信息:
package org.springframework.boot.autoconfigure.data.mongodb;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.io.Serializable;
@ConfigurationProperties(
prefix = "mongo"
)
public class JongoAutoProperties implements Serializable {
private String host="127.0.0.1"; // 主库
private int port=27017; // 主库
private String cluser="127.0.0.1"; // 副本集
private int cport=27017; // 副本集
private String database;
private String username;
private String password;
private boolean open=true; // 定义一个属性决定是否加载该组件
省略get和set方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@ConfigurationProperties:加载SpringBoot属性文件application.properties中的属性配置.
因为mongodb有可能会设置副本集,所以我这里多定义了两个属性接受副本集的信息。
实际上应该定义一个list来存放数据库ip和端口,因为又可能会有很多个链接信息。
定义一个配置类JongoAutoConfig自动注入一些Bean对象
package org.springframework.boot.autoconfigure.data.mongodb;
import com.mongodb.*;
import org.jongo.Jongo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.MongoDatabaseFactory;
import java.util.ArrayList;
import java.util.List;
@Configuration
@ConditionalOnClass({Jongo.class,JongoTemplate.class})
@EnableConfigurationProperties({JongoAutoProperties.class})
@ConditionalOnProperty(
prefix = "mongo",
value = "open",
havingValue = "true"
)
public class JongoAutoConfig {
@Autowired
private JongoAutoProperties jongoAutoProperties;
@Bean
@ConditionalOnMissingBean(
name = {"mongoDatabaseFactory"}
)
public MongoDatabaseFactory mongoDatabaseFactory(){
return new MongoDatabaseFactory();
}
@Bean
@ConditionalOnMissingBean(name = "jongoTemplate")
public JongoTemplate jongoTemplate(@Qualifier("jongo") Jongo jongo){
return new JongoTemplate(jongo);
}
@Bean
@ConditionalOnMissingBean(
name = "jongo"
)
public Jongo jongo(){
List<ServerAddress> serverAddresses = new ArrayList<>();
ServerAddress serverAddress = new ServerAddress(this.jongoAutoProperties.getHost(), this.jongoAutoProperties.getPort());
serverAddresses.add(serverAddress);
serverAddress = new ServerAddress(this.jongoAutoProperties.getCluser(), this.jongoAutoProperties.getCport());
serverAddresses.add(serverAddress);
MongoCredential credential = MongoCredential.createCredential(this.jongoAutoProperties.getUsername(), this.jongoAutoProperties.getDatabase(), this.jongoAutoProperties.getPassword().toCharArray());
MongoClientOptions.Builder build = new MongoClientOptions.Builder();
build.minConnectionsPerHost(10);
build.connectionsPerHost(200); //与目标数据库能够建立的最大connection数量为50
build.threadsAllowedToBlockForConnectionMultiplier(400);
build.maxWaitTime(1000*60*2);
build.connectTimeout(1000*60*1); //与数据库建立连接的timeout设置为1分钟
MongoClientOptions myOptions = build.readPreference(ReadPreference.secondaryPreferred()).build();
// MongoClientOptions myOptions = build.build();
//数据库连接实例
MongoClient mongoClient = new MongoClient(serverAddresses, credential, myOptions);
DB mondb = mongoClient.getDB(this.jongoAutoProperties.getDatabase());
return new Jongo(mondb);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
配置类里引入属性类JongoAutoProperties。里面使用@Bean分别实例化 MongoDatabaseFactory,JongoTemplate,Jongo。
1. MongoDatabaseFactory:自已定义的一个空类,为了防止SpringBoot自动装配autoconfigure里的MongoTemplate实例化。
2. JongoTemplate:自己封装的对业务的持久化对象,操作mongodb。为什么要封装这个对象,为了装逼。。。。
3. Jongo:第三方插件Jongo实例化对象。
JongoAutoProperties实例化有两种方式:
1.使用注解jongoAutoProperties。
2.使用构造方法:
public JongoAutoConfig(JongoAutoProperties jongoAutoProperties){
this.jongoAutoProperties = jongoAutoProperties;
}
使用构造方法时,需要注意,不能再写无参构造方法,因为启动的时候会默认使用无参构造去实例化类,如果没有的化才会使用有参构造
数据操作类JongoTemplate
package org.springframework.boot.autoconfigure.data.mongodb;
import org.jongo.Jongo;
import org.jongo.MongoCollection;
public class JongoTemplate {
private Jongo jongo;
public JongoTemplate(){}
public JongoTemplate(Jongo jongo){
this.jongo = jongo;
}
public MongoCollection getMongoCollection(String tableName){
return jongo.getCollection(tableName);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
里面就封装类一个Jongo类。
MongoDatabaseFactory这个类是个空类
package org.springframework.data.mongodb;
public class MongoDatabaseFactory {
}
1
2
3
4
还有个最重要的文件spring.factories,因为SpringBoot在自动装配starter的时候扫描所有引入的jar包中的WEB-INF目录下的spring.factories这个文件。里面引入了我们自定义的Configuration。
我们可以参考SpringBoot封装好的starter。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.springframework.boot.autoconfigure.data.mongodb.JongoAutoConfig
1
按照目录创建好就行了。
org.springframework.boot.autoconfigure.EnableAutoConfiguration:这个类就是自动加载的配置类。springBoot会按照这个类的值去加载我们写的configuration。
到这就创建完了一个自定义starter。
3. 用到的注解
@ConfigurationProperties(prefix = “mongo”):装配application.properties中的属性,prefix设置前缀名,属性类的中的属性名字对应属性文件中的名字。
@Configuration :配置类注解,表明这个类是一个配置类。
@ConditionalOnClass({Jongo.class,JongoTemplate.class}) :配置类的加载条件,如果符合这个条件才加载,条件是某个类。这里是如果项目中引入的有Jongo,JongoTemplate这个类才去加载这个配置类
@EnableConfigurationProperties({JongoAutoProperties.class}):引入属性配置类。
@ConditionalOnProperty(
prefix = “mongo”,
value = “open”,
havingValue = “true”
):配置类的加载条件,如果符合条件才加载。条件是属性文件的配置值。
@ConditionalOnMissingBean(
name = {“mongoDatabaseFactory”}
):如果项目中还没有实例化这个类才去实例化,如果已经有就不会再去实例化,name指定名字。
别的就是一些常用的注解了。
这些注解在SpringBoot里封装的starter中都有体现,可以去了解下。
4.遇到的问题
1.Failed to execute goal io.spring.javaformat:spring-javaformat-maven-plugin:0.0.6:validate (default) on project spring-boot-starter-data-mongodb-jongo: Formatting violations found in the following files:
** /Users/lxxx/ld-springboot-mongo-jongo-starter/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoDBPorperties.java **
Run spring-javaformat:apply to fix.
答:是因为这是自己写的starter,格式可能有些问题,解决方法上面也说了,在这个module下使用这个命令 mvn spring-javaformat:apply,得配置下maven环境。
2.在启动的时候JongoAutoConfig中JongoAutoProperties属性没有注入进来?
答:因为我多加了个无参构造方法,去掉就好了。
**3.项目启动成功,但是日志有报错:mongo cluster localhost:27017 connect timeout **
答:我在配置的时候配置了mongo的链接信息,没有配置过localhost:27017的配置,最后发现是SpringBoot的autoConfigure中配置了MongoAutoConfiguration,进源码看下:
看下这个加载的条件:项目中有MongoClient这个类,没有实例化org.springframework.data.mongodb.MongoDbFactory这个Bean对象。
那所以如果我们不想让SpringBoot自动加载这个配置,所以这两个条件得不能让它满足。MongoClient这个类我们肯定得用到,所以不能使用这个条件排除,所以要自己手动创建个org.springframework.data.mongodb.MongoDbFactory这个类,手动去实例化,
MongoAutoConfiguration检测到有org.springframework.data.mongodb.MongoDbFactory这个Bean对象才不会去实例话。
————————————————
版权声明:本文为CSDN博主「站在墙头上」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_19674263/article/details/107252975