最近由於項目開發需要,需要抽取一層MongoBaseDao:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.util.List; public abstract class MongoBaseDao<T> { private static final String ID_FIELD = "_id"; private static final String DELETE_FIELD = "deleted"; @Autowired @Qualifier("mongoTemplate") protected MongoTemplate mongoTemplate; //保存一個對象到mongodb public void save(T bean) { mongoTemplate.save(bean); } // 根據id刪除對象 public void deleteById(T t) { mongoTemplate.remove(t); } // 通過條件查詢更新數據 public void update(Query query, Update update) { mongoTemplate.updateMulti(query, update, this.getEntityClass()); } // 根據id進行更新 public void updateById(String id, T t) { Query query = new Query(); query.addCriteria(Criteria.where(ID_FIELD).is(id)); Update update = buildBaseUpdate(t); update(query, update); } // 查詢集合 public List<T> findAll() { Query query = Query.query(Criteria.where(DELETE_FIELD).is(false)); return mongoTemplate.find(query, this.getEntityClass()); } // 通過id查詢一個實體 public T findById(String id) { Query query = Query.query(Criteria.where(ID_FIELD).is(id).and(DELETE_FIELD).is(false)); return mongoTemplate.findOne(query, this.getEntityClass()); } private Update buildBaseUpdate(T t) { Update update = new Update(); Field[] fields = t.getClass().getDeclaredFields(); for (Field field : fields) { field.setAccessible(true); try { Object value = field.get(t); if (value != null) { update.set(field.getName(), value); } } catch (Exception e) { e.printStackTrace(); } } return update; } // 獲取需要操作的實體類class protected Class<T> getEntityClass() { return ((Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]); } public MongoTemplate getMongoTemplate() { return mongoTemplate; } }
由於是通用的代碼,所以想放至common包中供其他服務依賴使用,此時出現了問題。部分服務依賴於common包中的部分內容,但並不需要連接mongo,此時這些項目啟動時會報錯:
01-07 15:21:15.657 INFO -- [cluster-ClusterId{value='5c32fdebe4e45a2cdae06391', description='null'}-localhost:27017] org.mongodb.driver.cluster:76:[] [] Exception in monitor thread while connecting to server localhost:27017 com.mongodb.MongoSocketOpenException: Exception opening socket at com.mongodb.connection.SocketStream.open(SocketStream.java:63) at com.mongodb.connection.InternalStreamConnection.open(InternalStreamConnection.java:115) at com.mongodb.connection.DefaultServerMonitor$ServerMonitorRunnable.run(DefaultServerMonitor.java:113) at java.lang.Thread.run(Thread.java:748) Caused by: java.net.ConnectException: Connection refused (Connection refused) at java.net.PlainSocketImpl.socketConnect(Native Method) at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350) at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188) at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) at java.net.Socket.connect(Socket.java:589) at com.mongodb.connection.SocketStreamHelper.initialize(SocketStreamHelper.java:57) at com.mongodb.connection.SocketStream.open(SocketStream.java:58) ... 3 common frames omitted
查了相關資料發現如果在springboot項目中存在spring-boot-starter-data-mongodb的依賴,springboot會在項目啟動時自動實例化一個mongo實例,因此需要在項目啟動時禁用mongo的自動配置。
看了網上說在Springboot啟動類上增加 @SpringBootApplication(exclude = MongoAutoConfiguration.class) 配置,但是我試了之后發現仍然報錯:
01-07 15:52:49.717 ERROR -- [main] o.s.b.d.LoggingFailureAnalysisReporter:42:[] [] *************************** APPLICATION FAILED TO START *************************** Description: Parameter 0 of method mongoDbFactory in org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration required a bean of type 'com.mongodb.MongoClient' that could not be found. - Bean method 'mongo' not loaded because auto-configuration 'MongoAutoConfiguration' was excluded Action: Consider revisiting the conditions above or defining a bean of type 'com.mongodb.MongoClient' in your configuration.
繼續查資料發現配置中還需要加入MongoDataAutoConfiguration.class才行,最終配置如:@SpringBootApplication(exclude = {MongoAutoConfiguration.class, MongoDataAutoConfiguration.class} ) ,項目可以正常啟動。
如果單獨只配置 @SpringBootApplication(exclude = MongoDataAutoConfiguration.class),仍然會出現最開始的報錯情況。
針對我的項目情況,還想到有另外一種方案可供實現:可以在common包中單獨抽取出common-mongo模塊供其他需要連接mongo的服務依賴。
參考資料:
通用MongoDao:https://www.cnblogs.com/meisha/articles/3630036.html
Mongo自動配置:https://blog.csdn.net/xuyw10000/article/details/72918360