Spring Boot 1.5.8整合Dubbo

废话不多说,今天说说Spring Boot和Dubbo的整合,注册服务中心用的是Zookeeper,至于Dubbo、Zookeeper为何物我在此不再多言,不知道是什么自己去百度,本文适用于对微服务或者RPC了解的人准备的!
先介绍一下整合过程中用到的主要软件的版本:

Spring Boot: 1.5.8.RELEASE
Dubbo: dubbo-spring-boot-starter 0.1.1
Zookeeper: 3.4.10
dubbo-admin:2.5.4

其中dubbo-admin使用的是老版本的,新版本的大家可以到github上去搜索,这里给出这个版本的下载地址,我不保证任何时候都可以使用
dubbo-admin-2.5.4
Dubbo使用的是alibaba官方提供的starter :

<dependency>
    <groupId>com.alibaba.boot</groupId>
    <artifactId>dubbo-spring-boot-starter</artifactId>
    <version>0.1.1</version>
</dependency>

如果您的工程遇到了依赖问题, 请尝试添加如下 Maven 参考到工程的 pom.xml 文件中:

<repositories>
    <repository>
        <id>sonatype-nexus-snapshots</id>
        <url>https://oss.sonatype.org/content/repositories/snapshots</url>
        <releases>
            <enabled>false</enabled>
        </releases>
        <snapshots>
            <enabled>true</enabled>
        </snapshots>
    </repository>
</repositories>

从现在开始, dubbo-spring-boot-project 将在每个发布中发行两个版本 :

  • 0.2.x 是支持 Spring Boot 2.x 的主要版本(推荐,长期维护)
  • 0.1.x 是支持 Spring Boot 1.x 的维护版本(兼容,短期维护)
版本    Java    Spring Boot    Dubbo
0.2.0    1.8+    2.0.x    2.6.2+
0.1.1    1.7+    1.5.x    2.6.2+

以上牵涉到需要安装的软件,需要大家自行准备,本文的重点不在于此!友情提示,使用上面版本的dubbo-admin是个war包可以之前部署在Tomcat中,注意其中配置文件中的Zookeeper的地址,请修改成自己可用的Zookeeper地址!

我之前写过一个基于Spring Boot和Spring Cloud的BT搜索项目,我主要是想用这个项目练手Spring Cloud,其中用了Zuul、Fegin、Ribbon、Spring Config、Hystrix、Eureka等组件。下面开始正式的编码,Spring Boot和Dubbo的整合。其中问题有很多,浪费了我国庆假期中的一天,其实最后发现问题解决很简单。

由服务提供方为服务消费方暴露接口

package net.ydstudio.dubbo.search.api.service;

import net.ydstudio.dubbo.search.api.document.BtSearchDocument;
import net.ydstudio.dubbo.search.api.model.EsSearchHotResult;

import java.io.IOException;

/**
 * Created by Sam on 18/7/7.
 */
public interface BtSearchService {

    /**
     *  创建索引
     * @return
     * @throws IOException
     */
    Boolean createIndex() throws IOException;
    /**
     * 通过word查询 文档
     * @param word
     * @return
     * @throws IOException
     */
    BtSearchDocument findOne(String word) throws IOException;
    /**
     * 根据id删除文档
     * @param word
     * @throws IOException
     * @return
     */
    Boolean delete(String word) throws IOException;

    /**
     * 保存 document
     * @param word
     * @throws IOException
     * @return true or false
     */
    Boolean save(String word) throws IOException;
    /**
     * 删除索引
     * @return
     * @throws IOException
     */
    Boolean deleteIndex() throws IOException;

    /**
     * 热搜词
     * @return 
     */
    EsSearchHotResult hotWordList();
}

服务提供方

pom.xml中的依赖
    <dependencies>
        <dependency>
            <groupId>net.ydstudio.dubbo</groupId>
            <artifactId>search-api</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.alibaba.boot</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>0.1.1</version>
        </dependency>

    </dependencies>
</project>
实现暴露的接口
package net.ydstudio.dubbo.search.service;

import com.alibaba.dubbo.config.annotation.Service;
import io.searchbox.client.JestClient;
import io.searchbox.client.JestResult;
import io.searchbox.core.Search;
import net.ydstudio.dubbo.search.api.document.BtSearchDocument;
import net.ydstudio.dubbo.search.api.model.EsSearchHotResult;
import net.ydstudio.dubbo.search.api.service.BtSearchService;
import net.ydstudio.dubbo.search.util.Md5Util;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * Created by Sam on 18/7/7.
 */
@Service
public class BtSearchServiceImpl implements BtSearchService,EsSearchService<BtSearchDocument> {

    /**
     * 索引
     */
    public static final String INDEX_NAME = "search";

    /**
     * 索引类型
     */
    public static final String TYPE = "searchWord";


