CallBack实践。
第一:它的应用场景是什么?
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实践。的更多相关文章
- Atitit.http httpclient实践java c# .net php attilax总结
Atitit.http httpclient实践java c# .net php attilax总结 1. Navtree>> net .http1 2. Httpclient理论1 2. ...
- RESTful API 设计最佳实践
背景 目前互联网上充斥着大量的关于RESTful API(为了方便,以后API和RESTful API 一个意思)如何设计的文章,然而却没有一个"万能"的设计标准:如何鉴权?API ...
- Thrift简单实践
0.什么是RPC RPC(Remote Procedure Call - 远程过程调用),是通过网络从远程计算机上请求服务,而不需要了解底层网路技术的细节.简单点说,就是像调用本地服务(方法)一样调用 ...
- 高性能javascript学习笔记系列(5) -快速响应的用户界面和编程实践
参考高性能javascript 理解浏览器UI线程 用于执行javascript和更新用户界面的进程通常被称为浏览器UI线程 UI线程的工作机制可以理解为一个简单的队列系统,队列中的任务按顺序执行 ...
- ReactiveCocoa代码实践之-更多思考
三.ReactiveCocoa代码实践之-更多思考 1. RACObserve()宏形参写法的区别 之前写代码考虑过 RACObserve(self.timeLabel , text) 和 RACOb ...
- 【PC网站前端架构探讨系列】关于中小型PC网站前端架构方案的讨论与实践
目 录 1.遇到的问题 2.目标 3.探讨 4.架构设想 5.流程 6.初步实现 7.存在问题 8.最后 遇到的问题 我在这个系列上篇文章 已经讲解并开始逐步应用模块化思想,不知大家还记不记得,题 ...
- Android单元测试实践
为什么要写单元测试 首先要介绍为什么蘑菇街支付金融这边会采用单元测试的实践.说起来比较巧,刚开始的时候,只是我一个人会写单元测试.后来老板们知道了,觉得这是件 很有价值的事情,于是就叫我负责我们组的单 ...
- Ubuntu14.04+RabbitMQ3.6.3+Golang的最佳实践
目录 [TOC] 1.RabbitMQ介绍 1.1.什么是RabbitMQ? RabbitMQ 是由 LShift 提供的一个 Advanced Message Queuing Protocol ...
- NodeJS 错误处理最佳实践
NodeJS的错误处理让人痛苦,在很长的一段时间里,大量的错误被放任不管.但是要想建立一个健壮的Node.js程序就必须正确的处理这些错误,而且这并不难学.如果你实在没有耐心,那就直接绕过长篇大论跳到 ...
随机推荐
- CSS3动画里的过渡效果
过渡效果中有: 1平滑效果 2线性过渡 3由慢到快 4由快到慢 5慢-快-慢 等等 具体参考 w3chool 例如: <body> <div class="out&quo ...
- CustomEvent自定义事件
javascript与HTML之间的交互是通过事件来实现的.事件,就是文档或浏览器窗口发生的一些特定的交互瞬间.通常大家都会认为事件是在用户与浏览器进行交互的时候触发的,其实通过javascript我 ...
- Linux之head、tail、grep、cut等命令详解
http://jingyan.baidu.com/article/5225f26b6ab230e6fa0908be.html
- 如何使用的Ue4自带的SQLiteSupport
在UE4.6版本加入的模块.可以让开发者使用SQLite数据库.SQlite是个轻量型的本地数据库. 我下面就来介绍一下如何使用这个模块. 第一步:下载SQLite源代码以及SQLite GUI管理工 ...
- Linux下定时任务配置-crontab
实际中经常有一些任务需要定期执行,人工操作比较麻烦,如果定时执行将会省去很多人力,还可以在一些资源占用不多的时间段执行,linux下crontab命令就实现了这一便捷的功能,实现脚本的自动化运行. 常 ...
- VBA 获取Sheet最大行
compared all possibilities with a long test sheet: 0,140625 sec for lastrow = calcws.Cells.Find(&quo ...
- HDU-1171 Big Event in HDU
Big Event in HDU Problem Description Nowadays, we all know that Computer College is the biggest depa ...
- 【Cocos2d-x游戏开发】Cocos2d-x中的弱联网技术
在上一篇博客中,我们一起学习了如何在Cocos2d-x中存储数据和读取信息,本篇博客我们将一起讨论和数据存储同样重要的联网技术. 一.弱联网技术介绍 在网络游戏中许多重要的功能都需要网络连接,而根据需 ...
- VR技术驱动智慧旅游,自由漫步西湖不是梦
虚拟现实技术是今年最热门的科技之一,不少行业都在嫁接VR功能,其中旅游业也具备这方面的优势.VR+旅游,能让你足不出户即可感受清净唯美的名胜古迹.据591ARVR资讯网www.591arvr ...
- Qt Visual Studio Add-in 导出的 .pri 怎么用?
今天咱们介绍一下 Qt Add-in 导出的 pri 文件怎么用. 一般需要导出这个文件, 主要应该是跨平台编译的需求, 所以这个文件里包含的东西会比较少, 咱们看下导出的文件是什么样子的: # ...