【总结】Spring Boot中MongoDB的使用

Posted by Darkness463 on March 29, 2017

Spring Boot为我们省了很多工作,而在Spring Boot中使用MongoDB也是相当容易的。

【注:本文重点是MongoDB的使用,关于Spring Boot的其他配置、使用不多赘述。】

简单快速使用MongoDB

  1. 添加MongoDB的依赖

     <dependency>
         <groupId>org.springframework.data</groupId>
         <artifactId>spring-data-mongodb</artifactId>
         <version>1.9.2.RELEASE</version>
     </dependency>
     <dependency>
         <groupId>org.springframework.data</groupId>
         <artifactId>spring-data-commons</artifactId>
         <version>1.12.2.RELEASE</version>
     </dependency>
    

    如果单纯想使用MongoDB的driver,可使用下面的配置,在此就不多说了。

     <dependency>
         <groupId>org.mongodb</groupId>
         <artifactId>mongo-java-driver</artifactId>
         <version>3.1.1</version>
     </dependency>
    
  2. 开启Spring Boot自动配置

    Spring Boot支持很多东西的自动配置,如果不太了解如何开启的话我在此简单说一下。想要开启自动配置,需要在启动类加上@SpringBootApplication注解,这个注解相当于@ComponentScan、@EnableAutoConfiguration、@Configuration这三个注解,由于这三个注解使用频率很高,所以Spring Boot加入了这个注解帮助我们少打那么几个字,呵呵。

    另外多数情况下我们会把MongoDB的配置以及其他的一些配置放在一个配置文件中以方便管理和修改,例如我们可以在resources下放一个名为configTest.properties的配置文件,同时我们加上@PropertySource(“classpath:/configVRF.properties”)注解,Spring Boot便会读取配置文件中的内容进行配置。

    因此最终我们的启动类长这样。

     @SpringBootApplication()
     @PropertySource("classpath:/configTest.properties")
     public class Application {
        
         public static void main(String[] args) {
             SpringApplication.run(Application.class, args);
         }
        
     }
    
  3. 配置MongoDB

    对于MongoDB 3.x以上的版本,Spring Boot支持用uri的方式进行配置,我们在配置文件中加上如下形式的配置即可。

     spring.data.mongodb.uri=mongodb://user:pwd@ip1:port1,ip2:port2/database
    

    如果是MongoDB 2.x的版本,我们可以用如下形式进行配置。

     spring.data.mongodb.host=XXX.XXX.XXX.XXX
     spring.data.mongodb.prot=27017
     spring.data.mongodb.username=user
     spring.data.mongodb.password=pwd
     spring.data.mongodb.database=database
    
  4. 使用MongoTemplate进行CRUD

    经过上面的配置后,我们已经可以进行增删改查各类操作了,在此我们建一个Entity类进行测试。使用@Document(collection = “user”)来指明所属的collection。

     @Document(collection = "user")
     public class User {
        
         @Id
         private String _id;
         private String name;
        
         public String get_id() {
             return _id;
         }
        
         public void set_id(String _id) {
             this._id = _id;
         }
        
         public String getName() {
             return name;
         }
        
         public void setName(String name) {
             this.name = name;
         }
        
         @Override
         public String toString() {
             return "User{" +
                     "_id='" + _id + '\'' +
                     ", name='" + name + '\'' +
                     '}';
         }
     }
    

    同时为方便测试我们写一个CommandLineRunner进行一次简单的插入和查询。

     @Component
     public class Test implements CommandLineRunner {
        
         @Resource
         private MongoTemplate mongoTemplate;
        
         @Override
         public void run(String... args) throws Exception {
             insert();
             find();
         }
        
         private void insert() {
             User user = new User();
             user.set_id("123456");
             user.setName("张三");
             mongoTemplate.insert(user);
         }
        
         private void find() {
             User user = mongoTemplate.findOne(Query.query(Criteria.where("_id").is("123456")),
                     User.class);
             System.out.println(user);
         }
     }
    

    最终打印的结果如下,可见插入且查询成功了。

     User{_id='123456', name='张三'}
    

    到此为止我们已经可以开始使用MongoDB了,当然我们可以对查询等操作做一些简单的封装以方便我们使用,在此就不多说了。

多个MongoDB的使用

有些时候在一个项目里我们可能会使用多个MongoDB,而上面说的方法只能配置一个,所以此时我们就不能让Spring Boot去自动配置了。修改启动类的@SpringBootApplication注解,排除MongoAutoConfiguration。

@SpringBootApplication(exclude = MongoAutoConfiguration.class)

这条配置等价于

@EnableAutoConfiguration(exclude = MongoAutoConfiguration.class)

