查看: 241|回复: 0

[Java语言] 详解Spring Cloud 跨服务数据聚合框架

发表于 7 天前

AG-Merge

Spring Cloud 跨服务数据聚合框架

解决问题

解决Spring Cloud服务拆分后分页数据的属性或单个对象的属性拆分之痛, 支持对静态数据属性(数据字典)、动态主键数据进行自动注入和转化, 其中聚合的静态数据会进行 一级混存 (guava).

举个栗子:

两个服务,A服务的某张表用到了B服务的某张表的值,我们在对A服务那张表查询的时候,把B服务某张表的值聚合在A服务的那次查询过程中

示例

具体示例代码可以看 ace-merge-demo 模块

  1. |------- ace-eureka 注册中心
  2. |------- ace-data-merge-demo 查询数据,此处聚合示例
  3. |------- ace-data-provider 数据提供者
复制代码

Maven添加依赖

  1. <dependency>
  2. <groupId>com.github.wxiaoqi</groupId>
  3. <artifactId>ace-merge-core</artifactId>
  4. <version>2.0-SNAPSHOT</version>
  5. </dependency>
复制代码

推荐仓库配置

  1. <repositories>
  2. <repository>
  3. <id>oss</id>
  4. <name>oss</name>
  5. <url>https://oss.sonatype.org/content/groups/public</url>
  6. </repository>
  7. </repositories>
复制代码

启动类加注解

  1. @EnableAceMerge
复制代码

application.yml配置

  1. # 跨服务数据合并
  2. merge:
  3. enabled: true
  4. guavaCacheNumMaxSize: 1000
  5. guavaCacheRefreshWriteTime: 10 # min
  6. guavaCacheRefreshThreadPoolSize: 10
  7. aop: # 启动注解的方式,自动聚合
  8. enabled: true
复制代码

代码示例( @MergeField 标志对象的数据需要聚合)

  1. @Retention(RetentionPolicy.RUNTIME)
  2. @Target(value={ElementType.METHOD,ElementType.TYPE,ElementType.FIELD})
  3. public @interface MergeField {
  4. /**
  5. * 查询值
  6. * @return
  7. */
  8. String key() default "";
  9. /**
  10. * 目标类
  11. * @return
  12. */
  13. Class<? extends Object> feign() default Object.class;
  14. /**
  15. * 调用方法
  16. * @return
  17. */
  18. String method() default "";
  19. /**
  20. * 是否以属性值合并作为查询值
  21. * @return
  22. */
  23. boolean isValueNeedMerge() default false;
  24. }
复制代码

聚合对象

  1. public class User {
  2. private String name;
  3. // 需要聚合的属性
  4. @MergeField(key="test", feign = IService2.class,method = "writeLog")
  5. private String sex;
  6. // 需要聚合的属性
  7. @MergeField(feign = IService2.class,method = "getCitys",isValueNeedMerge = true)
  8. private String city;
  9. public User(String name, String sex, String city) {
  10. this.name = name;
  11. this.sex = sex;
  12. this.city = city;
  13. }
  14. public String getCity() {
  15. return city;
  16. }
  17. public void setCity(String city) {
  18. this.city = city;
  19. }
  20. public User(String name) {
  21. this.name = name;
  22. }
  23. public User(String name, String sex) {
  24. this.name = name;
  25. this.sex = sex;
  26. }
  27. public String getName() {
  28. return name;
  29. }
  30. public void setName(String name) {
  31. this.name = name;
  32. }
  33. public String getSex() {
  34. return sex;
  35. }
  36. public void setSex(String sex) {
  37. this.sex = sex;
  38. }
  39. }
复制代码

聚合数据来源方法(示例为通过FeignClient,也可以是本地的spring bean对象)

特别要求:入参必须为一个String,返回值必须为Map. 其中返回值的构成,就是聚合对象属性的key和对应的value.

  1. @FeignClient("test")
  2. public interface IService2 {
  3. @RequestMapping("car/do")
  4. public Map<String, String> writeLog(String test);
  5. @RequestMapping("car/city")
  6. public Map<String, String> getCitys(String ids);
  7. }
复制代码

对应的远程服务接口

  1. /**
  2. * @author ace
  3. * @create 2017/11/20.
  4. */
  5. @RestController
  6. @RequestMapping("car")
  7. public class Service2Rest {
  8. private Logger logger = LoggerFactory.getLogger(Service2Rest.class);
  9. @RequestMapping("do")
  10. public Map<String,String> writeLog(String test){
  11. logger.info("service 2 is writing log!");
  12. Map<String,String> map = new HashMap<String, String>();
  13. map.put("man","男");
  14. map.put("woman","女");
  15. return map;
  16. }
  17. @RequestMapping("city")
  18. public Map<String,String> getCity(String ids){
  19. logger.info("service 2 is writing log!"+ids);
  20. Map<String,String> map = new HashMap<String, String>();
  21. map.put("1","广州");
  22. map.put("2","武汉");
  23. return map;
  24. }
  25. }
复制代码

聚合对象的Biz类(下面的方式是采用aop扫描注解的方式)

  1. @Service
  2. @Slf4j
  3. public class UserBiz {
  4. @Autowired
  5. private MergeCore mergeCore;
  6. /**
  7. * aop注解的聚合方式
  8. * 其中聚合的方法返回值必须为list,
  9. * 如果为复杂对象,则需要自定义自己的聚合解析器(实现接口IMergeResultParser)
  10. */
  11. @MergeResult(resultParser = TestMergeResultParser.class)
  12. public List<User> getAopUser() {
  13. ArrayList<User> users = new ArrayList<User>();
  14. for (int i = 1000; i > 0; i--) {
  15. users.add(new User("zhangsan" + i, "man", "1"));
  16. users.add(new User("lisi" + i, "woman", "2"));
  17. users.add(new User("wangwu" + i, "unkonwn", "2"));
  18. }
  19. return users;
  20. }
  21. /**
  22. * 手动聚合方式
  23. * @return
  24. */
  25. public List<User> getUser(){
  26. ArrayList<User> users = new ArrayList<User>();
  27. for (int i = 1000; i > 0; i--) {
  28. users.add(new User("zhangsan" + i, "man", "1"));
  29. users.add(new User("lisi" + i, "woman", "2"));
  30. users.add(new User("wangwu" + i, "unkonwn", "2"));
  31. }
  32. try {
  33. // list 聚合
  34. mergeCore.mergeResult(User.class,users);
  35. // 单个对象聚合
  36. // mergeCore.mergeOne(User.class,users.get(0));
  37. } catch (Exception e) {
  38. log.error("数据聚合失败",e);
  39. }finally {
  40. return users;
  41. }
  42. }
  43. }
复制代码

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持程序员之家。



回复

使用道具 举报