第一:它的應用場景是什麼?
if you call me ,i will call back。目前我接觸到兩種須要回調的需求javascript
一、系統管理平臺登陸,登陸所須要的人員和部門數據都是在另外一個基礎信息系統中。當基礎信息中人員或者部門信息改變的時候,若是不通知其餘系統,尤爲是系統管理系統這種對於核心數據很關鍵的系統會形成數據不一樣步的問題,因此當基礎信息中的數據增刪改的時候就要通知其餘系統。html
二、小紅小明作算術題,小明須要小紅算數作做業,老婆婆須要小紅算數算帳,調用的都是小紅計算器,小紅接着調用特定的接口,小明和老婆婆各自不一樣實現。服務端提供一種公用的方法,可是各個客戶端調用的時候有較小的差別,那麼公用的方法放在服務端使用,存在差別的部分放在服務端本身實現。java
(參考文章:http://blog.csdn.net/qq_30983519/article/details/52537613)json
第二:它的實現原理是什麼?api
CallBack回調機制,它的本質是服務端調用客戶端的邏輯,形式是服務端提供接口,而由客戶端按照本身的需求具體實現。客戶端先調用服務端的服務,服務端處理後再調用客戶端邏輯。ide
第三:它的實現方式是什麼?函數
第一個例子是計算器:學習
小紅但願之後繼續向小明提供計算服務,同時還能向老婆婆提供算帳服務,甚至之後可以拓展其餘人的業務,因而她向全部的顧客約定了一個辦法,用於統一的處理,也就是本身須要的操做數和作完計算以後應該怎麼作。這個統一的方法,小紅作成了一個接口,提供給了你們,代碼以下:測試
public interface doJob { public void fillBlank(int a, int b, int result); }
同時,小紅修改了本身的計算器,使其能夠同時處理不一樣的實現了doJob接口的人,代碼以下:jsonp
public class SuperCalculator { public void add(int a, int b, doJob customer) { int result = a + b; customer.fillBlank(a, b, result); } }
小明和老婆婆拿到這個接口以後,只要實現了這個接口,就至關於按照統一的模式告訴小紅獲得結果以後的處理辦法,按照以前說的使用內部類來作,小明代碼以下:
public class Student { private String name = null; public Student(String name) { // TODO Auto-generated constructor stub this.name = name; } public void setName(String name) { this.name = name; } public class doHomeWork implements doJob { @Override public void fillBlank(int a, int b, int result) { // TODO Auto-generated method stub System.out.println(name + "求助小紅計算:" + a + " + " + b + " = " + result); } } public void callHelp (int a, int b) { new SuperCalculator().add(a, b, new doHomeWork()); } }
老婆婆:
public class Seller { private String name = null; public Seller(String name) { // TODO Auto-generated constructor stub this.name = name; } public void setName(String name) { this.name = name; } public class doHomeWork implements doJob { @Override public void fillBlank(int a, int b, int result) { // TODO Auto-generated method stub System.out.println(name + "求助小紅算帳:" + a + " + " + b + " = " + result + "元"); } } public void callHelp (int a, int b) { new SuperCalculator().add(a, b, new doHomeWork()); } }
測試代碼:
public class Test { public static void main(String[] args) { int a = 56; int b = 31; int c = 26497; int d = 11256; Student s1 = new Student("小明"); Seller s2 = new Seller("老婆婆"); s1.callHelp(a, b); s2.callHelp(c, d); } }
第二:系統登陸所需的部門人員數據變化
基礎信息服務端代碼:
import com.alibaba.dubbo.config.annotation.Service; /** * 提供回調功能的Dubbo服務 * @author yuankun * @version V1.0 */ @Service(protocol = { "dubbo" }) public interface CallbackService { /** * 向回調服務中註冊一個監聽器 * @param listener 監聽器 */ void addListener(CallbackListener listener); //這個接口是對外暴露的,用於增長相似於監聽器做用的訂閱對象。 /** * 當記錄修改事件發生時,通知全部監聽器 * @param changeType 事件類型 * @param object 被改變的對象 */ void notifyListener(String changeType, Object object, Class name); //這個是向內提供的,開始我還很奇怪,爲何會讓系統本身調用本身提供的dubbo服務,而不是將接口寫在core中,不對外暴露,後來我發如今接口的實現過程當中,addListener的listeners是公用的,爲了onChange時容易得到listeners,因此將邏輯寫在dubbo接口中,保證listeners的全局做用 /** * 返回回調服務目前的狀態,以斷定其工做是否正常 * @return 0:代表回調服務工做正常,其餘:代表回調服務沒法正常工做 */ int isActive(); }
dubbo接口的實現
package com.enjoyor.soa.traffic.server.ubms.service.dubbo.impl.callback; import java.util.ArrayList; import java.util.List; import com.enjoyor.soa.traffic.api.ubms.service.CallbackListener; import com.enjoyor.soa.traffic.api.ubms.service.CallbackService; public class CallbackServiceImpl implements CallbackService { private final List<CallbackListener> listeners = new ArrayList<CallbackListener>(); @Override public void addListener(CallbackListener listener) { // TODO Auto-generated method stub listeners.add(listener); } @Override public void notifyListener(String changeType, Object object, Class name) { // TODO Auto-generated method stub for (CallbackListener listener : listeners) { try { listener.update(changeType, object, name);//對外回調的接口 } catch (Throwable t) { if (listeners.indexOf(listener) >= 0) { listeners.remove(listener); } } } } @Override public int isActive() { return 0; } }
對外回調的接口:
import com.alibaba.dubbo.config.annotation.Service; /** * 提供內容變化監聽功能的接口 * @author yuankun * @version V1.0 */ @Service(protocol = { "dubbo" }) public interface CallbackListener { /** * 獲得監聽器通知後的響應方法 * @param changeType 事件類型 * @param object 被修改的對象 */ void update(String changeType, Object object, Class name); }
服務端通知過程,更新時通知:
public ResultPojo addDeptInfo(String token, DeptInfoDto deptInfoDto) { try { if(checkToken(token)) { List<DeptInfoPojo> list = this.deptInfoService.getDeptInfo(deptInfoDto.getDeptId(), null, null, null, null); if(list.size()>0){ return ResultHelper.getResult(EnumAppCode.PARAM_NAME_EXISTS); } DeptInfoPojo deptInfoPojo = this.dtoToPojo(deptInfoDto); int result = this.deptInfoService.addDeptInfo(getUserNameByToken(token), deptInfoPojo); this.notify(result, "addDeptInfo", deptInfoDto,DeptInfoDto.class);//!!! return ResultHelper.getResult(result); } else { return ResultHelper.getResult(EnumAppCode.TOKEN_INVALID); } } catch (Exception ex) { return ResultHelper.getResult(ex); } }
/** * 回調Dubbo服務 * @param result * @param type * @param obj */ private CallbackService getCallbackService() { CallbackService service = (CallbackService) SpringContextUtil.getBean("callbackService", CallbackService.class); // return service; } public void notify(int result, String type, Object obj, Class name) { if (result > 0) { if(null != this.getCallbackService()) { this.getCallbackService().notifyListener(type, obj, name); } } }
客戶端 登錄(uums)的代碼:
dubbo接口的調用,增長相應的監聽:
import java.util.Map; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import com.enjoyor.soa.traffic.api.ubms.dto.DeptInfoDto; import com.enjoyor.soa.traffic.api.ubms.dto.PersonInfoDto; import com.enjoyor.soa.traffic.api.ubms.service.CallbackService; import com.enjoyor.soa.traffic.server.uums.service.dubbo.invoke.DubboContext; import com.enjoyor.soa.traffic.server.uums.service.dubbo.invoke.DubboDeptInfoServiceInvoke; import com.enjoyor.soa.traffic.server.uums.service.dubbo.invoke.DubboPerserInfoServiceInvoke; import com.enjoyor.soa.traffic.server.uums.service.dubbo.invoke.DubboUbmsCallbackListener; public class DubboUbmsCallbackThread implements Runnable { public BlockingQueue<Map<String, Object>> queueReceive = new LinkedBlockingQueue<Map<String,Object>>(); // public DubboUbmsCallbackThread(BlockingQueue<Map<String, Object>> queueReceive){ // this.queueReceive=queueReceive; // } @SuppressWarnings("rawtypes") @Override public void run() { try { DubboUbmsCallbackListener dubboUbmsCallbackListener=new DubboUbmsCallbackListener(queueReceive); CallbackService callbackService=(CallbackService)DubboContext.getInstance().getContext().getBean("ubmsCallbackService"); callbackService.addListener(dubboUbmsCallbackListener); while (true) { Map<String, Object> map=queueReceive.poll(); if (map!=null) { String operationType=map.get("operationType").toString(); Object object=map.get("value"); Class valueClass=(Class)map.get("class"); if (valueClass==DeptInfoDto.class) { DubboDeptInfoServiceInvoke.getInstance().updateDeptInfoDtos(operationType, (DeptInfoDto)object); }else if (valueClass==PersonInfoDto.class) { DubboPerserInfoServiceInvoke.getInstance().updatePersonInfoDtos(operationType,(PersonInfoDto) object); } // switch (valueClass.getName()) { // case deptInfoDtoClassName: // DubboDeptInfoServiceInvoke.getInstance().updateDeptInfoDtos(operationType, (DeptInfoDto)map.get("value")); // break; // case "PersonInfoDto": // DubboPerserInfoServiceInvoke.getInstance().updatePersonInfoDtos(operationType,(PersonInfoDto) object); // default: // break; // } }else { Thread.sleep(100); } } } catch (Exception e) { e.printStackTrace(); } } }
回調接口的實現:
import java.util.HashMap; import java.util.Map; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import com.enjoyor.soa.traffic.api.ubms.service.CallbackListener; public class DubboUbmsCallbackListener implements CallbackListener { public BlockingQueue<Map<String, Object>> queueReceive = new LinkedBlockingQueue<Map<String,Object>>(); public DubboUbmsCallbackListener(BlockingQueue<Map<String, Object>> queueReceive){ this.queueReceive=queueReceive; } @Override public void update(String changeType, Object object, Class name) { try { Map<String, Object> map=new HashMap<String, Object>(); map.put("operationType", changeType); // map.put("classType", value); map.put("value", object); map.put("class", name); this.queueReceive.put(map); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
Ajax的callBack做用相似,在調用了後臺程序之後,繼續執行的操做。好比callBack:"callBackName" callBackName就至關於服務端的接口,能夠客戶端本身實現,否則就和success function同樣了。沒有實踐過,根本不能說懂,還有jsonp裏面的callback~
function rt(callback) {
if (typeof callback == "function") {
callback();
}
}
function callback(){
alert(2);
}
<
html
>
<
head
>
<
title
>回調函數(callback)</
title
>
<
script
language="javascript" type="text/javascript">
function a(callback)
{
alert("我是parent函數a!");
alert("調用回調函數");
callback();
}
function b(){
alert("我是回調函數b");
}
function c(){
alert("我是回調函數c");
}
function test()
{
a(b);
a(c);
}
</
script
>
</
head
>
<
body
>
<
h1
>學習js回調函數</
h1
>
<
button
onClick=test()>click me</
button
>
<
p
>應該能看到調用了兩個回調函數</
p
>
</
body
>
</
html
>