1.Mongo和MongoClient的关系
MongoClient继承自Mongo,使用Mongo也可建立连接,但是需要使用与Mongo适应的MongoOptions,MongoURI等类型。
2.建立连接
在MongoDB Java Driver API中,要操作MongoDB的第一步和使用其他DB Java Driver类似,都需要首先和数据库建立连接。在MongoDBJava Driver API中,建立连接的类为com.mongodb.MongoClient.在讨论连接字符串等内容之前,我们来看看它最简单的使用方式:
MongoClient client = new MongoClient();
一个构造函数不带任何参数的版本。使用这个构造函数连接到的是本地的MongoDB服务,即/127.0.0.1:27017,当然你如果改变了MongoDB服务的端口,那么这里显示的端口就是你的端口了。
可以通过以下单元测试代码进行验证:
@Test public void testConstruactors() throws UnknownHostException { MongoClient client; client = new MongoClient(); //也可指定连接的Host: //client = new MongoClient("127.0.0.1"); assertEquals(new ServerAddress(), client.getAddress()); client.close(); }
MongoClientOptions customClientOptions = new MongoClientOptions.Builder().connectionsPerHost(100).build();
分析上面的代码,MongoClientOptions.Builder()得到的是一个MongoClientOptions的Builder,通过该Builder可以设置各种Options,例如connectionsPerHost(100),设置连接池中最大连接个数,需要注意的是,每个属性的设置方法的返回类型是一个Builder,这意味着可以采用类似下面的链式调用
MongoClientOptions customClientOptions = new MongoClientOptions.Builder().connectionsPerHost(100).threadsAllowedToBlockForConnectionMultiplier(200).build();
MongoClientOptions customClientOptions = new MongoClientOptions.Builder().connectionsPerHost(50).maxWaitTime(2000).build(); MongoOptions options = new MongoOptions(customClientOptions); client = new MongoClient("127.0.0.1", customClientOptions); // 每个MongoClient实例维护一个连接池 assertEquals(new ServerAddress("127.0.0.1"), client.getAddress()); assertEquals(options, client.getMongoOptions()); client.close();
MongoOptions options=new MongoOptions(customClientOptions):这行代码并不影响MongoClientOptions的使用,只是展示如何获取到设置的MongoClientOptions。
此外,也可直接通过MongoClient.getMongoOptions()获取到MongoOptions后,进行设置,而不使用MongoClientOptions,如下
MongoOptions mps = mongoClient.getMongoOptions();
mps.setConnectionsPerHost(mongoDBConfig.getPoolSize());
mps.setConnectTimeout(mongoDBConfig.getConnectTimeout());
mps.setMaxWaitTime(mongoDBConfig.getMaxWaitTime());
通过两种方式的对比,我更喜欢MongoClientOptions,代码更加优雅。另外,即使没有设置MongoClientOptions,MongoClient也会有默认的设置。
最简单的连接字符串就是:mongodb://127.0.0.1
当然,在真正在项目开发中,没人会这么用!!!!!!~~~回到主题,在MongoClient中,如何使用连接字符串进行连接呢?MongoDB Java Driver提供了一个 com.mongodb.MongoClientURI类型,使用方式如下:
client = new MongoClient(new MongoClientURI("mongodb://kwiner:test123@127.0.0.1/test?authMechanism=MONGODB-CR&maxPoolSize=500")); client.close();
5.安全连接方式
MongoClient也提供了用户名和密码连接到指定数据库的方式,需要用到com.mongodb.MongoCredential,该类在mongo-java-driver的2.11.0版本中才开始提供,请注意!
MongoClientOptions clientOptions=new MongoClientOptions.Builder().connectionsPerHost(poolSize).threadsAllowedToBlockForConnectionMultiplier(200).build(); List<MongoCredential> lstCredentials = Arrays.asList(MongoCredential.createMongoCRCredential("admin", "myinfo", "123456".toCharArray())); client = new MongoClient(new ServerAddress("127.0.0.1"),lstCredentials, clientOptions); client.close(); 或者 MongoClientOptions mongoOptions=new MongoClientOptions.Builder().connectionsPerHost(poolSize).threadsAllowedToBlockForConnectionMultiplier(200).build(); MongoClient mongoClient = new MongoClient(new ServerAddress(server, port), mongoOptions); // 每个MongoClient实例维护一个连接池
try { db = mongoClient.getDatabase(database); collection = db.getCollection(table); catch (Exception e) { mongoClient.close(); throw e; }
MongoClientOptions.Builder builder = new MongoClientOptions.Builder(); MongoClientOptions options = builder.build(); assertEquals(100, options.getConnectionsPerHost());//最大连接数 assertEquals(0, options.getMinConnectionsPerHost());//最小连接数 assertEquals(0, options.getMaxConnectionIdleTime());//连接的最大闲置时间 assertEquals(0, options.getMaxConnectionLifeTime());//连接的最大生存时间 assertEquals(120000, options.getMaxWaitTime());//最大等待可用连接的时间 assertEquals(10000, options.getConnectTimeout());//连接超时时间 MongoClient client = new MongoClient("127.0.0.1", customClientOptions); client.close();
7.连接副本集
使用MongoDB作为数据库,基本上都会使用副本集,在这个集里面,有primary节点,又有其他secondary节点,并使用了读写分离,这个时候,使用java连接MongoDB服务应该怎么做呢? 其实很简单,就是使用一个ServerAddress集合保存副本集中的所有节点,然后作为MongoClient的构造函数的参数,并使用ReadPreference设置读写策略,注意,ReadPreference的读写策略既可以在MongoClient上设置,作用与使用MongoClient连接的所有操作,也可以设置到每次具体的集合操作上,作用域该次操作。代码如下:
在MongoClient上设置读写策略:
List<ServerAddress> addresses = new ArrayList<ServerAddress>(); ServerAddress address1 = new ServerAddress("192.168.1.136" , 27017); ServerAddress address2 = new ServerAddress("192.168.1.137" , 27017); ServerAddress address3 = new ServerAddress("192.168.1.138" , 27017); addresses.add(address1); addresses.add(address2); addresses.add(address3); mongoClient = new MongoClient(lstAddrs); mongoClient.setReadPreference(ReadPreference.primary());
在某次操作上设置读写策略:
List<ServerAddress> addresses = new ArrayList<ServerAddress>(); ServerAddress address1 = new ServerAddress("192.168.1.136" , 27017); ServerAddress address2 = new ServerAddress("192.168.1.137" , 27017); ServerAddress address3 = new ServerAddress("192.168.1.138" , 27017); addresses.add(address1); addresses.add(address2); addresses.add(address3); MongoClient client = new MongoClient(addresses); DB db = client.getDB( "test" ); DBCollection coll = db.getCollection( "test" ); BasicDBObject object = new BasicDBObject(); object.append( "test2" , "testval2" ); //读操作从副本节点读取 ReadPreference preference = ReadPreference.secondary(); DBObject dbObject = coll.findOne(object, null , preference); System.out.println(dbObject);
8.mongo连接池属性设置
Mongo的实例其实就是一个数据库连接池,这个连接池里默认有10个链接。我们没有必要重新实现这个链接池,但是我们可以更改这个连接池的配置。因为Mongo的实例就是一个连接池,所以,项目中最好只存在一个Mongo的实例。
常见的配置参数:
connectionsPerHost:每个主机的连接数
threadsAllowedToBlockForConnectionMultiplier:线程队列数,它以上面connectionsPerHost值相乘的结果就是线程队列最大值。如果连接线程排满了队列就会抛出“Out of semaphores to get db”错误。
maxWaitTime:最大等待连接的线程阻塞时间
connectTimeout:连接超时的毫秒。0是默认和无限
socketTimeout:socket超时。0是默认和无限
autoConnectRetry:这个控制是否在一个连接时,系统会自动重试
还有许多配置,可以参见mongodb的API。