Springboot移除自动配置Mongodb

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

posted @ 2019-01-07 16:14  yingkamen  阅读(16868)  评论(0编辑  收藏  举报