最近由于项目开发需要,需要抽取一层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