服务端对客户端进行回调

通过参数回调从服务器端调用客户端逻辑

特性说明

参数回调方式与调用本地 callback 或 listener 相同,只需要在 Spring 的配置文件中声明哪个参数是 callback 类型即可。Dubbo 将基于长连接生成反向代理,这样就可以从服务器端调用客户端逻辑。可以参考 dubbo 项目中的示例代码

使用场景

回调函数通知客户端执行结果,或发送通知,在方法执行时间比较长时,类似异步调用,审批工作流中回调客户端审批结果。

使用方式

服务接口示例

CallbackService.java

  1. package com.callback;
  2. public interface CallbackService {
  3. void addListener(String key, CallbackListener listener);
  4. }

CallbackListener.java

  1. package com.callback;
  2. public interface CallbackListener {
  3. void changed(String msg);
  4. }

服务提供者接口实现示例

  1. package com.callback.impl;
  2. import java.text.SimpleDateFormat;
  3. import java.util.Date;
  4. import java.util.Map;
  5. import java.util.concurrent.ConcurrentHashMap;
  6. import com.callback.CallbackListener;
  7. import com.callback.CallbackService;
  8. public class CallbackServiceImpl implements CallbackService {
  9. private final Map<String, CallbackListener> listeners = new ConcurrentHashMap<String, CallbackListener>();
  10. public CallbackServiceImpl() {
  11. Thread t = new Thread(new Runnable() {
  12. public void run() {
  13. while(true) {
  14. try {
  15. for(Map.Entry<String, CallbackListener> entry : listeners.entrySet()){
  16. try {
  17. entry.getValue().changed(getChanged(entry.getKey()));
  18. } catch (Throwable t) {
  19. listeners.remove(entry.getKey());
  20. }
  21. }
  22. Thread.sleep(5000); // 定时触发变更通知
  23. } catch (Throwable t) { // 防御容错
  24. t.printStackTrace();
  25. }
  26. }
  27. }
  28. });
  29. t.setDaemon(true);
  30. t.start();
  31. }
  32. public void addListener(String key, CallbackListener listener) {
  33. listeners.put(key, listener);
  34. listener.changed(getChanged(key)); // 发送变更通知
  35. }
  36. private String getChanged(String key) {
  37. return "Changed: " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
  38. }
  39. }

服务提供者配置示例

  1. <bean id="callbackService" class="com.callback.impl.CallbackServiceImpl" />
  2. <dubbo:service interface="com.callback.CallbackService" ref="callbackService" connections="1" callbacks="1000">
  3. <dubbo:method name="addListener">
  4. <dubbo:argument index="1" callback="true" />
  5. <!--也可以通过指定类型的方式-->
  6. <!--<dubbo:argument type="com.demo.CallbackListener" callback="true" />-->
  7. </dubbo:method>
  8. </dubbo:service>

服务消费者配置示例

  1. <dubbo:reference id="callbackService" interface="com.callback.CallbackService" />

服务消费者调用示例

  1. ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:consumer.xml");
  2. context.start();
  3. CallbackService callbackService = (CallbackService) context.getBean("callbackService");
  4. callbackService.addListener("foo.bar", new CallbackListener(){
  5. public void changed(String msg) {
  6. System.out.println("callback1:" + msg);
  7. }
  8. });

最后修改 December 16, 2022: Fix check (#1736) (97972c1)