第一:它的应用场景是什么?
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
>