在這個博客的製做中,決定使用mongodb來對文章和圖片進行存儲,若是純粹使用mongodb的api來進行crud操做的話,很是麻煩,html
因此在這裏採用Morphia,mongodb的一個orm框架,十分好用,具體dependcy以下:java
<!--morphia--> <dependency> <groupId>org.mongodb</groupId> <artifactId>mongo-java-driver</artifactId> <version>${mongodb.version}</version> </dependency> <dependency> <groupId>org.mongodb.morphia</groupId> <artifactId>morphia</artifactId> <version>${morphia.version}</version> </dependency>在整合Morphia以前,我還參考了一下別人的博文的編寫,其中採用許多那篇博文的代碼:
具體分爲以下:spring
MongoFactoryBean:mongodb
package cn.com.morphia; import com.mongodb.*; import org.springframework.beans.factory.config.AbstractFactoryBean; import java.util.ArrayList; import java.util.List; /** * Created by Administrator on 2016/1/17. */ public class MongoFactoryBean extends AbstractFactoryBean<MongoClient> { /** * 表示服務器列表 */ private String[] serverStrings; /** * mongo配置對象 */ private MongoOptions mongoOptions; /** * 是否主從分離,默認爲false */ private boolean readSecondary = false; public String[] getServerStrings() { return serverStrings; } public void setServerStrings(String[] serverStrings) { this.serverStrings = serverStrings; } public MongoOptions getMongoOptions() { return mongoOptions; } public void setMongoOptions(MongoOptions mongoOptions) { this.mongoOptions = mongoOptions; } public WriteConcern getWriteConcern() { return writeConcern; } public void setWriteConcern(WriteConcern writeConcern) { this.writeConcern = writeConcern; } public boolean isReadSecondary() { return readSecondary; } public void setReadSecondary(boolean readSecondary) { this.readSecondary = readSecondary; } /** * 設定寫策略,默認採用SAFE模式(須要拋異常) */ private WriteConcern writeConcern = WriteConcern.SAFE; @Override public Class<?> getObjectType() { return MongoClient.class; } @Override protected MongoClient createInstance() throws Exception { MongoClient mongo = initMongo(); //設定主從分離 if (readSecondary) { mongo.setReadPreference(ReadPreference.secondaryPreferred()); } //設定寫策略 mongo.setWriteConcern(writeConcern); return mongo; } /** * 初始化mongo * @return * @throws Exception */ private MongoClient initMongo() throws Exception { //根據條件建立mongo實例 MongoClient mongo = null; List<ServerAddress> serverList = getServerList(); mongo = new MongoClient(serverList.get(0)); return mongo; } /** * 獲取mongo地址 * @return */ private List<ServerAddress> getServerList() throws Exception { List<ServerAddress> serverList = new ArrayList<>(); try { for (String serverString: serverStrings) { String[] temp = serverString.split(":"); String host = temp[0]; if (temp.length > 2) { throw new IllegalArgumentException( "Invalid server address string:" + serverString ); } if (temp.length == 2) { serverList.add(new ServerAddress(host, Integer.parseInt(temp[1]))); } else { serverList.add(new ServerAddress(host)); } } return serverList; } catch (Exception e) { e.printStackTrace(); throw new Exception( "Error while converting serverString to ServerAddressList", e ); } } }原博文中採用的泛型是mongo,可是如今的api基本不支持這麼作了,因此我統一換成了MongoClient。
MorphiaFactory:數據庫
package cn.com.morphia; import org.mongodb.morphia.Morphia; import org.springframework.beans.factory.config.AbstractFactoryBean; /** * Created by Administrator on 2016/1/17. */ public class MorphiaFactoryBean extends AbstractFactoryBean<Morphia> { /** * 要掃描的包 * @return */ private String[] mapPackages; /** * 要映射的類 */ private String[] mapClasses; /** * 掃描包時,是否忽略不映射的類 * 這裏按照Morphia的原始定義,默認設爲false */ private boolean ignoreInvalidClasses; public String[] getMapPackages() { return mapPackages; } public void setMapPackages(String[] mapPackages) { this.mapPackages = mapPackages; } public String[] getMapClasses() { return mapClasses; } public void setMapClasses(String[] mapClasses) { this.mapClasses = mapClasses; } public boolean isIgnoreInvalidClasses() { return ignoreInvalidClasses; } public void setIgnoreInvalidClasses(boolean ignoreInvalidClasses) { this.ignoreInvalidClasses = ignoreInvalidClasses; } @Override public Class<?> getObjectType() { return Morphia.class; } @Override protected Morphia createInstance() throws Exception { Morphia morphia = new Morphia(); if (mapPackages != null) { for (String packageName: mapPackages) { morphia.mapPackage(packageName, ignoreInvalidClasses); } } if (mapClasses != null) { for (String entityClass: mapClasses) { morphia.map(Class.forName(entityClass)); } } return morphia; } }DatastoreFactoryBean:
package cn.com.morphia; import com.mongodb.Mongo; import com.mongodb.MongoClient; import org.mongodb.morphia.Datastore; import org.mongodb.morphia.Morphia; import org.springframework.beans.factory.config.AbstractFactoryBean; /** * Created by Administrator on 2016/1/17. */ public class DatastoreFactoryBean extends AbstractFactoryBean<Datastore> { /** * morphia實例,最好是單例 */ private Morphia morphia; /** * mongo實例,最好是單例 */ private MongoClient mongo; /** * 數據庫名 */ private String dbName; /** * 用戶名,可爲空 */ private String username; /** * 密碼,可爲空 */ private String password; public Morphia getMorphia() { return morphia; } public void setMorphia(Morphia morphia) { this.morphia = morphia; } public MongoClient getMongo() { return mongo; } public void setMongo(MongoClient mongo) { this.mongo = mongo; } public String getDbName() { return dbName; } public void setDbName(String dbName) { this.dbName = dbName; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public boolean isToEnsureIndexes() { return toEnsureIndexes; } public void setToEnsureIndexes(boolean toEnsureIndexes) { this.toEnsureIndexes = toEnsureIndexes; } public boolean isToEnsureCaps() { return isToEnsureCaps; } public void setIsToEnsureCaps(boolean isToEnsureCaps) { this.isToEnsureCaps = isToEnsureCaps; } /** * 是否確認索引存在,默認false */ private boolean toEnsureIndexes = false; /** * 是否確認caps存在,默認爲false */ private boolean isToEnsureCaps = false; @Override public Class<?> getObjectType() { return Datastore.class; } @Override protected Datastore createInstance() throws Exception { //這裏的username和password能夠爲null,morphia對象會去處理 Datastore ds = morphia.createDatastore(mongo, dbName); if (toEnsureIndexes) { ds.ensureIndexes(); } if (isToEnsureCaps) { ds.ensureCaps(); } return ds; } }具體代碼大概就是如上,可是還有spring中配置文件的配置尚未編寫,具體以下:
<!-- mongoDB的配置對象 --> <bean id="mongoOptions" class="com.mongodb.MongoOptions"> <property name="connectionsPerHost" value="10" /> <!-- 鏈接超時時間(毫秒),默認爲10000 --> <property name="connectTimeout" value="10000" /> <!-- 是否建立一個finalize方法,以便在客戶端沒有關閉DBCursor的實例時,清理掉它。默認爲true --> <property name="cursorFinalizerEnabled" value="true" /> <!-- 線程等待鏈接可用的最大時間(毫秒),默認爲120000 --> <property name="maxWaitTime" value="120000" /> <!-- 可等待線程倍數,默認爲5.例如connectionsPerHost最大容許10個鏈接,則10*5=50個線程能夠等待,更多的線程將直接拋異常 --> <property name="threadsAllowedToBlockForConnectionMultiplier" value="5" /> <!-- socket讀寫時超時時間(毫秒),默認爲0,不超時 --> <property name="socketTimeout" value="0" /> <!-- 是socket鏈接在防火牆上保持活動的特性,默認爲false --> <property name="socketKeepAlive" value="false" /> <!-- 對應全局的WriteConcern.SAFE,默認爲false --> <property name="safe" value="true" /> <!-- 對應全局的WriteConcern中的w,默認爲0 --> <property name="w" value="0" /> <!-- 對應全局的WriteConcern中的wtimeout,默認爲0 --> <property name="wtimeout" value="0" /> <!-- 對應全局的WriteConcern.FSYNC_SAFE,若是爲真,每次寫入要等待寫入磁盤,默認爲false --> <property name="fsync" value="false" /> <!-- 對應全局的WriteConcern.JOURNAL_SAFE,若是爲真,每次寫入要等待日誌文件寫入磁盤,默認爲false --> <property name="j" value="false" /> </bean> <!-- 使用工廠建立mongo實例 --> <bean id="mongo" class="cn.com.morphia.MongoFactoryBean"> <!-- mongoDB的配置對象 --> <property name="mongoOptions" ref="mongoOptions"/> <!-- 是否主從分離(讀取從庫),默認爲false,讀寫都在主庫 --> <property name="readSecondary" value="false"/> <!-- 設定寫策略,默認爲WriteConcern.SAFE,優先級高於mongoOptions中的safe --> <property name="writeConcern" value="SAFE"/> <!-- 設定服務器列表,默認爲localhost:27017 --> <property name="serverStrings"> <array> <value>localhost:27017</value> </array> </property> </bean> <!-- 使用工廠建立morphia實例,同時完成類映射操做 --> <bean id="morphia" class="cn.com.morphia.MorphiaFactoryBean" > <!-- 指定要掃描的POJO包路徑 --> <property name="mapPackages"> <array> <value>cn.com.domain</value> </array> </property> </bean> <!-- 使用工廠建立datastore,同時完成index和caps的確認操做 --> <bean id="datastore" class="cn.com.morphia.DatastoreFactoryBean" > <property name="morphia" ref="morphia"/> <property name="mongo" ref="mongo"/> <!-- collection的名稱 --> <property name="dbName" value="files"/> <!-- 用戶名和密碼能夠爲空 --> <!-- <property name="username" value="my_username"/> 93 <property name="password" value="my_password"/> --> <!-- 是否進行index和caps的確認操做,默認爲flase --> <property name="toEnsureIndexes" value="true"/> <property name="isToEnsureCaps" value="true"/> </bean>這裏我沒有再寫另一個mongodb.properties配置文件,直接將相應的參數寫到了spring的配置文件中,由於這裏只須要這幾個參數,能夠說不須要
另外再寫一個配置文件配置相應的參數。api
同時在datastore這個bean的編寫中,我直接讓這個bean掃描domain下面的全部pojo類,這樣便不須要再進行相應的一個個的將相應的pojo類添加進來。服務器
同時在mongooptions的配置中,我去掉了幾個參數,在新版本中,不須要這幾個參數。app
如今進行測試:框架
package morphia; import cn.com.domain.User; import org.junit.Before; import org.junit.Test; import org.mongodb.morphia.Datastore; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * Created by Administrator on 2016/1/19. */ public class TestMorphia { public ApplicationContext context; @Before public void init(){ context = new ClassPathXmlApplicationContext("classpath:spring/applicationContext.xml"); } @Test public void test() { Datastore datastore = (Datastore) context.getBean("datastore"); User u = new User(); u.setUsername("xx"); u.setPassword("xx"); datastore.save(u); System.out.println(datastore); } }得到datastore後,進行insert操做。
執行成功後,進mongo中查詢相應的表:dom
如此,spring與Morphia的整合即是成功的。