FlexとPyAMF間の通信でオブジェクトを使用する |
ベタに文字列データの通信を行うのではなく、オブジェクトデータの
やり取りを試してみます。
元ネタのサンプルURLはこちら。
server.py
http://pyamf.org/browser/examples/trunk/simple/python/server.py
SimpleView.as
http://pyamf.org/browser/examples/trunk/simple/flex/src/org/pyamf/examples/simple/SimpleView.as
User.as
http://pyamf.org/browser/examples/trunk/simple/flex/src/org/pyamf/examples/simple/User.as
こんなマイナーな記事を見る人は、うだうだ説明するよりソースの方が早いと思うので。
まず、サーバーとなるPythonのソース
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import logging
from wsgiref import simple_server
import pyamf
from pyamf import amf3
from pyamf.remoting.gateway.wsgi import WSGIGateway
class User(object):
"""
Flex <=> PyAMF間で共有するオブジェクトの定義
"""
def __init__(self, username=None, password=None, email=None):
self.username = username
self.password = password
self.email = email
class UserService(object):
"""
Userのリストを保持する。
get_userで、引数に該当するユーザーが存在する場合には
オブジェクトを返す
"""
def __init__(self, users):
self.users = users
def get_user(self, username):
"""
ユーザーの検索
※※※※※※※※※※※※※※※※※※※※※※
※※※このメソッドをFlex側から呼び出す※※※
※※※※※※※※※※※※※※※※※※※※※※
"""
try:
return self.users[username]
except KeyError:
return "Username '%s' not found" % username
def main():
#使用するクラス名の登録
amf3.use_proxies_default = True
#Flex側のUser.asで指定したRemoteClassのalias名と一致させる
pyamf.register_class(User, 'jp.exblog.fujishinko.examples.simple.User')
#サンプルデータを登録
users = {
u'坂本竜馬': User(u'坂本竜馬', 'pwd_sakamoto', 'sakamoto.ryoma@test.net'),
u'勝海舟': User(u'勝海舟', 'pwd_katsu', 'katsu.kaisyu@test.com'),
}
#my_remote_objという名前でサービスを登録する
services = {
'my_remote_obj': UserService(users)
}
# setup our server
gw = WSGIGateway(services, logger=logging)
httpd = simple_server.WSGIServer(
('サーバーのIP', 8000),
simple_server.WSGIRequestHandler)
httpd.set_app(gw)
print "Running Hello World AMF gateway on http://%s:%s" % httpd.server_address
try:
httpd.serve_forever()
except KeyboardInterrupt:
pass
if __name__ == '__main__':
main()
my_remote_objという名前で、UserServiceオブジェクトを登録します。
このmy_remote_objという名前でFlexからアクセスすることになります。
データのやり取りはUserオブジェクトで行います。
Pythonと同様の定義をFlex側でも行う必要があります。
User.as
package
{
[Bindable]
[RemoteClass(alias='jp.exblog.fujishinko.examples.simple.User')]
public class User
{
public var username : String;
public var password : String;
public var email : String;
public function User()
{
super();
}
}
}
RemoteClassのaliasにpyamf.register_classで指定した名称と同じ値を設定するのがミソ。
画面&通信ロジックのmxmlは以下の通り。
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<!-- RemoteObjectの定義 -->
<mx:RemoteObject id="remoteObj" destination="my_remote_obj" endpoint="http://サーバーIP:8000">
<mx:method name="get_user" result="onResult(event)" fault="onFault(event)"/>
</mx:RemoteObject>
<mx:Script>
<![CDATA[
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import mx.controls.Alert;
import mx.rpc.AbstractOperation;
//ボタンクリック時の処理
public function amf_call(): void {
// サーバー側に送信するデータ
remoteObj.get_user(user_name.text);
}
// 結果を受け取ったときの処理
private function onResult( re:ResultEvent ): void {
var user:User = re.result as User;
var msg:String = "";
if (user) {
msg += user.username + "\n";
msg += user.email + "\n";
msg += user.password;
} else {
msg += "変換失敗!\n";
msg += re.result.toString();
}
Alert.show(msg);
}
// エラー時の処理
private function onFault( fault:FaultEvent ): void {
var msg:String = "";
msg = "Remoting error: \n";
for ( var d:String in fault.fault ) {
msg += fault.fault[d] + "\n";
}
Alert.show(msg);
}
]]>
</mx:Script>
<mx:TextInput id="user_name" />
<mx:Button label="通信開始" click="amf_call()" />
</mx:Application>
テキストボックスに「坂本竜馬」や「勝海舟」と入力して検索してみます。