之前使用java做接口测试,均使用HttpClient来进行,今次遇到一个新的项目使用python的odoo框架开发,其接口和之前的网站稍有不同,导致在前台看到的接口返回内容和之前的差别很大,一般的restful接口在控制台里是这样的:
而现项目的控制台显示如下:
这种参数用通用的HttpClient就不好进行接口下发了,这只是个比较简单的参数,实际上args里还有可能包含字符串列表等类型,故采用JSONRPC的java版进行接口下发就比较方便;
json-rpc是基于json的跨语言远程调用协议,比xml-rpc、webservice等基于文本的协议传输数据格小;相对hessian、java-rpc等二进制协议便于调试、实现、扩展,是非常优秀的一种远程调用协议。目前主流语言都已有json-rpc的实现框架,java语言中较好的json-rpc实现框架有jsonrpc4j、jpoxy、json-rpc。三者之中jsonrpc4j既可独立使用,又可与spring无缝集合,比较适合于基于spring的项目开发。
son-rpc协议非常简单,发起远程调用时向服务端传输数据格式如下:
{ "method": "sayHello", "params": ["Hello JSON-RPC"], "id": 1}
参数说明:
服务器其收到调用请求,处理方法调用,将方法效用结果效应给调用方;返回数据格式:
{
"result":"Hello JSON-RPC",
"error": null,
"id": 1
}
参数说明:
JSON-RPC的java版配置比httpClient要简单很多,不需要管理连接、连接池、关闭返回等等,甚至连下发方式都略掉了。
maven地址
源码地址
这里jsonrpc就一个包,另外一个用于json字符串处理;
<dependency>
<groupId>com.github.briandilley.jsonrpc4jgroupId>
<artifactId>jsonrpc4jartifactId>
<version>1.5.2version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>fastjsonartifactId>
<version>1.2.41version>
dependency>
jsonrpc工具类代码如下
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.googlecode.jsonrpc4j.JsonRpcHttpClient;
public class JsonRpcUtil {
private static final Logger log = LoggerFactory.getLogger(JsonRpcUtil.class);
public static final String RPC_ACTION = "method";
/**
* 单例模式
*/
private static JsonRpcUtil rpcUtil=new JsonRpcUtil();
/**获得工具实例
* @return
*/
public static JsonRpcUtil getRpcUtil() {
return rpcUtil;
}
private JsonRpcHttpClient rpcClient;
/**设置headper
* @param url
* @param headers
* @return
* @throws MalformedURLException
*/
public JsonRpcUtil setHeaders(String url, Map<String, String> headers) throws MalformedURLException {
rpcClient = new JsonRpcHttpClient(new URL(url));
if (null != headers && headers.size() > 0)
{
rpcClient.setHeaders(headers);
}
return this;
}
/**远程调用
* @param action
* @param argument
* @param returnClass
* @return
* @throws Throwable
*/
public <T> T execute(String action, Object argument, Class<T> returnClass) throws Throwable {
return this.rpcClient.invoke(action, argument, returnClass);
}
/**
* 远程过程调用
*
* @param url 接口url
* @param headers 要加入的header
* @param argument 此处为浏览器控制台里参数里的params的值
* @param returnClass 返回值类型
* @return
* @throws MalformedURLException
* @throws Throwable
*/
public <T> T rpcExecute(String url, Map<String, String> headers, Object argument, Class<T> returnClass)
throws MalformedURLException, Throwable {
try {
return JsonRpcUtil.getRpcUtil().setHeaders(url, headers).execute(RPC_ACTION, argument, returnClass);
} finally {
log.debug("api url:" + url);
log.debug("api header:" + JsonUtil.ParseJson(headers));
log.debug("api params:" + JsonUtil.ParseJson(argument));
//this.clearParas();
}
}
}
json处理工具类:
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.parser.Feature;
public class JsonUtil {
public static String ParseJson(Object obj) {
return JSON.toJSONString(obj);
}
public static <T> T parseObject(String json,Class<T> clas) {
return (T)JSON.parseObject(json, clas) ;
}
public static <T> T parseObject(String json, TypeReference<T> type, Feature... features){
return (T)JSON.parseObject(json, type,features) ;
}
}
调用的时候需要取控制台里的Request URL
作为参数url
的值传入;取Request Payload
中params的值使用json转换为Object
作为工具调用里的agument
传入(或者也可以转换为Map
),headers
依然为Map
,按需要传入即可,至于第四个参数returnClass
,则根据具体返回的值的类型来定义,可以为Map.class
,或者List.class
等,如果不知道则直接传入Object.class
即可,返回值根据这个参数来定义;
如下是个简单的调用范例:
public static void main(String[] args)
{
String url = "http://127.0.0.1:8080/web/test";
String param = "{ \"method\": \"sayHello\", \"args\": [\"Hello JSON-RPC\"]}";
Map<String,Object> returnValue = JsonRpcUtil.rpcExecute(url,null,JsonUtil.parseObject(param,Object.class),Map.class);
}