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程序就必须正确的处理这些错误,而且这并不难学.如果你实在没有耐心,那就直接绕过长篇大论跳到 ...
随机推荐
- VS2010 有关测试的一些使用
Visual Studio 2010 单元测试之一---普通单元测试:http://blog.csdn.net/tjvictor/archive/2011/02/09/6175362.aspx V ...
- Tastypie 学习笔记
Tastypie是什么? 运行于Python环境中的 Django web服务器下的 Restful 风格API接口 (python 类库) 1.安装下面环境或者依赖包到python库(安装过程类似 ...
- HDU 3032 Nim or not Nim?(sg函数)
题目链接 暴力出来,竟然眼花了以为sg(i) = i啊....看表要认真啊!!! #include <cstdio> #include <cstring> #include & ...
- mongoVUE的增删改查操作使用说明
mongoVUE的增删改查操作使用说明 一. 查询 1. 精确查询 1)右键点击集合名,再左键点击Find 或者直接点击工具栏上的Find 2)查询界面,包括四个区域 {Find}区,查询条件格式{& ...
- MySQL查询语句(select)详解(2)
7.子查询 当进行查询的时候,需要的条件是另外一个select语句的结果,这时候就要用到子查询 用于子查询的主要关键字有:in,not in,=,!=,exists,not exists等. 以下两张 ...
- php摇杆Tiger摇奖
先说下整体思路,代码已附下方. 1.递归产生一个非中奖数(即非连续数字:'111','222','333','444','555','666','777','888') 2.点击摇奖,把奖项通过设置的 ...
- WPF整理-为User Control添加依赖属性
依赖属性 ".NET properties are nothing more than syntactic sugar over set and get methods." 我们知 ...
- final阶段成员贡献分
项目名:连连看 组名:天天向上 组长:王森 组员:张政.张金生.林莉.胡丽娜 final阶段各组员的贡献分分配如下: 姓名 个人工作量 组长评价 个人评价 团队贡献总分 张政 11 7 6 6.00 ...
- Servlet异步上传文件
这里需要用到插件ajaxfileupload.js,jar包:commons-fileupload-1.3.2.jar,commons-io-2.5.jar 注意红色部分的字!!!! 1.创建一个we ...
- android的程序运行数据存放在哪里?
Android应用开发中,给我们提供了5种数据的存储方式1 使用SharedPreferences存储数据2 文件存储数据3 SQLite数据库存储数据4 使用ContentProvider存储数据5 ...