第一:它的应用场景是什么?

if you call me ,i will call back。目前我接触到两种需要回调的需求

1、系统管理平台登录,登录所需要的人员和部门数据都是在另一个基础信息系统中。当基础信息中人员或者部门信息改变的时候,如果不通知其他系统,尤其是系统管理系统这种对于核心数据很关键的系统会造成数据不同步的问题,所以当基础信息中的数据增删改的时候就要通知其他系统。

2、小红小明做算术题,小明需要小红算数做作业,老婆婆需要小红算数算账,调用的都是小红计算器,小红接着调用特定的接口,小明和老婆婆各自不同实现。服务端提供一种公用的方法,但是各个客户端调用的时候有较小的差异,那么公用的方法放在服务端使用,存在差异的部分放在服务端自己实现。

(参考文章:http://blog.csdn.net/qq_30983519/article/details/52537613)

第二:它的实现原理是什么?

CallBack回调机制,它的本质是服务端调用客户端的逻辑,形式是服务端提供接口,而由客户端按照自己的需求具体实现。客户端先调用服务端的服务,服务端处理后再调用客户端逻辑。

第三:它的实现方式是什么?

第一个例子是计算器:

小红希望以后继续向小明提供计算服务,同时还能向老婆婆提供算账服务,甚至以后能够拓展其他人的业务,于是她向所有的顾客约定了一个办法,用于统一的处理,也就是自己需要的操作数和做完计算之后应该怎么做。这个统一的方法,小红做成了一个接口,提供给了大家,代码如下:

public interface doJob
{
public void fillBlank(int a, int b, int result);
}

同时,小红修改了自己的计算器,使其可以同时处理不同的实现了doJob接口的人,代码如下:

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>
懂了,就是把函数当作参数传进去了,callback的具体叫什么没关系,如果不用call()。

CallBack实践。的更多相关文章

  1. Atitit.http httpclient实践java c# .net php attilax总结

    Atitit.http httpclient实践java c# .net php attilax总结 1. Navtree>> net .http1 2. Httpclient理论1 2. ...

  2. RESTful API 设计最佳实践

    背景 目前互联网上充斥着大量的关于RESTful API(为了方便,以后API和RESTful API 一个意思)如何设计的文章,然而却没有一个"万能"的设计标准:如何鉴权?API ...

  3. Thrift简单实践

    0.什么是RPC RPC(Remote Procedure Call - 远程过程调用),是通过网络从远程计算机上请求服务,而不需要了解底层网路技术的细节.简单点说,就是像调用本地服务(方法)一样调用 ...

  4. 高性能javascript学习笔记系列(5) -快速响应的用户界面和编程实践

    参考高性能javascript 理解浏览器UI线程  用于执行javascript和更新用户界面的进程通常被称为浏览器UI线程  UI线程的工作机制可以理解为一个简单的队列系统,队列中的任务按顺序执行 ...

  5. ReactiveCocoa代码实践之-更多思考

    三.ReactiveCocoa代码实践之-更多思考 1. RACObserve()宏形参写法的区别 之前写代码考虑过 RACObserve(self.timeLabel , text) 和 RACOb ...

  6. 【PC网站前端架构探讨系列】关于中小型PC网站前端架构方案的讨论与实践

    目   录 1.遇到的问题 2.目标 3.探讨 4.架构设想 5.流程 6.初步实现 7.存在问题 8.最后 遇到的问题 我在这个系列上篇文章 已经讲解并开始逐步应用模块化思想,不知大家还记不记得,题 ...

  7. Android单元测试实践

    为什么要写单元测试 首先要介绍为什么蘑菇街支付金融这边会采用单元测试的实践.说起来比较巧,刚开始的时候,只是我一个人会写单元测试.后来老板们知道了,觉得这是件 很有价值的事情,于是就叫我负责我们组的单 ...

  8. Ubuntu14.04+RabbitMQ3.6.3+Golang的最佳实践

    目录 [TOC] 1.RabbitMQ介绍 1.1.什么是RabbitMQ?   RabbitMQ 是由 LShift 提供的一个 Advanced Message Queuing Protocol ...

  9. NodeJS 错误处理最佳实践

    NodeJS的错误处理让人痛苦,在很长的一段时间里,大量的错误被放任不管.但是要想建立一个健壮的Node.js程序就必须正确的处理这些错误,而且这并不难学.如果你实在没有耐心,那就直接绕过长篇大论跳到 ...

随机推荐

  1. Page-encoding specified in XML prolog (UTF-8) is different from that specified in page directive (utf-8)

    org.apache.jasper.JasperException:xxx.jsp(1,1) Page-encoding specified in XML prolog (UTF-8) is diff ...

  2. C# 正则表达式匹配汉字

    ; Regex P_regex = new Regex("^[\u4E00-\u9FA5]{0,}$"); ;i < txt_str.Text.Length; i++) { ...

  3. [深入浅出WP8.1(Runtime)]Windows Phone 8.1和Silverlight 8.1的区别

    1.2.2 Windows Phone 8.1应用程序模型 Windows Phone 8.1支持多种开发语言来开发应用程序,包括C#.VB.JavaScript和C++,那么本书的代码主要是采用C# ...

  4. BZOJ1090: [SCOI2003]字符串折叠

    区间dp. 一种是分段dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]); 一种是这一段可以缩写dp[i][j]=min(dp[i][j],dp[i][l]+2+ca ...

  5. ZeroMQ接口函数之 :zmq_getsockopt – 获取ZMQ socket的属性

    ZeroMQ API 目录 :http://www.cnblogs.com/fengbohello/p/4230135.html 本文地址 :http://www.cnblogs.com/fengbo ...

  6. html 之input标签height设置问题

    今天针对这个问题纠结了很久 <input type="button" value="xx" style="height:99px;" ...

  7. BZOJ3687 计算子集和的异或和

    题不知道怎么不见了,bzoj上已经没了3687这题了 题意:给你一个n 然后输入n个数 求这n个数的所有子集的和的异或和 思路:用bitset记录某个数是否在子集和中出现,利用bitset对二进制位的 ...

  8. 【python+mysql】在python中调用mysql出问题 ImportError: No module named MySQLdb.constants

    遇到如下异常: File "C:\Users\Neil\PycharmProjects\ScrapyDouban\book\book\database.py", line 4, i ...

  9. javascript平时例子⑩(表情发送)

    <!DOCTYPE html><html> <head> <meta charset="utf-8" /> <title> ...

  10. MySQL 事务

    MySQL 事务主要用于处理操作量大,复杂度高的数据.比如说,在人员管理系统中,你删除一个人员,你即需要删除人员的基本资料,也要删除和该人员相关的信息,如信箱,文章等等,这样,这些数据库操作语句就构成 ...