如何使用 MongoRepository 动态设置主机名
how to dynamically set the hostname with MongoRepository
我正在使用 Spring-Boot 项目和 MongoRepository 而不是 MongoTemplate。
使用 MongoTemplate 时,可以像这样使用 MongoConnectionPool 动态设置主机名:
@Autowired
MongoConnectionPool mongoConn
....
mongoConn.setHostname("127.23.45.89");
mongoConn.setPort(27017);
如何使用 MongoRepository 实现相同的效果?
我知道我可以通过指定
来指定主机名和端口
spring.data.mongodb.host=hostname1
spring.data.mongodb.port=27017
在 application.properties 文件中。
但是我正在使用 GenericContainer 通过 Docker 容器启动一个 mongo 实例到 运行 我的单元测试。容器将 IP 地址和端口动态分配给 mongo 实例,因此我需要能够在 运行 时间为 MongoRepository 动态设置主机名和端口。
这就是我设置单元测试的方式。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = MongoConfiguration.class)
public class HierarchiesServiceImplTests {
private static final Logger log = LoggerFactory.getLogger(HierarchiesServiceImplTests.class);
@Autowired
private HierarchiesService hierarchiesService;
@Autowired
private HierarchyRepository hierarchyRepo;
@BeforeClass
public void setUp() {
MockitoAnnotations.initMocks(this);
startMongo();
}
/**
* Starts a Mongo docker container, and configures the repository factory to use this instance.
*/
private void startMongo() {
GenericContainer mongo = new GenericContainer("mongo:3")
.withExposedPorts(27017);
mongo.start();
String containerIpAddress = mongo.getContainerIpAddress();
int mappedPort = mongo.getMappedPort(27017);
//TODO: set the hostname and port here so that the MongoRepository use this mongo instance instead of the default localhost.
log.info("Container mongo:3 listening on {}:{}", containerIpAddress, mappedPort);
}
这是我的 MongoConfiguration.class
@Configuration
@EnableMongoRepositories
@ComponentScan({"com.is.hierarchies.service"})
public class MongoConfiguration {
}
The container dynamically assigned IP Address and port to the mongo
instance and thus I need to be able to dynamically set the hostname
and port for the MongoRepository at run time.
您还可以在启动时覆盖属性:
$ java -jar YourApp.jar --spring.data.mongodb.host=hostnamexyz --spring.data.mongodb.port=123
或
$ java -Dspring.data.mongodb.host=hostnamexyz -Dspring.data.mongodb.port=123 -jar YourApp.jar
或通过Docker:
$ docker run -e spring.data.mongodb.host=hostnamexyz -e spring.data.mongodb.port=123 -p 8080:8080 -i -t yourdocker:latest
我只用一个 -e param
测试了 docker 命令,但我不明白为什么我们不能提供多个!
用你的覆盖 MongoTemplate Bean
您可以在此测试中定义额外的 @Configuration
class,只是为了覆盖 MongoTemplate
。
MongoRepository
使用 MongoTemplate
来执行其操作,因此通过定义 @Bean MongoTemplate
,我们能够设置我们选择的连接细节。这就是 Repository
将要使用的内容。
完整代码:
RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = MongoConfiguration.class)
public class HierarchiesServiceImplTests {
private static final Logger log = LoggerFactory.getLogger(HierarchiesServiceImplTests.class);
private static String containerIpAddress;
private static int mappedPort;
@Autowired
private HierarchiesService hierarchiesService;
@Autowired
private HierarchyRepository hierarchyRepo;
/**
* Starts a Mongo docker container, and configures the repository factory to use this instance.
*/
private void startMongo() {
GenericContainer mongo = new GenericContainer("mongo:3").withExposedPorts(27017);
mongo.start();
containerIpAddress = mongo.getContainerIpAddress();
mappedPort = mongo.getMappedPort(27017);
log.info("Container mongo:3 listening on {}:{}", containerIpAddress, mappedPort);
}
@Configuration
public static class MongoTestConfiguration {
@Bean
@Primary
public MongoTemplate mongoTemplate() throws DataAccessException, Exception{
return createMongoOperations(containerIpAddress, mappedPort, "mydb", "user", "pwd");
}
private MongoTemplate createMongoOperations(String hostname, int port, String dbName, String user, String pwd) throws DataAccessException, Exception {
MongoCredential mongoCredentials = MongoCredential.createScramSha1Credential(user, dbName, pwd.toCharArray());
MongoClient mongoClient = new MongoClient(new ServerAddress(hostname, port), Arrays.asList(mongoCredentials));
Mongo mongo = new SimpleMongoDbFactory(mongoClient, dbName).getDb().getMongo();
return new MongoTemplate(mongo, dbName);
}
}
@BeforeClass
public static void setUp() {
MockitoAnnotations.initMocks(this);
startMongo();
}
我做了什么:
- 将
static
添加到您的设置方法中
- 将ip转换为静态字段:
containerIpAddress = mongo.getContainerIpAddress();
- 添加@Configuration MongoTestConfiguration 重新定义MongoTemplate
@Alex 给了我一个想法来制作一个更清洁的解决方案。我没有修改测试套件中的 MongoTemplate,而是将该代码移至 MongoConfiguration.java。
这是我最终解决问题的方法。
在我的 MongoConfiguration.class 中,我进行了以下更改:
@Configuration
@EnableMongoRepositories
@ComponentScan({"com.is.hierarchies.service"})
public class MongoConfiguration extends AbstractMongoConfiguration {
String containerIpAddress;
Integer mappedPort;
@Override
public Mongo mongo() throws Exception {
startMongo();
return new Mongo(containerIpAddress,mappedPort);
}
@Override
public String getDatabaseName() {
return "hierarchies_db";
}
/**
* Starts a Mongo docker container, and configures the repository factory to use this instance.
*/
private void startMongo() {
GenericContainer mongo = new GenericContainer("mongo:3")
.withExposedPorts(27017);
mongo.start();
containerIpAddress = mongo.getContainerIpAddress();
mappedPort = mongo.getMappedPort(27017);
}
}
我正在使用 Spring-Boot 项目和 MongoRepository 而不是 MongoTemplate。
使用 MongoTemplate 时,可以像这样使用 MongoConnectionPool 动态设置主机名:
@Autowired
MongoConnectionPool mongoConn
....
mongoConn.setHostname("127.23.45.89");
mongoConn.setPort(27017);
如何使用 MongoRepository 实现相同的效果?
我知道我可以通过指定
来指定主机名和端口spring.data.mongodb.host=hostname1
spring.data.mongodb.port=27017
在 application.properties 文件中。
但是我正在使用 GenericContainer 通过 Docker 容器启动一个 mongo 实例到 运行 我的单元测试。容器将 IP 地址和端口动态分配给 mongo 实例,因此我需要能够在 运行 时间为 MongoRepository 动态设置主机名和端口。
这就是我设置单元测试的方式。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = MongoConfiguration.class)
public class HierarchiesServiceImplTests {
private static final Logger log = LoggerFactory.getLogger(HierarchiesServiceImplTests.class);
@Autowired
private HierarchiesService hierarchiesService;
@Autowired
private HierarchyRepository hierarchyRepo;
@BeforeClass
public void setUp() {
MockitoAnnotations.initMocks(this);
startMongo();
}
/**
* Starts a Mongo docker container, and configures the repository factory to use this instance.
*/
private void startMongo() {
GenericContainer mongo = new GenericContainer("mongo:3")
.withExposedPorts(27017);
mongo.start();
String containerIpAddress = mongo.getContainerIpAddress();
int mappedPort = mongo.getMappedPort(27017);
//TODO: set the hostname and port here so that the MongoRepository use this mongo instance instead of the default localhost.
log.info("Container mongo:3 listening on {}:{}", containerIpAddress, mappedPort);
}
这是我的 MongoConfiguration.class
@Configuration
@EnableMongoRepositories
@ComponentScan({"com.is.hierarchies.service"})
public class MongoConfiguration {
}
The container dynamically assigned IP Address and port to the mongo instance and thus I need to be able to dynamically set the hostname and port for the MongoRepository at run time.
您还可以在启动时覆盖属性:
$ java -jar YourApp.jar --spring.data.mongodb.host=hostnamexyz --spring.data.mongodb.port=123
或
$ java -Dspring.data.mongodb.host=hostnamexyz -Dspring.data.mongodb.port=123 -jar YourApp.jar
或通过Docker:
$ docker run -e spring.data.mongodb.host=hostnamexyz -e spring.data.mongodb.port=123 -p 8080:8080 -i -t yourdocker:latest
我只用一个 -e param
测试了 docker 命令,但我不明白为什么我们不能提供多个!
用你的覆盖 MongoTemplate Bean
您可以在此测试中定义额外的 @Configuration
class,只是为了覆盖 MongoTemplate
。
MongoRepository
使用 MongoTemplate
来执行其操作,因此通过定义 @Bean MongoTemplate
,我们能够设置我们选择的连接细节。这就是 Repository
将要使用的内容。
完整代码:
RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = MongoConfiguration.class)
public class HierarchiesServiceImplTests {
private static final Logger log = LoggerFactory.getLogger(HierarchiesServiceImplTests.class);
private static String containerIpAddress;
private static int mappedPort;
@Autowired
private HierarchiesService hierarchiesService;
@Autowired
private HierarchyRepository hierarchyRepo;
/**
* Starts a Mongo docker container, and configures the repository factory to use this instance.
*/
private void startMongo() {
GenericContainer mongo = new GenericContainer("mongo:3").withExposedPorts(27017);
mongo.start();
containerIpAddress = mongo.getContainerIpAddress();
mappedPort = mongo.getMappedPort(27017);
log.info("Container mongo:3 listening on {}:{}", containerIpAddress, mappedPort);
}
@Configuration
public static class MongoTestConfiguration {
@Bean
@Primary
public MongoTemplate mongoTemplate() throws DataAccessException, Exception{
return createMongoOperations(containerIpAddress, mappedPort, "mydb", "user", "pwd");
}
private MongoTemplate createMongoOperations(String hostname, int port, String dbName, String user, String pwd) throws DataAccessException, Exception {
MongoCredential mongoCredentials = MongoCredential.createScramSha1Credential(user, dbName, pwd.toCharArray());
MongoClient mongoClient = new MongoClient(new ServerAddress(hostname, port), Arrays.asList(mongoCredentials));
Mongo mongo = new SimpleMongoDbFactory(mongoClient, dbName).getDb().getMongo();
return new MongoTemplate(mongo, dbName);
}
}
@BeforeClass
public static void setUp() {
MockitoAnnotations.initMocks(this);
startMongo();
}
我做了什么:
- 将
static
添加到您的设置方法中 - 将ip转换为静态字段:
containerIpAddress = mongo.getContainerIpAddress();
- 添加@Configuration MongoTestConfiguration 重新定义MongoTemplate
@Alex 给了我一个想法来制作一个更清洁的解决方案。我没有修改测试套件中的 MongoTemplate,而是将该代码移至 MongoConfiguration.java。
这是我最终解决问题的方法。
在我的 MongoConfiguration.class 中,我进行了以下更改:
@Configuration
@EnableMongoRepositories
@ComponentScan({"com.is.hierarchies.service"})
public class MongoConfiguration extends AbstractMongoConfiguration {
String containerIpAddress;
Integer mappedPort;
@Override
public Mongo mongo() throws Exception {
startMongo();
return new Mongo(containerIpAddress,mappedPort);
}
@Override
public String getDatabaseName() {
return "hierarchies_db";
}
/**
* Starts a Mongo docker container, and configures the repository factory to use this instance.
*/
private void startMongo() {
GenericContainer mongo = new GenericContainer("mongo:3")
.withExposedPorts(27017);
mongo.start();
containerIpAddress = mongo.getContainerIpAddress();
mappedPort = mongo.getMappedPort(27017);
}
}