2. 服务端项目搭建
进入服务器,安装各种包
sudo apt-get update # 更新相关源 sudo apt-get install git # 按照git # mysql的安装 sudo apt-get install mysql-server sudo apt-get install libmysqlclient-dev
进入数据库, 刚安装完成的数据库,root是空密码,所以要修改root的密码
mysql -uroot -p # 修改密码 use mysql; update user set authentication_string=password('新密码') where user='root' and Host ='localhost'; update user set plugin="mysql_native_password"; # 刷新权限 flush privileges;
创建数据库命令如下:
create database mogu charset=utf8mb4;
redis安装
sudo apt-get install redis-server
注意,redis安装完成以后,要观察redis是否启动了,如果没有启动,则参考之前redis笔记,启动redis。
# 查看是否启动redis-server,一般是没启动 # 原因是现在的云服务器基本都默认给redis配置一个IPV6的绑定地址。而我们大部分人的服务器是没使用IPV6的 ps -aux | grep redis # 如果没有启动,则运行以下命令,再查看是否启动成功,再不行,则查看下面 注意事项 redis-server /etc/redis/redis.conf
注意事项:给服务器开通redis的6379,你也可以把全部端口打开(腾讯云可以)
sudo apt install python3-pip
pip3 install virtualenv
pip3 install virtualenvwrapper
安装完成了以后,接下来需要配置系统环境变量
mkdir $HOME/.virtualenvs
执行命令,打开并编辑 ~/.bashrc
vim ~/.bashrc
文件末尾添加以下几行代码(注意最后一句命令,和我们本地的有所不同),:wq 保存退出。
export WORKON_HOME=$HOME/.virtualenvs export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3 source /usr/local/bin/virtualenvwrapper.sh
可以用一下操作查看到你的虚拟环境实际地址
whereis virtualenvwrapper # 查看地址 /home/ubuntu/.local/bin/virtualenvwrapper.sh
刷新配置文件
source ~/.bashrc
mkvirtualenv mogu -p python3
安装依赖模块
pip install flask==1.0.3 pip install pymysql==0.9.3 pip install redis==3.2.1 pip install flask-sqlalchemy==2.4.0 pip install flask-mysqldb==0.2.0 pip install flask-session==0.3.1 pip install flask-script==2.0.6 pip install flask-migrate==2.5.2
我们把项目搭建在/home/mogu目录下
cd /home mkdir moguapp cd moguapp # 创建flask项目启动文件manage.py vim manage.py
manage.py文件代码:
from flask import Flask app = Flask(__name__) @app.route('/') def index(): return 'hello,moluo~' if __name__ == '__main__': app.run(host="0.0.0.0")
在终端下使用python manage.py运行测试服务器
python manage.py
前面我们已经在云服务器控制台的网络安全组中添加5000端口,所以可以直接通过浏览器进行访问。
到码云上面,创建一个git仓库,把服务器代码上传到码云
git config --global user.name "mooluo" git config --global user.email "649641514@qq.com" git init git add . git commit -m "创建manage.py启动文件" git remote add origin https://gitee.com/mooluo/moguapp.git git push -u origin master
apt install tree
moguapp/ ├─ logs/ # 日志文件存储目录 ├─ apps/ # 项目主要逻辑业务代码保存目录 │ ├─ __init__.py # 项目初始化文件 │ ├─ modules/ # 保存项目中所有api模块的存储目录 │ │ ├─ common/ # 公共api接口目录 │ │ │ ├─ __init__.py # 公共api接口的初始化文件 │ │ │ ├─ models.py # 公共api接口的模型文件 │ │ │ └─ api.py # 公共api接口代码文件 │ │ └─ __init__.py | ├─ utils/ # 项目自定义封装工具包目录 | ├─ libs/ # 项目第三方工具包目录 | ├─ settings/ # 项目配置存储目录 │ │ ├─ dev.py # 开发阶段的配置文件 │ │ ├─ prop.py # 生产阶段的配置文件 │ │ └─ __init__.py │ └─ statics/ # 保存项目中所有的静态资源文件[img/css/js] └── manage.py # 项目的终端管理脚本文件
Config项目配置
在
import redis class Config(object): """项目配置信息""" # 设置密钥,可以通过 base64.b64encode(os.urandom(48)) 来生成一个指定长度的随机字符串 SECRET_KEY = "T1vEjTCjkGon5vU8C6Xq3ujNSQgHQje" # 配置日志 LOG_LEVEL = "DEBUG" # 调试模式 DEBUG = True # 数据库的配置信息 SQLALCHEMY_DATABASE_URI = "mysql://root:123456@127.0.0.1:3306/mogu?charset=utf8" SQLALCHEMY_TRACK_MODIFICATIONS = True SQLALCHEMY_ECHO = True # redis配置 REDIS_HOST = "127.0.0.1" REDIS_PORT = 6379 # session 配置 SESSION_TYPE = "redis" # 指定 session 保存到 redis 中 SESSION_USE_SIGNER = True # session_id 进行加密签名处理 SESSION_REDIS = redis.StrictRedis( host=REDIS_HOST, port=REDIS_PORT,db=1 ) PERMANENT_SESSION_LIFETIME = 24 * 60 * 60 # session 的有效期,单位是秒
from . import Config class DevelopementConfig(Config): """开发模式下的配置""" pass
from . import Config class ProductionConfig(Config): """生产模式下的配置""" DEBUG = False LOG_LEVEL = "INFO" SQLALCHEMY_TRACK_MODIFICATIONS = False SQLALCHEMY_ECHO = False
配置项目日志
把日志设置封装成一个函数init_log
,保存到utils/log.py
import logging from logging.handlers import RotatingFileHandler # 把日志相关的配置封装成一个日志初始化函数 def init_log(Config): # 设置日志的记录等级 logging.basicConfig(level=Config.LOG_LEVEL) # 调试debug级 # 创建日志记录器,指明日志保存的路径、每个日志文件的最大大小、保存的日志文件个数上限 file_log_handler = RotatingFileHandler("logs/log", maxBytes=1024 * 1024 * 300, backupCount=10) # 创建日志记录的格式 日志等级 输入日志信息的文件名 行数 日志信息 formatter = logging.Formatter('%(levelname)s %(filename)s:%(lineno)d %(message)s') # 为刚创建的日志记录器设置日志记录格式 file_log_handler.setFormatter(formatter) # 为全局的日志工具对象(flaskapp使用的)添加日志记录器 logging.getLogger().addHandler(file_log_handler)
项目初始化代码抽取
在apps/__init__.py
from flask import Flask from redis import StrictRedis from flask_session import Session from flask_sqlalchemy import SQLAlchemy from apps.settings.dev import DevelopementConfig from apps.settings.prop import ProductionConfig from apps.utils.log import init_log config = { "dev": DevelopementConfig, "prop": ProductionConfig, } # 预设全局变量 redis_store = None db = SQLAlchemy() def init_app(config_name): """项目的初始化功能""" app = Flask(__name__) # 设置配置类 Config = config[config_name] # 加载配置 app.config.from_object(Config) # redis的链接初始化 global redis_store redis_store = StrictRedis(host=Config.REDIS_HOST, port=Config.REDIS_PORT,db=0) # 开启session功能 Session(app) # 配置数据库链接 db.init_app(app) # 启动日志 init_log(Config) return app
配置项目启动文件
# coding=utf-8 from flask_script import Manager from flask_migrate import Migrate, MigrateCommand from apps import init_app,db app = init_app("dev") # 使用终端脚本工具启动和管理flask manager = Manager(app) # 启用数据迁移工具 Migrate(app, db) # 添加数据迁移的命令到终端脚本工具中 manager.add_command('db', MigrateCommand) @app.route('/') def index(): return 'hello,moluo~' if __name__ == '__main__': manager.run()
在虚拟环境重新使用manage.py启动项目
sudo pip install flask_script
sudo pip install flask_migrate
sudo easy_install redis
python manage.py runserver --host=0.0.0.0 --port=5000
4.
所谓的RPC,Re
mote Procedure Call
的简写,中文译作远程过程调用或者远程服务调用。
直观的理解就是,通过网络来请求服务,获取接口数据,而不用知晓底层网络协议的细节。
RPC
支持的格式很多,比如XML
格式,JSON
格式等等。最常用的肯定是json-rpc。
JSON-RPC协议中的客户端一般是为了向远程服务器请求执行某个方法/函数。客户端向实现了JSON-RPC协议的服务端发送请求,多个输入参数能够通过数组或者对象传递到远程方法,这个远程方法也能返回多个输出数据,具体是什么,当然要看具体的方法实现。
jsonrpc: 用来声明JSON-RPC协议的版本,现在基本固定为“2.0”
method,方法,是等待调用的远程方法名,字符串类型
params,参数,对象类型或者是数组,向远程方法传递的多个参数值
id,任意类型值,用于和最后的响应进行匹配,也就是这里设定多少,后面响应里这个值也设定为相同的
响应的接收者必须能够给出所有请求以正确的响应。这个值一般不能为Null,且为数字时不能有小数。
响应也有三个属性:
result,结果,是方法的返回值,调用方法出现错误时,必须不包含该成员。
error,错误,当出现错误时,返回一个特定的错误编码,如果没有错误产生,必须不包含该成员。
id,就是请求带的那个id值,必须与请求对象中的id成员的值相同。请求对象中的id时发生错误(如:转换错误或无效的请求),它必须为Null
当然,有一些场景下,是不用返回值的,比如只对客户端进行通知,由于不用对请求的id进行匹配,所以这个id就是不必要的,置空或者直接不要了。
git地址:https://github.com/cenobites/flask-jsonrpc
文档:
pip install Flask-JSONRPC==0.3.1
快速实现一个测试的RPC接口。
例如,我们直接在manage.py启动文件中直接实现。
from apps import init_app,db from flask_script import Manager from flask_migrate import Migrate, MigrateCommand from flask_jsonrpc import JSONRPC app = init_app("dev") # 使用终端脚本工具启动和管理flask manager = Manager(app) # 启用数据迁移工具 Migrate(app, db) # 添加数据迁移的命令到终端脚本工具中 manager.add_command('db', MigrateCommand) @app.route('/') def index(): return 'hello,moluo~' # 初始化jsonrpc模块 jsonrpc = JSONRPC(app, '/api') # 实现rpc接口 @jsonrpc.method('Common.index') def index(): return u'Welcome to Flask JSON-RPC' if __name__ == '__main__': manager.run()
客户端需要发起post请求,访问地址为:http://服务器地址:端口/api
默认情况下,/api
接口只能通过post请求访问。如果要使用jsonrpc提供的界面调试工具,则访问地址为:
http://服务器地址端口/api/browse/
访问数据格式应是:
{ "jsonrpc": "2.0", "method": "Common.index", "params": {}, "id": "1" }
通过postman访问效果:
对RPC接口代码进行模块化分离
apps/__init__py
,代码:
from flask import Flask from redis import StrictRedis from flask_session import Session from flask_sqlalchemy import SQLAlchemy from flask_jsonrpc import JSONRPC from apps.utils.log import init_log from apps.settings.dev import DevelopementConfig from apps.settings.prop import ProductionConfig config = { "dev": DevelopementConfig, "prop": ProductionConfig, } # 预设全局变量 redis_store = None db = SQLAlchemy() # 创建jsonrpc实例对象 jsonrpc = JSONRPC(app=None, service_url='/api', enable_web_browsable_api=True) def init_app(config_name): """项目的初始化功能""" app = Flask(__name__) # 设置配置类 Config = config[config_name] # 加载配置 app.config.from_object(Config) # redis的链接初始化 global redis_store redis_store = StrictRedis(host=Config.REDIS_HOST, port=Config.REDIS_PORT,db=0) # 开启session功能 Session(app) # 配置数据库链接 db.init_app(app) # 启动日志 init_log(Config) # jsonrpc注册到app应用对象中 jsonrpc.init_app(app) return app
modules/common/api.py,代码:
from apps import jsonrpc # 实现rpc接口 @jsonrpc.method('Common.index') def index(): return u'Welcome to Flask JSON-RPC'
manage.py启动文件中加载api接口
from apps import init_app,db from flask_script import Manager from flask_migrate import Migrate, MigrateCommand app = init_app("dev") # 使用终端脚本工具启动和管理flask manager = Manager(app) # 启用数据迁移工具 Migrate(app, db) # 添加数据迁移的命令到终端脚本工具中 manager.add_command('db', MigrateCommand) # api接口列表 from apps.modules.common import api @app.route('/') def index(): return 'hello,moluo~' if __name__ == '__main__': manager.run()
重新启动项目,使用postman进行还是原来的结果,则表示调整成功,后面的开发中,我们只需要不断增加对应的接口即可。
from apps import jsonrpc @jsonrpc.method("模块名.方法名(username=String, password=String)") def 方法名(username,password): return u"账号:%s,密码:%s" % (username,password)
客户端发送请求:
{ "jsonrpc": "2.0", "id": 188, "method": "Common.add", "params": { "username":"xiaohui", "age":33, "sex":false, "lve":["吃饭","睡觉",3,4,{"title":"aaaa"}], "son":{ "username":"xiaohuihui", "age":12 } } }
实现jsonrpc接口的版本迭代
apps/__init__
代码:
from flask import Flask from redis import StrictRedis from flask_session import Session from flask_sqlalchemy import SQLAlchemy from flask_jsonrpc import JSONRPC from flask_jsonrpc.site import JSONRPCSite from apps.settings.dev import DevelopementConfig from apps.settings.prop import ProductionConfig from apps.utils.log import init_log config = { "dev": DevelopementConfig, "prop": ProductionConfig, } # 预设全局变量 redis_store = None db = SQLAlchemy() # jsonrpc实例化 jsonrpc = JSONRPC(service_url="/api/v1", site=JSONRPCSite(), enable_web_browsable_api=True) jsonrpc_v2 = JSONRPC(service_url="/api/v2", site=JSONRPCSite(), enable_web_browsable_api=True) def init_app(config_name): 。。。。 # 启动日志 init_log(Config) # 把jsonrpc注入到app实例对象中 jsonrpc.init_app(app) jsonrpc2.init_app(app) return app
模块目录modules/common/api.py,代码:
from apps import jsonrpc,jsonrpc2 @jsonrpc.method("Common.add(username=String,age=Number,sex=Boolean,lve=Array,son=Object)") def add_v1(username,age,sex,lve,son): return "username=%s,age=%s,sex=%s,lve=%s,son=%s" % (username,age,sex,lve,son) @jsonrpc2.method("Common.add(username=String,age=Number,sex=Boolean,lve=Array,son=Object)") def add_v2(username,age,sex,lve,son): return u"账号=%s,年龄=%s,性别=%s,爱好=%s,后代=%s" % (username,age,sex,lve,son)
. |-- config.xml # app核心配置文件 |-- css/ # 公共css存储目录 | |-- api.css | `-- style.css |-- feature # 启动画面图片 |-- html/ # 页面/窗口的文件存储目录 |-- icon # 手机应用图标 |-- image/ # 静态图片存储目录 |-- index.html |-- launch # 启动画面图片 |-- res # 除了图片以外的其他文件 |-- script/ # javascript文件存储目录 | `-- api.js `-- wgt # app模块目录
欢迎页面
window APP的窗口
Frame 窗口里面的框架页面
FrameGroup 框架页面的组合
api.openWin({ name: 'page1', # window名字 url: './page1.html', # 页面地址,可以为本地文件路径,支持相对路径和绝对路径 pageParam: { # 页面参数,新页面中可以通过 api.pageParam 获取 name: 'test' } });