废话不多说,今天说说Spring Boot和Dubbo的整合,注册服务中心用的是Zookeeper,至于Dubbo、Zookeeper为何物我在此不再多言,不知道是什么自己去百度,本文适用于对微服务或者RPC了解的人准备的!
先介绍一下整合过程中用到的主要软件的版本:
1 2 3 4 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 :
1 2 3 4 5 <dependency > <groupId > com.alibaba.boot</groupId > <artifactId > dubbo-spring-boot-starter</artifactId > <version > 0.1.1</version > </dependency >
如果您的工程遇到了依赖问题, 请尝试添加如下 Maven 参考到工程的 pom.xml 文件中:
1 2 3 4 5 6 7 8 9 10 11 12 <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 的维护版本(兼容,短期维护)1 2 3 版本 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的整合。其中问题有很多,浪费了我国庆假期中的一天,其实最后发现问题解决很简单。
####由服务提供方为服务消费方暴露接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 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;public interface BtSearchService { Boolean createIndex () throws IOException ; BtSearchDocument findOne (String word) throws IOException ; Boolean delete (String word) throws IOException ; Boolean save (String word) throws IOException ; Boolean deleteIndex () throws IOException ; EsSearchHotResult hotWordList () ; }
####服务提供方
pom.xml中的依赖 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <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 >
实现暴露的接口 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 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;@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 () { 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 = 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的配置信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 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中的依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 <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 > <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 >
配置文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 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调用 1 2 @Reference private BtSearchService btSearchService;
使用com.alibaba.dubbo.config.annotation.Reference中的 @Reference注解修饰接口BtSearchService ,然后像普通的bean使用即可。
整合总结 由于软件更新的快,或者软件项目的生存周期太短,软件对应的说明文档会跟不上。Dubbo现在已经捐献给了Apache,这一方面可能会好一点。大家在开发的时候注意细心一点,多去看看GitHub,不然问题会很多!
附注参考资料 【官方Dubbo和Spring Boot整合的GitHub地址】