接下来就需要我们手动配置MongoDB了,方法很多,在此提供一种解决方案供大家参考。

  1. 添加MongoDB各种配置参数

    给不同的MongoDB的配置用不同的前缀以便区分且方便Spring Boot自动赋值。

     ################ server MongoDB ################
     server.mongodb.hosts=ip1:port1,ip2:port2
     server.mongodb.username=username
     server.mongodb.password=password
     server.mongodb.database=database
     ################ boss MongoDB ################
     boss.mongodb.hosts=ip3:port3
     boss.mongodb.username=username
     boss.mongodb.password=password
     boss.mongodb.database=database
    
  2. 新建一个BaseMongoConfig

    这个类里面4个变量分别对应配置文件中的hosts、username、password和database,mongo()方法会根据配置的内容创建MongoClient,需要注意的是MongoDB 2.x和3.x版本用的认证方式不同,2.x使用MongoCR认证,3.x使用ScramSha1认证,需要结合实际情况选择。

     public class BaseMongoConfig {
        
         private String hosts;
         private String username;
         private String password;
         private String database;
        
         // get set 方法省略
    
         public MongoTemplate mongoTemplate() throws Exception {
             return new MongoTemplate(mongoDbFactory(), null);
         }
        
         private ServerAddress parseServerAddress(String host)
                 throws UnknownHostException {
             ServerAddress addr = null;
             int mh = host.indexOf(':');
             if (mh < 0) {
                 addr = new ServerAddress(host);
             } else {
                 String serv = host.substring(0, mh).trim();
                 int port = Integer.parseInt(host.substring(mh + 1).trim());
                 addr = new ServerAddress(serv, port);
             }
             return addr;
         }
        
         public MongoClient mongo() throws Exception {
             List<MongoCredential> authList = new ArrayList<>();
             // 【mongodb 3.x】
             MongoCredential auth = MongoCredential.createScramSha1Credential(
                     username, database, password.toCharArray());
             // 【mongodb 2.x】
             //    MongoCredential auth = MongoCredential.createMongoCRCredential(
             //            username, database, password.toCharArray());
             String[] hostArray = hosts.split("[,]");
             int countMongoServers = hostArray.length;
             while (countMongoServers-- > 0) {
                 authList.add(auth);
             }
             MongoClient mongo = null;
             if (hostArray.length == 1) {
                 ServerAddress addr = parseServerAddress(hosts);
                 mongo = new MongoClient(addr, authList);
             } else {
                 List<ServerAddress> reps = new ArrayList<>();
                 for (String host : hostArray) {
                     ServerAddress addr = parseServerAddress(host);
                     reps.add(addr);
                 }
                 mongo = new MongoClient(reps, authList);
             }
             return mongo;
         }
        
         public MongoDbFactory mongoDbFactory() throws Exception {
             return new SimpleMongoDbFactory(mongo(), database);
         }
     }
    
  3. 为每个MongoDB添加配置

    这里用其中一个MongoDB作为例子。使用@ConfigurationProperties(prefix = “server.mongodb”)告诉Spring Boot配置是以server.mongodb开头的,这样Spring Boot能自动给hosts等字段赋值。重写mongoTemplate()和mongo()方法,Spring不允许有名字一样的Bean出现,我们给MongoTemplate和MongoClient一个特殊的名字,且需要在其中一个MongoDB的配置中加上@Primary注解。

     @Configuration
     @ConfigurationProperties(prefix = "server.mongodb")
     public class ServerMongoConfig extends BaseMongoConfig {
        
         @Override
         @Primary
         @Bean(name = "serverMongoTemplate")
         public MongoTemplate mongoTemplate() throws Exception {
             return super.mongoTemplate();
         }
        
         @Override
         @Primary
         @Bean(name = "serverMongo")
         public MongoClient mongo() throws Exception {
             return super.mongo();
         }
     }
    
  4. 使用MongoTemplate

    此时已可以使用MongoTemplate了,不过记得告诉Spring Boot你要的是哪个MongoTemplate哦。

     @Resource(name = "serverMongoTemplate")
     private MongoTemplate serverMongoTemplate;
     @Resource(name = "bossMongoTemplate")
     private MongoTemplate bossMongoTemplate;
    

其他问题

去除_class字段

用上面的方法默认插入时会自动加上一个 _class 字段,其值是Entity类的全路径,如果不需要这个字段可以用以下方法去除。

在BaseMongoConfig添加一个getMongoConverter()方法,在new DefaultMongoTypeMapper(null)时传入null作为参数,这个参数是给DefaultMongoTypeMapper中的typeKey变量赋值,而起默认值就是_class。new MongoTemplate时用这个方法返回的MongoConverter当其第二个参数即可。

public MongoConverter getMongoConverter() throws Exception {
    DbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoDbFactory());
    MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, new MongoMappingContext());
    MongoTypeMapper typeMapper = new DefaultMongoTypeMapper(null);
    converter.setTypeMapper(typeMapper);
    converter.afterPropertiesSet();
    return converter;
}

到此关于Spring Boot中MongoDB的使用就基本讲完了,总体来说,Spring Boot在很大程度上方便了我们的开发,借助它我们能很快完成一些轻量级的服务端开发工作。