赞
踩
docker pull redis:latest
docker run -itd --name redis-test -p 6379:6379 redis
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- commons-pool2 对象池依赖 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
不需要写版本,springboot父依赖定好了。
# Spring
spring:
redis:
database: 1 # 选择哪个库,默认0库
host: 127.0.0.1
port: 6379
timeout: 30000
password:
lettuce:
pool:
max-active: 1024
max-wait: 10000ms
max-idle: 200
min-idle: 5
import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.CachingConfigurerSupport; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.cache.RedisCacheConfiguration; import org.springframework.data.redis.cache.RedisCacheManager; import org.springframework.data.redis.cache.RedisCacheWriter; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; import java.text.SimpleDateFormat; import java.time.Duration; @Configuration @EnableCaching public class RedisConfig extends CachingConfigurerSupport { //缓存管理器 @Bean public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) { RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofHours(1)); // 设置缓存有效期一小时 return RedisCacheManager .builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory)) .cacheDefaults(redisCacheConfiguration).build(); } @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory){ RedisTemplate<String, Object> template = new RedisTemplate(); template.setConnectionFactory(factory); template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); template.setHashKeySerializer(new StringRedisSerializer()); template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); return template; } }
第一个bean:配置redis缓存
第二个beasn:配置redis序列化,可以将对象存到redis里,在图形化界面看来是一个json串形式;如果你不存对象,redis自带StringRedisTemplate template
,满足字符串操作。
@EnableCaching
缓存是为了优化查询速度,主要体现在查询上
**查询:@Cacheable **
代码:
@Autowired private ElasticsearchRestTemplate elasticsearchRestTemplate; @Cacheable(value = "goodsPage",key="#searchKey+'-'+#pageNum+''+#pageSize") public List<Goods> pageSearch(String searchKey,Integer pageNum,Integer pageSize){ NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder(); NativeSearchQuery query = nativeSearchQueryBuilder /** * 第一个参数:关键词 * 第二个参数:对应es的字段 */ .withQuery(QueryBuilders.multiMatchQuery(searchKey, "goodsName")) /** * 第一个参数:当前页,0开始 * 第二个参数:每个条数 * 第三个参数:排序对象 * 升序/降序 * 比较字段 */ // .withPageable(PageRequest.of(0,5,Sort.Direction.DESC,"goodsId","marketPrice")) // 分页 .withPageable(PageRequest.of(pageNum-1, pageSize)) // .withSort(SortBuilders.fieldSort("marketPrice").order(SortOrder.ASC)) //高亮,默认样式<em></em>(斜体) // .withHighlightFields(new HighlightBuilder.Field("goodsName")) //高亮,指定样式 .withHighlightBuilder(new HighlightBuilder().field("goodsName").preTags("<span style='color:red;'>").postTags(" </span>")) .build(); //返回结果 List<Goods> result=new ArrayList<>(); SearchHits<Goods> search = elasticsearchRestTemplate.search(query, Goods.class); for (SearchHit<Goods> searchHit : search) { Goods goods=null; String highlightMessage = searchHit.getHighlightField("goodsName").get(0); System.out.println("高亮-----------"); System.out.println(highlightMessage); //结果对象 goods=searchHit.getContent(); goods.setGoogsNameH1(highlightMessage); goods.setGoodsNum((int) search.getTotalHits()); System.out.println("数据:"+goods.getGoodsNum()); result.add(goods); } return result; }
- 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
3.访问接口
数据:
缓存数据:
结合注解和查询参数:
@Cacheable(value = "goodsPage",key="#searchKey+'-'+#pageNum+''+#pageSize")
value:作为redis key的第一部分
key:作为redis key的第二部分
第一部分和第二部分以
::
连接,显示出类似于hash般的结构在注解里取值:
#变量名
或者对于对象#对象名.属性名
,多个值拼接在key里面的多个值之间加:+'分隔符'+
或者#arg1#arg2...
修改:@CachePut
应用到写数据的方法上,如新增/修改方法,调用方法时会自动把相应的数据放入缓存
@Override @Transactional @CachePut(value = "goodsCategory",key="#goodsCategory") public int saveCategory(GoodsCategory goodsCategory) { //GoodsCategory(id=null, name=手机 、 数码 、 通信123, mobileName=数码产品321, parentId=35, parentIdPath=null, level=3, sortOrder=12, isShow=1, image=, isHot=null, catGroup=1, commissionRate=12) //parentIdPath 赋值 String parentPath=goodsCategoryMapper.getParentIdPath(goodsCategory.getParentId()); Integer maxID = goodsCategoryMapper.getMaxID()+1; String parentIdPath=parentPath+"_"+maxID; goodsCategory.setParentIdPath(parentIdPath); return goodsCategoryMapper.insert(goodsCategory); }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
删除@CacheEvict
增/修改”方法上添加@CacheEvict(value=”goods”, key= “#变量名”)注解,当方法调用成功后,会删除缓存testValue上key值为testKey的缓存。
总结
数据操作严格分为两类:
修改:修改,添加,删除
@CachePut:更新缓存数据
@CacheEvict:删除缓存数据
这两个注解都可以用在增删改上,他们的区别是:
- @CachePut:更新缓存,效率高,但是其他系统对数据库数据修改,就会导致读脏数据
- @CacheEvict:删除缓存,数据一致性更强,但如果数据删除后,短时间大量数据请求这个数据,就会引发缓存击穿
查询:查询
@Cacheable :数据存缓存
只有注解的value值相同,key都是根据同一属性建立,注解才会操作同一份缓存里的数据:
@Cacheable(value = "goodsPage",key="#searchKey+'-'+#pageNum+''+#pageSize")
对查询结果缓存到数据库:格式为String
redis:
- key:注解的value值::注解的key值
- value:查询结果序列化
@CachePut(value = "goodsPage",key="#searchKey+'-'+#pageNum+''+#pageSize")
修改值,一般为sevice层对数据的更新操作,注意: 要与查询的value对应上,key的格式也需要相同
@Override @Cacheable(value = "goodsCategory", key="#pId") public List<GoodsCategory> selectCategoryParentId(Integer pId) { Map<String, Object> params = new HashMap<>(); params.put("parent_id", pId); List<GoodsCategory> goodsCategories = goodsCategoryMapper.selectByMap(params); return goodsCategories; } @Override @Transactional @CachePut(value = "goodsCategory",key="#goodsCategory.parentId") public int saveCategory(GoodsCategory goodsCategory) { //GoodsCategory(id=null, name=手机 、 数码 、 通信123, mobileName=数码产品321, parentId=35, parentIdPath=null, level=3, sortOrder=12, isShow=1, image=, isHot=null, catGroup=1, commissionRate=12) //parentIdPath 赋值 String parentPath=goodsCategoryMapper.getParentIdPath(goodsCategory.getParentId()); Integer maxID = goodsCategoryMapper.getMaxID()+1; String parentIdPath=parentPath+"_"+maxID; goodsCategory.setParentIdPath(parentIdPath); return goodsCategoryMapper.insert(goodsCategory); }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
@Cacheable和@CachePut注解的value值相同,并且key也是以parentId建立的,这个@CachePut才能发挥效果。
@CacheEvict(value = "goodsPage",key="#searchKey+'-'+#pageNum+''+#pageSize")
@Override @Cacheable(value = "goodsCategory", key="#pId") public List<GoodsCategory> selectCategoryParentId(Integer pId) { Map<String, Object> params = new HashMap<>(); params.put("parent_id", pId); List<GoodsCategory> goodsCategories = goodsCategoryMapper.selectByMap(params); return goodsCategories; } @Override @Transactional @CacheEvict(value = "goodsCategory",key="#goodsCategory.parentId") public int saveCategory(GoodsCategory goodsCategory) { //GoodsCategory(id=null, name=手机 、 数码 、 通信123, mobileName=数码产品321, parentId=35, parentIdPath=null, level=3, sortOrder=12, isShow=1, image=, isHot=null, catGroup=1, commissionRate=12) //parentIdPath 赋值 String parentPath=goodsCategoryMapper.getParentIdPath(goodsCategory.getParentId()); Integer maxID = goodsCategoryMapper.getMaxID()+1; String parentIdPath=parentPath+"_"+maxID; goodsCategory.setParentIdPath(parentIdPath); return goodsCategoryMapper.insert(goodsCategory); }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
@Cacheable和 @CacheEvict注解的value值相同,并且key也是以parentId建立的,这个@CachePut才能发挥效果。
1.虚拟机:192.168.10.100 ,192.168.10.101 ,192.168.10.102
2.下载:elasticsearch-7.6.2-linux-x86_64.tar.gz
3.发送给虚拟机:192.168.10.100 使用xftp或者finalShell右键上传
4.发给其他两台(不使用命令使用步骤3上传也可以):
scp 192.168.10.101@root /root/elasticsearch-7.6.2-linux-x86_64.tar.gz /root/
scp 192.168.10.102@root /root/elasticsearch-7.6.2-linux-x86_64.tar.gz /root/
5.开始批量操作,三台虚拟机一起
tar zxvf elasticsearch-7.6.2-linux-x86_64.tar.gz -C /usr/local/ #elasearch不能以root运行 groupadd es useradd es -g es #修改权限 chown -Rf es:es /usr/local/elasticsearch-7.6.2/ #jdk如果该centos安装的jdk11就不用下面操作 #修改此文件文件末尾添加 vim bin/elasticsearch-env JAVA_HOME="/usr/local/elasticsearch-7.6.2/jdk/" #远程访问设置 #实际环境添加允许访问的ip vi config/elasticsearch.yml network.host: 0.0.0.0 #修改运行数据 #末尾添加 vi /etc/security/limits.conf es soft nofile 65535 es hard nofile 65535 es soft nproc 4096 es hard nproc 4096 #修改jvm运行内存 vi /etc/sysctl.conf vm.max_map_count = 262144 #重新加载系统内存 sysctl -p #修改elasearchjvm垃圾回收器:不改会有警告提示; UseConcMarkSweepGC 在jdk9就标注过时 #将: -XX:+UseConcMarkSweepGC 改为: -XX:+UseG1GC vi config/jvm.options #配置集群环境 vi config/elasticsearch.yml #===========================================每台电脑不同的node.name:分别为:node-1,node-2,node-3 #:如果设置了 node.name 需要将 cluster.initial_master_nodes 改为对应节点名称。 cluster.name: es # 集群名称,同一集群要一致 node.name: node-1 # 集群下各节点名称 http.port: 9200 # 端口 # 跨域请求配置(为了让类似head的第三方插件可以请求es) http.cors.enabled: true http.cors.allow-origin: "*" # 集群发现配置 discovery.seed_hosts: ["192.168.10.100", "192.168.10.101", "192.168.10.102"] cluster.initial_master_nodes: ["node-1", "node-2", "node-3"] discovery.zen.ping_timeout: 60s #======================================================================= #elasearch占内存特别高,我是 1G 1cup,修改jvm参数512m vi config/jvm.options -Xms512m -Xmx512m #大功告成,有些文件修改需要root权限,所以如果文件修改失败需要切换root su root #最后防止权限的问题 chown -Rf es:es /usr/local/elasticsearch-7.6.2/ #运行,3台集群,这里先运行两台 /usr/local/elasticsearch/elasticsearch-7.6.2/bin/elasticsearch
访问:http://192.168.10.100:9200/_cluster/health?pretty
这里可以看到有两台节点。这里安装完成;
谷歌浏览器图形界面:ElasticSearch Head
或者微软 Edge浏览器Elasticvue插件
这里面的数据是通过Logstash导入
ES官网:https://www.elastic.co/products/logstash
下载地址:https://www.elastic.co/cn/downloads/logstash
Logstash 是开源的服务器端数据处理管道,能够同时从多个来源采集数据,转换数据,然后将数据发 送到您最喜欢的 “存储库” 中。(我们的存储库当然是 Elasticsearch。)
mkdir -p /usr/local/logstash
tar -zxvf logstash-7.6.2.tar.gz -C /usr/local/logstash/
cd /usr/local/logstash/logstash-7.6.2
bin/logstash -e 'input { stdin {} } output { stdout {} }'
出来message:hello-world就成功开启了
关闭logstash:ctrl c
上传mysql驱动到:/usr/local/logstash/logstash-7.6.2/logstash-core/lib/jars/
jdbc.conf:
cd /usr/local/logstash/logstash-7.6.2
vi jdbc.conf
内容
input { stdin { } jdbc { # 配置数据库信息 jdbc_connection_string => "jdbc:mysql://localhost:3306/shop? useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai" jdbc_driver_class => "com.mysql.cj.jdbc.Driver" jdbc_user => "root" jdbc_password => "root" jdbc_paging_enabled => "true" jdbc_page_size => "50000" jdbc_default_timezone => "Asia/Shanghai" # 执行 sql 语句文件 statement_filepath => "/usr/local/logstash/logstash-7.6.2/jdbc.sql" # 定时字段 各字段含义(由左至右)分、时、天、月、年,全部为*默认含义为每分钟都更新 schedule => "* * * * *" # 是否将 sql 中 column 名称转小写 lowercase_column_names => false } } output { elasticsearch { hosts => ["127.0.0.1:9200"] index => "shop" # 文档_id,%{goods_id}意思是取查询出来的goods_id的值,并将其映射到es的_id字段中 # 文档_id,%{goodsId}如果是别名,意思是取查询出来的goodsId的值,并将其映射到es的_id字段 中 document_id => "%{goodsId}" } stdout { codec => json_lines } }
修改成你的mysql连接,用户名和密码
jdbc.sql:你的sql查询语句:例如
SELECT
goods_id goodsId,
goods_name goodsName,
market_price marketPrice,
original_img originalImg
FROM
t_goods
检查jdbc.conf正确性
bin/logstash -f /usr/local/logstash/logstash-7.6.2/jdbc.conf -t
创建索引库
curl -X PUT http://localhost:9200/shop -H 'Content-Type:application/json' -d'{
"settings": {
"number_of_shards": 5,
"number_of_replicas": 1
}
}'
设置mapping
curl -XPOST http://localhost:9200/shop/_mapping -H 'Content-Type:application/json' -
d'{
"properties": {
"goodsName": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_max_word"
}
}
}'
运行导入数据:
cd /usr/local/logstash/logstash-7.6.2/
bin/logstash -f /usr/local/logstash/logstash-7.6.2/jdbc.conf
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
#配置es
spring:
elasticsearch:
rest:
uris: 192.168.10.100:9200,192.168.10.100:9201,192.168.10.100:9202
pojo类:
为需要使用索引库的实体类加上注解 @Document 部分属性如下
indexName=“索引库名”
shards = 分片数量(默认1)
replicas = 副本数量(默认1)
为id属性 添加 @Id 注释
各个字段加上注解并制定类型 @Field 部分属性如下
type= FieldType.枚举 : 指定字段类型 Keyword不分词, Text分词 对应着elasticsearch的字 段类型
为需要分词的字段添加分词器 analyzer=“分词器名” (ik分词器固定写法 ik_max_word )
是否创建索引 createIndex=boolean(默认true)
import lombok.Data; import org.springframework.data.annotation.Id; import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.elasticsearch.annotations.Field; import org.springframework.data.elasticsearch.annotations.FieldType; import java.io.Serializable; import java.math.BigDecimal; import java.util.Date; /** * @author lwf * @since 1.0.0 */ @Document(indexName = "shop",shards = 5,replicas = 1,createIndex = false) @Data public class Goods implements Serializable { /** * 商品id */ @Id private Integer goodsId; /** * 商品名称 */ @Field(type = FieldType.Text,analyzer = "ik_max_word") private String goodsName; /** * 市场价 */ @Field(type = FieldType.Double) private BigDecimal marketPrice; /** * 商品上传原始图 */ @Field(type = FieldType.Keyword) private String originalImg; //高亮名字 private String googsNameH1; //数量 private Integer goodsNum; //日期 private Date addTime; }
查询代码
import com.xxxx.protal.dao.GoodsRepository; import com.xxxx.protal.pojo.Goods; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder; import org.elasticsearch.search.sort.SortBuilders; import org.elasticsearch.search.sort.SortOrder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.Cacheable; import org.springframework.data.domain.PageRequest; import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate; import org.springframework.data.elasticsearch.core.SearchHit; import org.springframework.data.elasticsearch.core.SearchHits; import org.springframework.data.elasticsearch.core.query.NativeSearchQuery; import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.List; /** * @author lwf * @title: EsSearchService * @projectName shop * @description: TODO * @date 2021/1/515:24 */ @Service public class EsSearchService { @Autowired private ElasticsearchRestTemplate elasticsearchRestTemplate; @Cacheable(value = "goodsPage",key="#searchKey+'-'+#pageNum+''+#pageSize") public List<Goods> pageSearch(String searchKey,Integer pageNum,Integer pageSize){ NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder(); NativeSearchQuery query = nativeSearchQueryBuilder /** * 第一个参数:关键词 * 第二个参数:对应es的字段 */ .withQuery(QueryBuilders.multiMatchQuery(searchKey, "goodsName")) /** * 第一个参数:当前页,0开始 * 第二个参数:每个条数 * 第三个参数:排序对象 * 升序/降序 * 比较字段 */ // .withPageable(PageRequest.of(0,5,Sort.Direction.DESC,"goodsId","marketPrice")) // 分页 .withPageable(PageRequest.of(pageNum-1, pageSize)) // .withSort(SortBuilders.fieldSort("marketPrice").order(SortOrder.ASC)) //高亮,默认样式<em></em>(斜体) // .withHighlightFields(new HighlightBuilder.Field("goodsName")) //高亮,指定样式 .withHighlightBuilder(new HighlightBuilder().field("goodsName").preTags("<span style='color:red;'>").postTags(" </span>")) .build(); //返回结果 List<Goods> result=new ArrayList<>(); SearchHits<Goods> search = elasticsearchRestTemplate.search(query, Goods.class); for (SearchHit<Goods> searchHit : search) { Goods goods=null; String highlightMessage = searchHit.getHighlightField("goodsName").get(0); System.out.println("高亮-----------"); System.out.println(highlightMessage); //结果对象 goods=searchHit.getContent(); goods.setGoogsNameH1(highlightMessage); goods.setGoodsNum((int) search.getTotalHits()); System.out.println("数据:"+goods.getGoodsNum()); result.add(goods); } return result; } }
和jpa类似用法:
@Repository
public interface GoodsRepository extends ElasticsearchRepository<Goods, Integer> {
List<Goods> findByGoodsName(String goodsName);
@Query("{\"match\": {\"goodsId\":{ \"query\": \"?0\"}}}")
Goods findByGoodsIdValue(Integer id);
}
公共接口作为jar宝存在,生产者消费者单独作为一个项目;
流程说明:
服务提供者启动时: 向 /dubbo/com.foo.BarService/providers 目录下写入自己的 URL 地 址
服务消费者启动时: 订阅 /dubbo/com.foo.BarService/providers 目录下的提供者 URL 地 址。并向 /dubbo/com.foo.BarService/consumers 目录下写入自己的 URL 地址
监控中心启动时: 订阅 /dubbo/com.foo.BarService 目录下的所有提供者和消费者 URL 地 址。
三台服务器分别为:192.168.10.100,192.168.10.101,192.168.10.102
解压
tar -zxvf apache-zookeeper-3.6.1-bin.tar.gz -C /usr/local/
创建数据目录data,日志目录log,数据目录data添加myid文件,myid 文件中
192.168.10.100:只写1
192.168.10.101:只写2
192.168.10.102:只写3
mkdir -p /usr/local/apache-zookeeper-3.6.1-bin/data
mkdir -p /usr/local/apache-zookeeper-3.6.1-bin/log
cd /usr/local/apache-zookeeper-3.6.1-bin/data
vim myid
复制zoo_sample.cfg,并将文件重命名为zoo.cfg
# The number of milliseconds of each tick tickTime=2000 # The number of ticks that the initial # synchronization phase can take initLimit=10 # The number of ticks that can pass between # sending a request and getting an acknowledgement syncLimit=5 # the directory where the snapshot is stored. # do not use /tmp for storage, /tmp here is just # example sakes. dataDir=/usr/local/apache-zookeeper-3.6.1-bin/data logDir=/usr/local/apache-zookeeper-3.6.1-bin/log # the port at which the clients will connect clientPort=2181 # the maximum number of client connections. # increase this if you need to handle more clients #maxClientCnxns=60 # # Be sure to read the maintenance section of the # administrator guide before turning on autopurge. # # http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance # # The number of snapshots to retain in dataDir #autopurge.snapRetainCount=3 # Purge task interval in hours # Set to "0" to disable auto purge feature #autopurge.purgeInterval=1 # 集群配置 # server.1 中的 1 是 myid 文件中的内容,2888 用于集群内部通信,3888用于选择leader server.1=192.168.10.100:2888:3888 server.2=192.168.10.101:2888:3888 server.3=192.168.10.102:2888:3888
启动
cd /usr/local/
apache-zookeeper-3.6.1-bin/bin/zkServer.sh start
查看状态
apache-zookeeper-3.6.1-bin/bin/zkServer.sh status
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <packaging>pom</packaging> <modules> <module>dubbo-api</module> <module>dubbo-provider</module> <module>dubbo-consumer</module> </modules> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.5.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.xxxx</groupId> <artifactId>dubbo-demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>dubbo-demo</name> <description>Demo project for Spring Boot</description> <properties> <java.version>11</java.version> <dubbo.version>2.7.3</dubbo.version> </properties> <dependencyManagement> <dependencies> <!-- dubbo依赖 --> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>${dubbo.version}</version> </dependency> <!--zookeeper 注册中心客户端引入 curator客户端 --> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-dependencies-zookeeper</artifactId> <version>${dubbo.version}</version> <type>pom</type> </dependency> </dependencies> </dependencyManagement> </project>
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>dubbo-demo</artifactId> <groupId>com.xxxx</groupId> <version>0.0.1-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>dubbo-api</artifactId> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- dubbo依赖 --> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> </dependency> <!--zookeeper 注册中心客户端引入 curator客户端 --> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-dependencies-zookeeper</artifactId> <type>pom</type> </dependency> </dependencies> </project>
接口
public interface MyService {
List<Panda> getBySome(Panda panda);
}
pojo类
public class Panda implements Serializable { private Integer id; private String name; private String city; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } @Override public String toString() { return "Panda{" + "id=" + id + ", name='" + name + '\'' + ", city='" + city + '\'' + '}'; } public Panda(Integer id, String name, String city) { this.id = id; this.name = name; this.city = city; } public Panda() { } }
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>dubbo-demo</artifactId> <groupId>com.xxxx</groupId> <version>0.0.1-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>dubbo-provider</artifactId> <dependencies> <dependency> <groupId>com.xxxx</groupId> <artifactId>dubbo-api</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> </dependencies> </project>
application.yml
server: port: 8081 dubbo: application: # 应用名称 name: provider registry: # 注册中心地址 address: zookeeper://192.168.10.100:2181?backup=192.168.10.101:2181,192.168.10.102:2181 # 超时时间,单位毫秒 timeout: 6000 metadata-report: address: zookeeper://192.168.10.100:2181 protocol: #协议名称 name: dubbo #协议端口 port: 20880 scan: #扫描包的位置 base-packages: com.xxxx.provider.service
服务暴露:在com.xxxx.provider.service包下
import com.xxxx.api.pojo.Panda; import com.xxxx.api.service.MyService; import org.apache.dubbo.config.annotation.Service; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; /** * @author lwf * @title: MyServiceImpl * @projectName dubbozk * @description: TODO * @date 2020/12/2920:13 */ @Service(version = "1.0",interfaceClass = MyService.class) public class MyServiceImpl implements MyService { @Override public List<Panda> getBySome(Panda panda) { List<Panda> pandas=new ArrayList<>(); pandas.add(new Panda(1, "雪宝", "上海")); pandas.add(new Panda(2, "雪宝1", "上海")); pandas.add(new Panda(3, "金虎", "大连")); pandas.add(new Panda(4, "熊猫", "成都")); pandas.add(new Panda(5, "熊猫", "成都")); pandas.add(new Panda(6, "熊猫", "成都")); pandas.add(new Panda(7, "绩效", "重庆")); pandas.add(new Panda(8, "小熊猫", "重庆")); List<Panda> list=null; if(panda.getId()!=null){ //编号大于传入id的熊猫 list=pandas.parallelStream().filter(a->{ return panda.getId()<a.getId(); }).collect(Collectors.toList()); } if(panda.getCity()!=null){ //城市 list=list.stream().filter(e->{ return e.getCity().equals(panda.getCity()); }).collect(Collectors.toList()); } return list; } }
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>dubbo-demo</artifactId> <groupId>com.xxxx</groupId> <version>0.0.1-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>dubbo-consumer</artifactId> <dependencies> <dependency> <groupId>com.xxxx</groupId> <artifactId>dubbo-api</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> </dependencies> </project>
消费服务
import com.xxxx.api.pojo.Panda; import com.xxxx.api.service.MyService; import com.xxxx.api.service.UserService; import org.apache.dubbo.config.annotation.Reference; import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; @Component public class UserInit implements CommandLineRunner { @Reference(version = "1.0", parameters = {"unicast", "false"}) private MyService myService; @Override public void run(String... args) throws Exception { myService.getBySome(new Panda(2,null,null)).forEach(System.out::println); } }
注意:
pojo类必须实现序列化接口
version可以指定调用哪个版本;
消费成功
复制生产者,两个生产者被消费
生产者消费另外的生产者
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。