概念

参数回调就是dubbo的provider调用consumer代码.
参数回调分为同步回调和异步回调

同步回调官网文档地址:https://dubbo.apache.org/zh/docs/v2.7/user/examples/callback-parameter/
异步回调官网文档地址
https://dubbo.apache.org/zh/docs/v2.7/user/examples/async-call/
异步回调就是利用了Java的CompletableFuture

gitee代码地址

https://gitee.com/zjj19941/ZJJ_Dubbo.gitcallback项目就是代码,自己准备个zookeeper,然后改一下配置文件,先执行provider,再执行consumer,即可看到效果

使用

interface项目声明一个回调接口类

  1. package com.zjj;
  2. // 回调参数
  3. public interface DemoServiceListener {
  4. String changed(String msg) throws InterruptedException;
  5. }

interface项目接口添加一个回调方法

  1. package com.zjj;
  2. public interface DemoService {
  3. // 添加回调逻辑,不然的话消费者无法进行回调
  4. //参数2是key, 不同的key的回调函数可以不一样. 这个key就类似于
  5. default String sayHello(String name, DemoServiceListener listener) throws InterruptedException {
  6. return null;
  7. };
  8. }

provider编写回调方法

public String sayHello(String name, DemoServiceListener callback) 是回调方法

@Service也配置了一些参数回调相关的参数

  1. package com.zjj.provider.service;
  2. import com.zjj.DemoService;
  3. import com.zjj.DemoServiceListener;
  4. import org.apache.dubbo.config.annotation.Argument;
  5. import org.apache.dubbo.config.annotation.Method;
  6. import org.apache.dubbo.config.annotation.Service;
  7. // DemoService的sayHello方法的index=1的参数是回调对象,服务消费者可以调用addListener方法来添加回调对象,服务提供者一旦执行回调对象的方法就会通知给服务消费者
  8. //arguments = {@Argument(index = 1, callback = true)})} 的意思是 sayHello方法的第二个参数是回调参数
  9. //callbacks = 3 的意思是这个服务最多支持多少个回调
  10. @Service(version = "default", timeout =1000000 , methods = {@Method(name = "sayHello", arguments = {@Argument(index = 1, callback = true)})}, callbacks = 3)
  11. public class CallBackDemoService implements DemoService {
  12. /**
  13. * 回调方法
  14. */
  15. @Override
  16. public String sayHello(String name, DemoServiceListener callback) throws InterruptedException {
  17. System.out.println("1.开始执行回调服务,参数name是:" + name + " 毫秒值是 :" + System.currentTimeMillis());
  18. //在执行回调函数
  19. String rs = callback.changed("我是provider传过去的入参");
  20. Thread.sleep(1000);
  21. System.out.println("3.回调的结果是: " + rs + " 毫秒值是 :" + System.currentTimeMillis());
  22. return String.format( name); // 正常访问
  23. }
  24. }

consumer编写回调类

这个回调类的逻辑会被provider调用

  1. package com.zjj;
  2. //参数回调
  3. public class DemoServiceListenerImpl implements DemoServiceListener {
  4. @Override
  5. public String changed(String msg) throws InterruptedException {
  6. System.out.println("2.被回调了:"+msg + " 毫秒值是 :" + System.currentTimeMillis());
  7. Thread.sleep(1000);
  8. return "回调结果";
  9. }
  10. }

consumer方法访问provider

参数2就是指定回调方法.指定的这个回调方法会被provider调用到.

String rs = demoService.sayHello(“周瑜”, new DemoServiceListenerImpl());

  1. package com.zjj;
  2. import org.apache.dubbo.config.annotation.Reference;
  3. import org.springframework.boot.SpringApplication;
  4. import org.springframework.boot.autoconfigure.SpringBootApplication;
  5. import org.springframework.context.ConfigurableApplicationContext;
  6. @SpringBootApplication
  7. public class DubboConsumerDemo {
  8. //@Reference注解就是用于标记这个服务具体使用了生产者的哪个接口实现
  9. @Reference(version = "default",timeout = 100000000)
  10. private DemoService demoService;
  11. public static void main(String[] args) throws InterruptedException {
  12. ConfigurableApplicationContext context = SpringApplication.run(DubboConsumerDemo.class);
  13. DemoService demoService = context.getBean(DemoService.class);
  14. //等provider调用完了回调之后,这个方法才会给返回值结果.
  15. String rs = demoService.sayHello("周瑜", new DemoServiceListenerImpl());
  16. System.out.println("4.rs:" + rs + " 毫秒值是 :" + System.currentTimeMillis());
  17. }
  18. }

执行结果

provider控制台

  1. 1.开始执行回调服务,参数name是:周瑜 毫秒值是 :1639306614182
  2. 3.回调的结果是: 回调结果 毫秒值是 :1639306616205

consumer控制台

2.被回调了:我是provider传过去的入参   毫秒值是 :1639306614201
4.rs:周瑜   毫秒值是 :1639306616210

看控制台打印的毫秒值就能看出来方法执行顺序.

1.consumer先调用provider的sayHello方法,
2.provider调用consumer的回调方法
3.provider收到回调结果后方法执行完毕
4.consumer的sayHello执行完毕,获取到方法的返回结果

上面是同步回调的处理顺序