如何使用MongoRepository动态设置主机名

时间:2016-09-06 18:44:40

标签: mongodb spring-boot spring-data spring-data-mongodb mongorepository

我正在使用Spring-Boot项目和MongoRepository而不是MongoTemplate。

使用MongoTemplate时,可以使用MongoConnectionPool动态设置主机名,如下所示:

> formals(predict.train)$na.action
na.omit

如何使用MongoRepository实现相同的效果?

我知道我可以通过指定

来指定主机名和端口
na.fail

在application.properties文件中。

但是我使用GenericContainer通过Docker容器启动mongo实例来运行我的单元测试。容器动态地为mongo实例分配了IP地址和端口,因此我需要能够在运行时动态设置MongoRepository的主机名和端口。

这就是我设置单元测试的方法。

// QUEUE Object Definition

var Queue = function() {
  this.first = null;
  this.last = null;
  this.size = 0;
};

var Node = function(data) {
  this.data = data;
  this.next = null;
};

Queue.prototype.enqueue = function(data) {
  var node = new Node(data);

  if (!this.first){ // for empty list first and last are the same
    this.first = node;
    this.last = node;
  } else { // otherwise we stick it on the end
    this.last.next=node;
    this.last=node;
  }

  this.size += 1;
  return node;
};

Queue.prototype.dequeue = function() {
  if (!this.first) //check for empty list
    return null;

  temp = this.first; // grab top of list
  if (this.first==this.last) {
    this.last=null;  // when we need to pop the last one
  }
  this.first = this.first.next; // move top of list down
  this.size -= 1;
  return temp;
};

这就是我在MongoConfiguration.class中的内容

@Autowired
MongoConnectionPool mongoConn
....
mongoConn.setHostname("127.23.45.89");
mongoConn.setPort(27017);

3 个答案:

答案 0 :(得分:1)

  

容器动态地为mongo分配IP地址和端口   实例,因此我需要能够动态设置主机名   和运行时MongoRepository的端口。

您还可以在发布时覆盖属性:

$ 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命令,但我不明白为什么我们不能提供多个!{/ p>

答案 1 :(得分:0)

用你的方式覆盖MongoTemplate Bean

您可以在此测试中定义其他@Configuration类,只是为了覆盖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添加到您的setUp方法
  • 将ip转换为静态字段:containerIpAddress = mongo.getContainerIpAddress();
  • 添加@Configuration MongoTestConfiguration以重新定义MongoTemplate

答案 2 :(得分:0)

@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);

}
}