本文是小弟的技术文章处女作,由于个人水平和文字表达能力等原因,错误及不妥之处还望各位同行指点,我的主要目的是把自己的研究心得拿出来分享并使自己有一个总结的过程,高手们见笑了。
Buffalo是一个贯穿前后端的比较完整的Ajax框架,Buffalo最有价值之处,个人感觉有两点:
1、 后端实现了较为完整的基于xml的xml<->object序列化反序列化协议;
2、 前端提供了适配协议的调用封装和响应解析机制,并基于回调机制提供编码API。
这里先给大家详细介绍 buffalo2.0 中JAVA端如何根据 js 提交的请求XML报文来调用最合适的方法。先来看看JS通过buffalo
异步调用java方法的请求格式,比如我要调用 TestSum 类的 sum(double a,double b) 方法,比如我要调用 TestSum 类的 sum(double a,double b) 方法,参数值为1,2,那么在js中的写法是:
buffalo.remoteCall("TestSum.sum",[1,2], function(reply) { // 回调函数,这里buffalo是一个Buffalo对象 }
那么经过buffall.js 处理后的格式为:
1. url: contextPath/buffalo/TestSum ,其中 contenPath是工程路径,buffalo是一个Servlet,作用类似struts中的
ActionSerlvet,而 TestSum 就是类名,其实这只是一个 key ,buffalo 会根据 TestSum 这个 key 到配置文件
buffalo.properties 中查找匹配的类全限名. (其实是从缓存中的HashMap中取,因为buffalo会先读取配置到HashMap中并缓存在ServletContext中)这条配置类似这样 TestSum = com.test.TestSum
2. 方法名和参数经buffalo.js处理后为一XML格式,封装在 http 的请求体中提交到java端由buffalo解析,格式如下:
<buffalo-call>
<method>sum</method> // 这是要调用的方法
<double>1</double> // 之后的都是参数,这里表示有两个参数,均为double,一个值为1,一个为2
<double>2</double>
</buffalo-call>
知道了请求格式,那么接下来就来看看JAVA部分对请求流和URL的处理,是如何解析并调用正确的JAVA方法的。由于本文关注的是如何根据解析出的类名,方法名,参数类型,参数值来调用最合适的方法,所以 buffalo 中较为复杂的部分,即 如何解析 xml,完成 js 到 java 对象的转换这一步将放到下一篇文章中进行介绍,这次只需要知道xml格式的请求信息通过buffalo解析后返回一个BuffaloCall对象,该对象其实就是对方法名,方法参数类型,方法参数值的封装,源码如下:
public class BuffaloCall {
private String methodName; // 方法名,对应例子中的 sum
private Object[] arguments; //方法参数值的集合,对应例子中的 1 , 2
private Class[] argumentTypes; // 方法参数类型的集合,对应例子中的 java.lang.Double , java.lang.Double
public BuffaloCall(String methodName, Object[] arguments) {
this.methodName = methodName;
this.arguments = arguments;
Class[] types = new Class[this.arguments.length];
for (int i = 0; i < arguments.length; i++) {
types[i] = arguments[i].getClass();
}
this.argumentTypes = types;
}
其余的 getter,setter, toString()方法我就不贴出来了,到此,前台的请求信息全部被封装在 BuffalCall对象之中了,大
家可以对比下BuffaloCall类和<buffalo-call>,其实BuffaloCall对象就是对这段xml信息的封装,只不过相应的js类型已经被转
换为JAVA类型了,接下来进入本次主题的核心代码讲解。
如果我们得到一个类的 Class 对象,那么我们就可以通过反射机制来获取其所有方法,如果知道了要调用的方法名,那么我
们就可以通过 Method 的invoke 反射调用该方法,但是有一个问题,如果遇到重载的方法呢 ? 比如 TestSum 类中出现了多个重载且参数个数相同的 sum() 方法sum(int a,int b) ,sum(double a,double b), sum(int a,double b),sum(int[] a,int[] b) 等等类似这样的,我们来看看 buffalo 中是如何根据方法参数的匹配权重来获取最合适的调用方法。
private Map methodCache = new HashMap();
/* service就是通过反射创建的请求对象,这里就是 TestSum对象;
call 就是上面说到的封装了请求方法,参数值,参数类型的BuffaloCall对象;
signature 这里可以先看做为一个 HashMap的 key 对象,因为buffalo会将本次请求的方法缓存在HashMap中,如果下次同样请求调用这个方法,就不用重复查找了,因为反射会降低效率嘛
*/
private Method lookupMethod(Object service, BuffaloCall call,
Signature signature) {
Method[] methods = service.getClass().getMethods(); //取得调用对象(这里为TestSum)的所有方法集合
List matchedResults = new ArrayList(); // 这个List存储所有和请求方法同名的方法对象
for (int i = 0; i < methods.length; i++) { // 循环调用对象的每个方法
Method method = methods[i];
// 对与请求方法同名的做进一步操作
if (method.getName().equals(call.getMethodName())) {
Class[] parameterTypes = method.getParameterTypes(); // 获取方法的参数类型集合
int matched = 0, weight = 0;
//如果方法参数个数与请求方法的参数个数相同,则进一步操作
if (parameterTypes.length == call.getArguments().length) {
for (int j = 0; j < parameterTypes.length; j++) {
// 循环获取方法的每个参数类型的匹配权重并累加在变量 weight 中
int matchWeight = parameterAssignable(
parameterTypes[j], call.getArguments()[j].getClass());
if (matchWeight > 0) {
matched++; //参数每匹配成功一次,就递增 matched
weight += matchWeight;
}
}
}
// 如果参数都匹配成功的话,就将这个方法对象和权重封装到对象 MatchedResult中去
if (matched == parameterTypes.length) {
matchedResults.add(new MatchedResult(weight, method));
}
}
}
if (matchedResults.size() == 0) { // 没有匹配的方法,返回 null
return null;
} else if (matchedResults.size() == 1) { // 只有一个匹配则先缓存结果然后直接返回匹配的Method对象
methodCache.put(signature, ((MatchedResult) matchedResults.get(0))
.getMethod());
return ((MatchedResult) matchedResults.get(0)).getMethod();
} else {
/* 存在多个匹配的方法,那么根据前面计算的权重排序,权重最高者为最精确匹配的方法,MatchedResult实
现了Comparable 接口,覆盖了 compareTo方法,该方法根据 权重大小 weight 进行比较判断
*/
Collections.sort(matchedResults);
// 经过排序后,matchedResults这个List中的第一个MatchedResult元素就包含了最精确匹配的
// Method字段,所以这里就取第一个MatchedResult元素的Method缓存起来并返回。
methodCache.put(signature, ((MatchedResult) matchedResults.get(0)).getMethod());
return ((MatchedResult) matchedResults.get(0)).getMethod();
}
}
private int parameterAssignable(Class targetType, Class sourceType) {
if (targetType.equals(sourceType)) return 6; //如果类型相等,匹配度为6
if (targetType.isAssignableFrom(sourceType)) return 5; //目标参数类型是请求参数类型的超类或超接口,为5
if (targetType.isPrimitive()) { //如果是primitive,则获取Wrapper类
targetType = ClassUtil.getWrapperClass(targetType);
}
if (targetType.equals(sourceType)) {
return 4; //此时肯定是经过处理的匹配,只能为4
} else if (Number.class.isAssignableFrom(targetType) &&
Number.class.isAssignableFrom(sourceType)) {
return 3; //如果两边都是Number型的,马虎匹配了,为3
}
return 0; //0就是没啥匹配度了
}
到此为止,已经找到了最精确匹配的方法了,之后就是通过反射来调用这个方法。在调用这个方法之前buffalo还有做一些其
他处理,但和本文的主题没啥关系,且和解析xml有关,所以这里就先不讲了。
本文介绍的虽然不算复杂,但我觉得其处理思路还是值得借鉴的,下一章将介绍 buffalo 最核心的部分即对请求报文
xml的解析并转换为正确的java类型部分,这里涉及的知识点和类很多,需要我好好整理段时间,其中模板方法模式涉及较多,且
我将绘制些 uml静态图和时序图辅助,所以请不熟悉的这些基础知道的朋友先了解些模板方法模式的运用场景和uml基础。
如果我发觉自己哪里写的不对需要改进,我会及时更新本文的,有兴趣的朋友可以关注下。
分享到:
相关推荐
在IT行业中,`buffalo-l` 和 `buffalo-sc` 是两个特定的软件包,它们可能涉及特定的开发框架或工具。尽管提供的信息有限,但我们可以根据这些关键词推测出一些可能的知识点。以下是对这两个包的详细解释以及与之相关...
在没有"Party Buffalo硬盘管理"这类工具之前,用户可能需要通过复杂的过程来转移或备份这些数据。而该软件则简化了这一过程,通过专用的数据线连接PC和XBOX360,使得数据迁移变得轻松且安全。 使用"Party Buffalo...
例如,`buffalo.js`可能是一个封装了与服务器通信的库,使得前端能够轻松调用服务端API。 3. 使用方法: - 下载完成后,你需要将这些jar文件添加到项目的类路径(ClassPath)中,这通常在IDE如Eclipse或IntelliJ ...
buffalo1.2ajax框架应用演示例子 buffalo1.2下载地址: http://www.codechina.net/resource/html/2005-12/06/119641.html
本文将深入探讨InsightFace的核心概念,并以"buffalo-l.zip"为例,解析其内部结构与使用方法。 InsightFace的工作原理基于深度学习模型,特别是卷积神经网络(CNN)。它通过训练大规模的人脸数据集,学习人脸特征...
Buffalo 提供了一种结构化的方法来组织你的Go应用,包括路由、模型、控制器、数据库连接等。通过“HelloWorld”,我们可以预期该示例将展示如何设置一个新的 Buffalo 项目,如何创建一个简单的路由,以及如何编写一...
在IT行业中,"buffalo.jar & buffalo.js" 提到的两个文件名可能指的是某个软件或框架的组件。这里,我们分别来探讨它们可能涉及的知识点。 首先,`buffalo.jar` 是一个Java Archive (JAR) 文件,它是Java平台的标准...
Buffalo是一个J2EE轻量级AJAX框架,也是国内著名的开源项目。它与DWR 和JSON-RPC一样,着眼于Web远程调用(Web Remoting),其简洁而实用的特性一直以来深受开发者喜爱。 Buffalo2.0最大的特点在于其性能的提升,还有...
Buffalo是Go语言中的一款强大的Web开发框架,它简化了构建现代、健壮且可维护的Web应用程序的过程。本篇文章将深入探讨`buffalo`应用实例,通过一系列实践技巧,帮助开发者更好地理解和运用这个框架。 首先,理解`...
【标题】:“buffalo tftpboot.zip”是一个用于恢复 Buffalo ...以上就是关于“buffalo tftpboot.zip”压缩包及其中涉及的技术点的详细介绍。在处理类似问题时,遵循正确的步骤和使用正确的工具是成功恢复设备的关键。
下面将详细介绍这个实现过程中的关键知识点。 1. **Buffalo框架**:Buffalo是一个轻量级的Java服务框架,它提供了一种简单的方式来处理HTTP请求和服务。在这个例子中,`BuffaloCheck` 类继承自 `BuffaloService`,...
- **Buffalo应用Servlet**:定义了一个名为`bfapp`的Servlet,并将其映射到URL模式`/bfapp/*`,这使得所有匹配该模式的请求都将由`ApplicationServlet`处理。 #### 2.2 `applicationContext-buffalo.xml`配置示例 ...
《Buffalo NAS用户手册》是针对巴比禄(Buffalo)公司TeraStation系列网络附加存储设备(NAS)的一份详尽的操作与设置指南。该手册涵盖了TS-XHL、TS-XL、TS-XEL、TS-WXL以及TS-RXL系列产品的设定参数与功能介绍,为...
本文将围绕"buffalo_l.zip"中的内容,详细解析InsightFace的核心概念、技术框架,以及如何结合PyTorch和ONNX进行实现和部署。 1. InsightFace概述: InsightFace由MXNet框架开发,但现在也支持PyTorch,这大大拓宽...
Buffalo中定义了Web远程调用的传输基础,并且将远程调用对象完整的序列化到了本地,成为可以被JavaScript编程触及的对象。Buffalo中的重要组件-BuffaloBinding,提供了将JavaScript对象绑定到HTML元素的能力。这种...
《Xbox360硬盘管理:Party Buffalo及源代码解析》 在电子游戏领域,微软的Xbox360是一款备受玩家喜爱的游戏主机。而针对Xbox360的硬盘管理,尤其是 Party Buffalo 项目,为用户提供了更高效、便捷的操作体验。本文...
在本文中,我们将深入探讨`buffalo`框架的核心概念、功能特性以及它如何与`Ajax`相比较,同时还会简要介绍如何使用`buffalo`进行实际的开发工作。 首先,让我们理解一下`Ajax`(Asynchronous JavaScript and XML)。`...
xbox硬盘连接电脑必用软件,可传输所有数据。