背景
springboot项目启动时,报错
com.mongodb.MongoSocketOpenException: Exception opening socket
at com.mongodb.internal.connection.SocketStream.open(SocketStream.java:70) ~[mongodb-driver-core-3.11.2.jar:na]
at com.mongodb.internal.connection.InternalStreamConnection.open(InternalStreamConnection.java:128) ~[mongodb-driver-core-3.11.2.jar:na]
at com.mongodb.internal.connection.DefaultServerMonitor$ServerMonitorRunnable.run(DefaultServerMonitor.java:117) ~[mongodb-driver-core-3.11.2.jar:na]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_181]
Caused by: java.net.ConnectException: Connection refused: connect
at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method) ~[na:1.8.0_181]
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85) ~[na:1.8.0_181]
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350) ~[na:1.8.0_181]
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) ~[na:1.8.0_181]
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188) ~[na:1.8.0_181]
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172) ~[na:1.8.0_181]
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) ~[na:1.8.0_181]
at java.net.Socket.connect(Socket.java:589) ~[na:1.8.0_181]
at com.mongodb.internal.connection.SocketStreamHelper.initialize(SocketStreamHelper.java:64) ~[mongodb-driver-core-3.11.2.jar:na]
at com.mongodb.internal.connection.SocketStream.initializeSocket(SocketStream.java:79) ~[mongodb-driver-core-3.11.2.jar:na]
at com.mongodb.internal.connection.SocketStream.open(SocketStream.java:65) ~[mongodb-driver-core-3.11.2.jar:na]
... 3 common frames omitted
并且用工具能够连接mongodb,已经排除是mongodb不能连接的问题
原因
项目中配置了自定义的MongoClient
:
java
@Bean
public MongoDatabase mongoDatabase() {
String host = mongodbProperties.getHost();
Integer port = mongodbProperties.getPort();
MongoClientOptions.Builder options = new MongoClientOptions.Builder();
options.connectionsPerHost(mongodbProperties.getPoolSize());
options.threadsAllowedToBlockForConnectionMultiplier(mongodbProperties.getBlockSize());
options.build();
MongoClient mongoClient = null;
ServerAddress serverAddress = new ServerAddress(mongodbProperties.getHost(), mongodbProperties.getPort());
List<ServerAddress> seeds = new ArrayList<>();
seeds.add(serverAddress);
String userName = mongodbProperties.getUserName();
String password = mongodbProperties.getPassword();
if (StringUtils.isNotBlank(userName) && StringUtils.isNotBlank(password)){
MongoCredential credentials = MongoCredential.createCredential(userName, mongodbProperties.getDatabase(), password.toCharArray());
List<MongoCredential> credentialsList = new ArrayList<>();
credentialsList.add(credentials);
mongoClient = new MongoClient(seeds, credentialsList);
}else {
mongoClient = new MongoClient(host, port);
}
return mongoClient.getDatabase(mongodbProperties.getDatabase());
}
而springboot在启动时会自动实例化一个MongoClient
:
源码如下:
java
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.mongo;
import com.mongodb.MongoClientURI;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* Configuration properties for Mongo.
*
* @author Dave Syer
* @author Phillip Webb
* @author Josh Long
* @author Andy Wilkinson
* @author Eddú Meléndez
* @author Stephane Nicoll
* @author Nasko Vasilev
* @author Mark Paluch
* @author Artsiom Yudovin
* @since 1.0.0
*/
@ConfigurationProperties(prefix = "spring.data.mongodb")
public class MongoProperties {
/**
* Default port used when the configured port is {@code null}.
*/
public static final int DEFAULT_PORT = 27017;
/**
* Default URI used when the configured URI is {@code null}.
*/
public static final String DEFAULT_URI = "mongodb://localhost/test";
/**
* Mongo server host. Cannot be set with URI.
*/
private String host;
/**
* Mongo server port. Cannot be set with URI.
*/
private Integer port = null;
/**
* Mongo database URI. Cannot be set with host, port and credentials.
*/
private String uri;
/**
* Database name.
*/
private String database;
/**
* Authentication database name.
*/
private String authenticationDatabase;
/**
* GridFS database name.
*/
private String gridFsDatabase;
/**
* Login user of the mongo server. Cannot be set with URI.
*/
private String username;
/**
* Login password of the mongo server. Cannot be set with URI.
*/
private char[] password;
/**
* Fully qualified name of the FieldNamingStrategy to use.
*/
private Class<?> fieldNamingStrategy;
/**
* Whether to enable auto-index creation.
*/
private Boolean autoIndexCreation;
public String getHost() {
return this.host;
}
public void setHost(String host) {
this.host = host;
}
public String getDatabase() {
return this.database;
}
public void setDatabase(String database) {
this.database = database;
}
public String getAuthenticationDatabase() {
return this.authenticationDatabase;
}
public void setAuthenticationDatabase(String authenticationDatabase) {
this.authenticationDatabase = authenticationDatabase;
}
public String getUsername() {
return this.username;
}
public void setUsername(String username) {
this.username = username;
}
public char[] getPassword() {
return this.password;
}
public void setPassword(char[] password) {
this.password = password;
}
public Class<?> getFieldNamingStrategy() {
return this.fieldNamingStrategy;
}
public void setFieldNamingStrategy(Class<?> fieldNamingStrategy) {
this.fieldNamingStrategy = fieldNamingStrategy;
}
public String getUri() {
return this.uri;
}
public String determineUri() {
return (this.uri != null) ? this.uri : DEFAULT_URI;
}
public void setUri(String uri) {
this.uri = uri;
}
public Integer getPort() {
return this.port;
}
public void setPort(Integer port) {
this.port = port;
}
public String getGridFsDatabase() {
return this.gridFsDatabase;
}
public void setGridFsDatabase(String gridFsDatabase) {
this.gridFsDatabase = gridFsDatabase;
}
public String getMongoClientDatabase() {
if (this.database != null) {
return this.database;
}
return new MongoClientURI(determineUri()).getDatabase();
}
public Boolean isAutoIndexCreation() {
return this.autoIndexCreation;
}
public void setAutoIndexCreation(Boolean autoIndexCreation) {
this.autoIndexCreation = autoIndexCreation;
}
}
解决方法
禁用SpringBoot对Mongo的自动配置,以免和自定义的配置冲突,在SpringBoot启动类上加上:
java
@SpringBootApplication(exclude = MongoAutoConfiguration.class)
由此可见,在任何springboot项目中,如果自定义了MongoClient
且交与了springboot管理,都需要排除掉springboot对mongodb的自动配置