JSON-RPC
前言
RPC(Remote Procedure Call),远程过程调用,是一个分布式系统间通信的必备技术,使用protobuf、thrift、hessian、xml、json等序列化方式序列化数据,使用tcp或http等传输协议传输数据。
简介
json-rpc是基于json的跨语言远程调用协议,使用json作为序列化方式。json-rpc比xml-rpc、webservice等基于文本的协议传输数据小;相对hessian、java-rpc等二进制协议便于调试、实现、扩展,是非常优秀的一种远程调用协议。目前主流语言都已有json-rpc的实现框架,java语言中较好的json-rpc实现框架有jsonrpc4j、jpoxy、json-rpc。三者之中jsonrpc4j既可独立使用,又可与spring无缝集合,比较适合于基于spring的项目开发。
请求数据格式
{
"method": "sayHello",
"params": ["Hello JSON-RPC"],
"id": 1
}
参数说明:
method
:调用的方法名params
:方法传入的参数,若无参数则传入 []
id
:调用标识符,用于标示一次远程调用过程
返回数据格式
{
"result": "Hello JSON-RPC",
"error": null,
"id": 1
}
返回值说明:
result
: 方法返回值,若无返回值,则返回null。若调用错误,返回null。error
: 调用时错误,无错误返回null。id
: 调用标识符,与调用方传入的标识符一致。
示例
下面的例子使用jsonrpc4j和springboot演示对两个数求和。
定义一个Request对象,用来接收参数。
public class CalcReq implements Serializable {
private int a;
private int b;
public int getA() {
return a;
}
public void setA(int a) {
this.a = a;
}
public int getB() {
return b;
}
public void setB(int b) {
this.b = b;
}
}
定义一个Service,用来实现两个数相加的逻辑
@Service
public class CalculateService {
public int add(CalcReq req) {
return req.getA() + req.getB();
}
}
定义一个controller用来接收http请求
@Controller
public class CalculateController implements InitializingBean {
@Autowired
private CalculateService calculateService;
private JsonRpcServer jsonRpcServer;
@RequestMapping("/add")
public void add(HttpServletRequest req, HttpServletResponse res) throws IOException {
jsonRpcServer.handle(req, res);
}
@Override
public void afterPropertiesSet() throws Exception {
jsonRpcServer = new JsonRpcServer(calculateService);
}
}
- 创建一个JsonRpcServer对象,将service对象作为这个JsonRpcServer对象的handler。
- 将请求转发给JsonRpcServer处理
启动项目,使用curl发送请求:
➜ ~ curl -i -H 'content-type: application/json' -X POST -d '{"jsonrpc": "2.0", "method": "sub", "params":[{"a": 1, "b": 2}], "id": 1}' 'http://127.0.0.1:8080/add'
得到响应:
HTTP/1.1 200
Content-Type: application/json-rpc
Content-Length: 36
Date: Sat, 25 Aug 2018 06:49:09 GMT
{"jsonrpc":"2.0","id":1,"result":3}
jsonrpc4j和springboot
在上面的例子中,JsonRpcServer是在controller中创建的。实际上jsonrpc4j提供了AutoJsonRpcServiceImplExporter
可以简化代码的编写。
创建JsonRpcService
@JsonRpcService("/calc")
public interface ExampleServerApi {
int multiplier(@JsonRpcParam(value = "a") int a, @JsonRpcParam(value = "b") int b);
}
创建实现类
@Service
@AutoJsonRpcServiceImpl
public class ExampleServerApiImpl implements ExampleServerApi {
@Override
public int multiplier(int a, int b) {
return a * b;
}
}
创建ServiceExporter
@Configuration
public class ApplicationConfig {
@Bean
public static AutoJsonRpcServiceImplExporter autoJsonRpcServiceImplExporter() {
AutoJsonRpcServiceImplExporter exp = new AutoJsonRpcServiceImplExporter();
//in here you can provide custom HTTP status code providers etc. eg:
//exp.setHttpStatusCodeProvider();
//exp.setErrorResolver();
return exp;
}
}
启动项目,发送请求:
➜ ~ curl -i -H 'content-type: application/json' -X POST -d '{"jsonrpc": "2.0", "method": "multiplier", "params":{"a": 3, "b": 2}, "id": 1}' 'http://127.0.0.1:8080/calc'
返回响应:
HTTP/1.1 200
Content-Type: application/json-rpc
Content-Length: 36
Date: Sat, 25 Aug 2018 07:28:25 GMT
{"jsonrpc":"2.0","id":1,"result":6}