Flutter JSON-RPC通信插件jsonrpc2的使用
Flutter JSON-RPC通信插件jsonrpc2的使用
jsonrpc2
此包是一组纯 Dart 工具类和方法,用于在 Dart 中实现 JSON-RPC 客户端和服务器。你需要提供实际的通信协议。文档、示例和测试均已提供。
JSON-RPC 是一种 JSON 编码语法,用于调用远程服务器上的方法并接收响应。该规范位于 https://jsonrpc.org。
使用
JSON-RPC 被分为客户端和服务器的责任。此包实现了 JSON-RPC 2.0 规范中繁琐的部分,并为服务器提供了 1.0 的回退支持。
客户端
与规范一样,客户端实现不指定客户端的传输细节。需要创建一个从 ServerProxyBase
扩展的类,以实际发送方法请求并接收响应。请参阅示例以了解常见用法,或查看以下步骤说明。
实例化后,客户端代理可以使用代理的 call
方法调用服务器上的方法,并接收响应。客户端有责任匹配服务器的 API。
Future<dynamic> call(String method, [dynamic params])
proxy.call('method_a')
// 没有参数proxy.call('method_b', [arg1])
// 一个参数,通用情况proxy.call('method_c', arg1)
// 一个参数,参数既不是[]
也不是{}
proxy.call('method_d', [arg1, arg2, arg3])
// 多个参数proxy.call('method_e', [[item1, item2, item3, item4]])
// 一个参数,参数是[]
proxy.call('method_f', [{'a': 'hello', 'b': 'world'}])
// 一个参数,参数是{}
proxy.call('method_g', {'name_a':value_a,'name_b':value_b})
// 命名参数
创建一个客户端(ServerProxy)类
- 导入客户端库。
import 'package:jsonrpc2/jsonrpc2.dart';
import 'package:rpc_exceptions/rpc_exceptions.dart';
- 创建一个从
ServerProxyBase
扩展的服务器代理类,并初始化服务器资源。resource
可能在transmit
方法中使用。
class MyServerProxy extends ServerProxyBase {
/// 构造函数。如果你想要扩展它,请正确地使用 `super`
MyServerProxy(resource) // resource 可以是任何东西
: super(resource);
}
- 在你的服务器代理类中重写
transmit
方法,该方法发送一个字符串到远程 JSON-RPC 服务器并返回返回的字符串。你可以使用之前标识的服务器资源。
/// 返回一个包含 JSON-RPC 响应的 Future。使用真实的传输方式,
/// 如 `package:http` 而不是虚构的 `ExampleTransport`。
@override
Future<String> transmit(String package) async {
// 例如,使用字符串资源名称创建一个传输对象。
var transport = ExampleTransport(resource);
// 使用传输发送包,并等待响应
var response = await transport.send(package);
// 返回字符串响应以进行进一步处理
return response;
}
- 使用你的服务器代理实例来调用该端点上的方法,并处理结果。
/// 获取服务器列表中紧跟在该项目后面的那个项目
MyViewItem nextItem (String lastItemId) async {
var remoteSite = MyServerProxy('https://example.org/');
var item = await remoteSite.call('nextItem', lastItemId);
// 或者,如果你在代理中镜像了服务器 API,
// var nextItem = await remoteSite.nextItem(lastItemId); // 非常好!
return MyViewItem.fromJson(item);
}
示例 JSON-RPC 客户端使用 http.dart
来自 pub.dev
// 使用 http.dart 包的 JSON-RPC 客户端
import 'package:http/http.dart' as http;
class HttpServerProxy extends ServerProxyBase {
final String url;
HttpServerProxy(this.url);
@override
Future<String> transmit(String package) async {
var response = await http.post(
Uri.parse(url),
headers: {"Content-Type": "application/json"},
body: package,
);
return response.body;
}
}
客户端通知
JSON-RPC 支持通知的概念。通知是一种在不期望响应的情况下调用远程服务器上的方法的方式。
通过使用 notify
而不是 call
来调用客户端(或服务器代理)上的远程方法。
void notify(String method, [dynamic params])
JSON-RPC 规范要求通知没有响应。一些传输方式,如 HTTP,总是返回响应。你可以在服务器代理的覆盖 transmit
方法中适当地处理这种情况。对于 HTTP,我的示例从服务器返回空字符串或 204 状态码,而服务器代理返回空字符串。无论如何,ServerProxyBase
的 notify
方法不会返回任何内容。
批量请求
JSON-RPC V2 支持将多个方法请求批量到一个传输请求中。
为了在客户端上支持这一点,在创建你的客户端(服务器代理)类之后,执行以下操作:
- 使用你的客户端
ServerProxy
类作为实例代理创建一个客户端BatchServerProxy
类。
/// 查看 [BatchServerProxyBase] 文档
class MyBatchServerProxy extends BatchServerProxyBase {
@override
dynamic proxy;
/// 构造函数
MyBatchServerProxy(String url, [customHeaders = const <String, String>{}]) {
proxy = MyServerProxy(url, customHeaders);
}
}
- 使用你的
BatchServerProxy
类,像使用普通代理一样调用任意数量的方法。然后作为批处理发送这些方法。
/// 调用一些方法以返回三个项目
List threeItems () async {
var remoteSite = MyBatchServerProxy('https://example.org/');
var item1 = remoteSite.call('firstItem');
var item2 = remoteSite.call('secondItem');
remoteSite.notify('happyLog', 'I hope the last item comes through!');
var item3 = remoteSite.call('lastItem');
// 或者,如果你在代理中镜像了服务器 API,
// var item1 = remoteSite.item1(); // ...等等。
// 现在,向服务器发送请求。
await remoteSite.send();
// 现在处理来自调用的 Futures。
return [fromJson(await item1), fromJson(await item2), fromJson(await item3)]
}
服务器基础
服务器库解码 JSON-RPC 请求包,并允许将 JSON-RPC 请求与调用远程方法的对象关联起来,并返回结果。网络和传输问题不在此实现的范围内。也就是说,这设计得相当容易与你使用的传输或框架一起使用。这只是使用调度器的一个方法。在服务器实现中,为特定调度器创建一个端点,并使用这些工具解码请求并打包结果。
此服务器实现使用调度器概念。本质上,调度器是一个包含要在一个端点上调用的远程方法的实例化的类。服务器接受一个调用请求,解构 JSON,然后创建或关联一个调度器以调用该实例上的方法,使用请求的参数。返回值(或异常)被组装成一个 JSON 响应并发送回客户端。
- 导入服务器库
import 'package:jsonrpc2/jsonrpc2.dart';
- 创建一个实现端点服务方法的类。几乎任何带有方法的类都可以。
example/api_class.dart
,如果在不同的文件中,导入它。
import 'rpc_methods.dart';
- 为您的监听器创建一个方法,该方法接受来自客户端的 JSON-RPC 字符串。这个字符串可能,例如,是 HTTP POST 的主体。在这个方法内,使用这个库的
jsonRpc
方法将字符串与Dispatcher
关联起来,后者执行方法。jsonRpc
方法最终会生成一个字符串,应该将其作为响应发送回客户端。
jsonRpc
方法具有以下签名。
Future<String> jsonRpc(String request, Dispatcher dispatcher)
-
request
是来自客户端的 JSON-RPC 请求字符串。 -
dispatcher
满足Dispatcher 接口
。你会想要使用以下之一:mirror_dispatcher
reflector_dispatcher
这两个实现等效工作。mirror_dispatcher
更易于使用,但它使用 dart:mirrors
,不能在 Flutter 应用程序中使用。可能还有其他权衡。
示例服务器使用 shelf_io
和 mirror_dispatcher
import 'package:jsonrpc2/jsonrpc2.dart';
import 'package:mirror_dispatcher/mirror_dispatcher.dart';
class MyService {
String firstMethod() => "Hello, World!";
}
void main() {
var dispatcher = new MethodMirrorDispatcher(MyService());
var handler = createHandler(dispatcher);
runServer(handler);
}
示例服务器使用 shelf_io
和 reflector_dispatcher
import 'package:jsonrpc2/jsonrpc2.dart';
import 'package:reflector_dispatcher/reflector_dispatcher.dart';
class MyService {
String firstMethod() => "Hello, World!";
}
void main() {
var dispatcher = new ReflectorDispatcher(MyService());
var handler = createHandler(dispatcher);
runServer(handler);
}
更多关于Flutter JSON-RPC通信插件jsonrpc2的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter JSON-RPC通信插件jsonrpc2的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
在Flutter中,使用jsonrpc2
插件进行JSON-RPC通信可以让我们与基于JSON-RPC协议的服务器进行交互。以下是一个简单的示例,展示了如何在Flutter项目中使用jsonrpc2
插件来进行JSON-RPC通信。
首先,确保你的Flutter项目中已经添加了jsonrpc2
依赖。在你的pubspec.yaml
文件中添加以下依赖:
dependencies:
flutter:
sdk: flutter
jsonrpc2: ^3.0.0 # 请根据最新版本调整版本号
然后运行flutter pub get
来安装依赖。
接下来,我们编写一个Flutter应用,它使用jsonrpc2
客户端与JSON-RPC服务器进行通信。假设我们有一个JSON-RPC服务器运行在http://localhost:8545
(这通常是以太坊JSON-RPC节点的默认地址,但你可以根据实际情况替换)。
以下是一个简单的Flutter应用示例:
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:jsonrpc2/jsonrpc2.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter JSON-RPC Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String responseText = '';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter JSON-RPC Demo'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Response:',
),
Text(
responseText,
style: TextStyle(fontSize: 20),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () async {
await sendRpcRequest();
},
child: Text('Send RPC Request'),
),
],
),
),
);
}
Future<void> sendRpcRequest() async {
final client = JsonRpcClient(
'http://localhost:8545',
client: http.Client(),
);
try {
final request = Request('web3_clientVersion', []);
final response = await client.send(request);
if (response is SuccessResponse) {
setState(() {
responseText = 'Client Version: ${response.result}';
});
} else if (response is ErrorResponse) {
setState(() {
responseText = 'Error: ${response.error.message} (code: ${response.error.code})';
});
}
} catch (e) {
setState(() {
responseText = 'Exception: $e';
});
} finally {
client.close();
}
}
}
在这个示例中,我们做了以下几件事:
- 添加依赖:在
pubspec.yaml
文件中添加了jsonrpc2
依赖。 - 创建Flutter应用:使用
MaterialApp
和Scaffold
等Flutter组件创建了一个简单的UI。 - 定义RPC客户端:在
sendRpcRequest
方法中,我们创建了一个JsonRpcClient
实例,用于与JSON-RPC服务器通信。 - 发送RPC请求:构造了一个
Request
对象,并使用client.send(request)
方法发送请求。然后,我们根据响应的类型(SuccessResponse
或ErrorResponse
)更新UI。 - 处理异常和关闭客户端:在
try-catch
块中处理可能的异常,并在finally
块中关闭客户端连接。
这个示例展示了如何使用jsonrpc2
插件在Flutter中与JSON-RPC服务器进行基本的通信。你可以根据需要扩展这个示例,以处理更多的RPC方法和复杂的请求/响应结构。