    @Value("classpath:mapping/searchMapping.json")
    private Resource mappingFile;

    @Autowired
    private JestClient jestClient;

    @Override
    public Boolean createIndex() throws IOException {

        return createESIndex(jestClient, mappingFile, INDEX_NAME, TYPE);
    }

    @Override
    public BtSearchDocument findOne(String word) throws IOException {

        String id  = Md5Util.md5(word);
        return findDocument(jestClient, INDEX_NAME, TYPE, id, BtSearchDocument.class);
    }

    @Override
    public Boolean delete(String word) throws IOException {

        String id  = Md5Util.md5(word);
        return deleteDocument(jestClient, INDEX_NAME, TYPE, id);
    }

    @Override
    public Boolean save(String word) throws IOException {

        String id  = Md5Util.md5(word);
        BtSearchDocument document = this.findOne(id);

        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = new Date();

        if (StringUtils.isEmpty(document)){
            document = new BtSearchDocument();
            document.setId(id);
            document.setCreated(format.format(date));
            document.setNum(1);
            document.setWord(word);

        }else {
            document.setNum(document.getNum()+1);
        }

        document.setUpdated(format.format(date));

        return saveDocument(jestClient, INDEX_NAME, TYPE, id, document);
    }


    @Override
    public Boolean deleteIndex() throws IOException {
        return deleteESIndex(jestClient, INDEX_NAME);
    }

    @Override
    public EsSearchHotResult hotWordList() {
 
        //    match_all
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        QueryBuilder queryBuilder = QueryBuilders.matchAllQuery();
        boolQuery.must(queryBuilder);

        FieldSortBuilder sortBuilder = SortBuilders.fieldSort("num");
        sortBuilder.order(SortOrder.DESC);
        searchSourceBuilder.query(boolQuery);

        searchSourceBuilder.sort(sortBuilder);

        // 构建Search对象
        Search search = new Search.Builder(searchSourceBuilder.toString())
                .addIndex(INDEX_NAME)
                .addType(TYPE)
                .build();

        EsSearchHotResult esSearchHotResult = new EsSearchHotResult();
        try {
            JestResult result = jestClient.execute(search);
            List<BtSearchDocument> list = result.getSourceAsObjectList(BtSearchDocument.class);


            esSearchHotResult.setTook(result.getValue("took").toString());
            esSearchHotResult.setDocumentList(list);


        } catch (IOException e) {
            e.printStackTrace();
        }
        return esSearchHotResult;
    }
}

search服务提供方的application的配置信息:

dubbo:
  application:
    id: search-provider
    name: search-provider
  protocosl:
    id: dubbo
    name: dubbo
    port: 20880
  scan:
    basePackages: net.ydstudio.dubbo.search.service
  registry:
    id: my-registry
    address: zookeeper://xx.xx.xxx.xxx:xxx
    parameters:
      max-active: 8
      max-wait: -1
      max-idle: 8
      min-idle: 0

注意 basePackages项配置的包路径,他对应的是设置扫描路径即被注解@service和@Reference描述的接口(或者说是暴露接口的实现类的包路径,这个很重要,我在此处耽搁了很久),这个配置可以使用 @EnableDubbo 注解替代(加在启动类上)

服务消费方

pom.xml中的依赖
<dependencies>
        <dependency>
            <groupId>net.ydstudio.dubbo</groupId>
            <artifactId>bt-model</artifactId>
        </dependency>
        <dependency>
            <groupId>net.ydstudio.dubbo</groupId>
            <artifactId>search-api</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.alibaba.boot</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>0.1.1</version>
        </dependency>
        <!--thymeleaf-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>net.sourceforge.nekohtml</groupId>
            <artifactId>nekohtml</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator</artifactId>
            <type>pom</type>
        </dependency>
    </dependencies>
配置文件
dubbo:
  application:
    id: bt-search
    name: bt-search
  protocosl:
    id: dubbo
    name: dubbo
    port: 20880
  scan:
    basePackages: net.ydstudio.dubbo.bt
  registry:
    id: my-registry
    address: zookeeper://xx.xx.xxx.xxx:xxx
    parameters:
      max-active: 8
      max-wait: -1
      max-idle: 8
      min-idle: 0

注意 basePackages 设置扫描路径,扫描被注解@service和@Reference的接口

RPC调用
@Reference
private BtSearchService  btSearchService;

使用com.alibaba.dubbo.config.annotation.Reference中的 @Reference注解修饰接口BtSearchService ,然后像普通的bean使用即可。

整合总结

由于软件更新的快,或者软件项目的生存周期太短,软件对应的说明文档会跟不上。Dubbo现在已经捐献给了Apache,这一方面可能会好一点。大家在开发的时候注意细心一点,多去看看GitHub,不然问题会很多!

附注参考资料
【官方Dubbo和Spring Boot整合的GitHub地址】

相关文章

此处评论已关闭