Kewei
首页·Home
留言·Message
关于·About
搜索
从零开始搭建一个联网小程序(二)—— 服务器端程序
2019年07月29日 20:22:43
548
0
0
文章分类:
Android
Flask
## 文章列表 1. [从零开始搭建一个联网Android APP(一)—— 工具和基本概念介绍](https://xkw168.github.io/2019/05/25/%E4%BB%8E%E9%9B%B6%E5%BC%80%E5%A7%8B%E6%90%AD%E5%BB%BA%E4%B8%80%E4%B8%AA%E8%81%94%E7%BD%91%E5%B0%8F%E7%A8%8B%E5%BA%8F-%E4%B8%80-%E5%B7%A5%E5%85%B7%E5%92%8C%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5%E4%BB%8B%E7%BB%8D.html) 2. [从零开始搭建一个联网Android APP(二)—— 服务器端程序](https://xkw168.github.io/2019/05/25/%E4%BB%8E%E9%9B%B6%E5%BC%80%E5%A7%8B%E6%90%AD%E5%BB%BA%E4%B8%80%E4%B8%AA%E8%81%94%E7%BD%91%E5%B0%8F%E7%A8%8B%E5%BA%8F-%E4%BA%8C-%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%AB%AF%E7%A8%8B%E5%BA%8F.html) 3. [从零开始搭建一个联网Android APP(三)—— Android端程序](https://xkw168.github.io/2019/05/25/%E4%BB%8E%E9%9B%B6%E5%BC%80%E5%A7%8B%E6%90%AD%E5%BB%BA%E4%B8%80%E4%B8%AA%E8%81%94%E7%BD%91%E5%B0%8F%E7%A8%8B%E5%BA%8F-%E4%B8%89-Android%E7%AB%AF%E7%A8%8B%E5%BA%8F.html) 本文[源码](https://github.com/xkw168/account_book/tree/online) 注:该工程有两个branch,master为[离线版本](https://github.com/xkw168/account_book/releases),所有功能集成到Android端,便于使用;online为在线版本,适合喜欢折腾的人 注:本系列博客主要重点在于服务器端的程序开发、部署和Android端如何与服务器端通信,不涉及具体的Android开发内容。 --- ## 程序介绍   服务器端编程使用的是python语言,涉及flask和sqlite3两个库,其中flask用于构建Web程序(获得并相应用户请求GET/POST),sqlite3用于操作数据库相关的内容。 --- ## 库文件的安装与使用 ### 1. Flask #### 一、前期环境配置   首先选择一款你喜欢的IDE或者编辑器,python的话个人推荐[PyCharm](https://www.jetbrains.com/pycharm/),和Android Studio都是JetBrain出产的,界面很相似,两者直接基本无缝切换,而且也很好用。   因为sqlite3是python自带的一款轻量级数据库,所以我们只需要安装flask即可。安装 flask 最便捷的方式是使用虚拟环境(virtual environment)。 win+R并输入cmd打开命令提示符,利用cd指令转到工程目录,并输入 `virtualenv env #创建名为env的虚拟环境` 然后利用 ``` cd env/Scripts activate #激活虚拟环境 ``` mac下可用如下指令激活 ``` source env/bin/activate ``` 如下图,当命令行前面出现(env)的时候就证明虚拟环境成功激活,然后就可以在虚拟环境里面安装flask了。  ``` pip install flask #安装flask ```  前期的环境配置就大功告成了,然后就可以开始写代码了。 #### 二、Flask程序介绍 (1)初始化 ```python from flask import Flask app = Flask(__name__) ``` (2)路由和视图函数 - 客户端(例如 Web 浏览器)把请求发送给 Web 服务器 - Web服务器再把请求发送给 **Flask程序实例**app - app需要知道:对每个URL请求运行哪些代码,所以保存了一个URL到Python函数的映射关系。处理 URL 和函数之间关系的程序称为路由   在 Flask 程序中定义路由的最简便方式,是使用程序实例提供的 app.route 修饰器,把修饰的函数注册为路由。如: ```python @app.route('/') def index(): return'Hello Flask!' 还可以在路由里面定义动态部分,如: @app.route('/<name>') def hello(name): return'Hello ' + name + ' !' ```   尖括号中的内容就是动态部分,任何能匹配静态部分的URL都会映射到这个路由上。路由中的动态部分默认使用字符串,不过也可使用类型定义。例如,路由`/user/<int:id>`只会匹配动态片段id为整数的URL。Flask 支持在路由中使用int、float和path类型。(path类型也是字符串,但不把斜线视作分隔符,而将其当作动态片段的一部分)调用视图函数时,Flask会将动态部分作为参数传入函数。 注:修饰器是Python语言的标准特性,可以使用不同的方式修改函数的行为。惯常用法是使用修饰器把函数注册为事件的处理程序 (3)启动服务器 ```python if __name__ == '__main__': app.run(debug=True) ``` (4)把前面几节的拼起来就是一个完整的flask程序了 ```python from flask import Flask app = Flask(__name__) @app.route('/') def index(): return'Hello Flask!' @app.route('/<name>') def hello(name): return'Hello ' + name + ' !' if __name__ == '__main__': app.run(debug=True) ``` 运行后如下:  浏览器访问http://127.0.0.1:5000/  浏览器访问http://127.0.0.1:5000/whu  ### 2. sqlite3简介   sqlite3是一款python自带的轻量级数据库,支持传统的SQL语法。 (1)建表   注意**Order为SQL的关键字,所以建表的时候表名不能是Order**,但是数据库文件名字可以是Order ```python import sqlite3 conn = sqlite3.connect('Order.db'); c = conn.cursor(); print("Openeddatabase successfully"); sql = '''CREATE TABLE Order1 (ID integer PRIMARY KEY autoincrement, name TEXT NOT NULL, serialNumber TEXT NOT NULL, creatTime TEXT NOT NULL, count integer NOT NULL, isFinish integer );''' c.execute(sql) print ("Tablecreated successfully"); conn.commit() conn.close() ```   创建完之后用软件(DB Browser forSQLite)打开Order.db,可以看到成功创建了表Order1 (2)增删改查(CRUD:creat,retrieve,update,delete) 1. 增(关键词insert) ```python sql = '''insert into Order1 (name, serialNumber, creatTime,count, isFinish) values(?, ?, ?, ?, ?)''' c.execute(sql,(u'测试订单', 'test666', '2018-4-2', 1000, False)) conn.commit() print ("Records created successfully"); ``` 2. 删(关键词delete) ```python sql = "delete from Order1 where ID = 2" c.execute(sql) print('Delete recordsuccessfully') conn.commit() ``` 3. 改(关键词update) ```python sql = "update Order1 set isFinish = ? where ID = ?" c.execute(sql,('true',1)) print('Update record succesfully') conn.commit() ``` 4. 查(关键词select) ```python c.execute('''select * from Order1 order by creatTime''') result =c.fetchall() for column in result: print(column) conn.close() # select * 表示把整张表全部查询出来 ``` 关于更多SQLite3的知识可以:点击[此处](https://www.runoob.com/sqlite/sqlite-python.html) --- ## 程序编写   综上所述,我们可以新建两个文件,分别为`main.py`和`sql.py`,其中main里面写flask的路由函数,sql里面写后端的数据库函数   其中一个标准的flask接口函数为 GET模式: ```python @app.route('/queryAllAccount/<offset>/<limit>', methods=['GET']) def query_all_account(offset, limit): accounts = query_all_account_info(int(offset), int(limit)) response = {"accounts": accounts} return json.dumps(response, indent=4, default=json_default, ensure_ascii=False) ``` 这里解释一下,`@app.route('/queryAllAccount/<offset>/<limit>', methods=['GET'])`就说明了这个接口的调用方法是GET,而且URL格式为`http://你的服务器地址/queryAllAccount/参数1/参数2`,指定参数的格式可以通过`<int:offset>`的形式。 声明函数的时候,参数数量一定要和URL里面的一致且命名保持统一,随后函数内部就正常使用参数 POST模式: ```python # 新增订单 @app.route('/addAccount', methods=['POST']) def add_account(): content = request.form.get('content') number = request.form.get('number') person = request.form.get('person') create_time = request.form.get('createTime') account = Account(account_id=0, content=content, number=number, create_time=create_time, person=person) if add_new_account(account): return jsonify({'statue': 'successful'}) else: return jsonify({'statue': 'failure'}) ``` 这里解释一下`@app.route('/addAccount', methods=['POST'])`就说明了这个接口的调用方法为POST,URL内不含参数,参数都在body内,此时函数本身也不含参数没需要在函数内部通过`request.form.get('参数的key')`的形式获得参数。(client端是以键值对的形式添加的参数) --- ## 程序部署   这里以腾讯云服务器,基于CentOS的系统为例介绍程序的部署。   服务器端配置使用了gunicorn和nginx,其中gunicorn用于运行Python程序,nginx用于反向代理(缓冲请求和相应)。 ### 1. 安装准备 #### 1.1 安装python   注意我们使用的是python3,可以在服务器里面输入`python -V`或者`python --version`来查看python版本,很多服务器都默认安装了python2.7版本,这时候我们需要另外安装python3,这里就不详细赘述了(可以上网查找详细资料)。 #### 1.2 安装flask - 首先安装虚拟环境virtualenv(`pip install virtualenv`)(可以通过`pip list`查看可安装的内容) - 然后进入工程目录并创建虚拟环境(`virtualenv env #创建一个名为env的虚拟环境`) - 激活虚拟环境(`source env/bin/activate`) - 安装flask(`pip install flask`) #### 1.3 安装Nginx 安装Nginx有两种方式可以选择: 一是直接`yum install nginx`(省事); 二是下载Nginx的源代码在服务器端重新编译生成(虽然麻烦,但是和服务器更兼容)。 第一种方式就是小白教程,一句指令搞定,这里就不说了。 第二种方式可以参考这个[博客](https://blog.csdn.net/jiangeeq/article/details/70144319)。   注意一下不同的安装方法对应的启动Nginx方法也不一样,通过yum install安装的可以直接使用指令`service nginx start`启动,自己编译的需要到nginx的目录下(可以使用`whereis nginx`定位目录)再`./nginx`启动。 #### 1.4 安装gunicorn 进入工程目录,激活虚拟环境,然后 ``` pip install gunicorn ``` ### 2. 加载flask程序   有两种方法可以将本地的python(flask)程序上传至云端。 - 方案一:使用WinSCP直接把.py文件拷贝到服务器对应位置 - 方案二:利用git 下面分别介绍这两种方法(假设云端的工程路径为root/test): #### 2.1 WinSCP    打开WinSCP,文件协议选择SFTP,主机名输入云端服务器的公网IP地址(注意一定要是公网),端口号选择22,用户名和密码不同服务器的默认用户名不同(也可以根据自己需要新建一个用户)。    成功登陆远程服务器之后找到对应的工程目录,左边是我们电脑的本地文件,右边是服务器的文件。直接把.py文件拖拽至右端即可。(FileZilla使用方式类似) #### 2.2 git 服务器一般都安装好了git,我们可以直接使用git进行版本管理。 在本地电脑开发好之后,push上去,然后登录服务器pull下来。 如果不会使用git,可以参考该[博客](https://www.liaoxuefeng.com/wiki/896043488029600)。 ### 3. 运行flask程序   先进入工程所在目录,再使用以下指令运行代码。 ```shell gunicorn -D -w 4 -b localhost:8080 HelloFlask:app ``` 说明: -D:表示后台运行 -w 4:表示开启四个线程(效率会高一点,可以根据自己服务器情况决定) -b localhost:8080:表示ip和端口,这里采用本机访问,方便nginx代理 最后面的HelloFlask表示程序名称,app为全局变量`app = Flask(__name__)`   启动完后,可以通过指令`pstree -ap|grep gunicorn`查看gunicorn树。可以看到,成功开启了四个线程,主线程号为11027。至此,我们的代码已经在服务器上面愉快的跑起来了。    现在用浏览器测试一下,会发现显示找不到网页,因为此时我们的程序只在服务器的本地上运行(前面写了运行在本地端口),所以在其他机器是无法访问的,这时候就需要nginx进行一个请求的转发。 ### 4. 部署nginx反向代理   安装完nginx之后,到`user/local/nginx/conf`路径下,找到`nginx.conf`文件,修改其中的配置信息。(可以直接在服务器修改,也可以使用前面介绍的方法先下载到本地修改完后再同步到服务器端)   这里我采用下载到本地修改。找到关键代码段,这里的意思就是监听80端口,并将80端口的请求转发给8080端口(也就是我们前面gunicorn运行的那个端口)。listen填写要监听的端口号(Http协议默认为80,也可以填写其他端口,但是主要需要去**腾讯云-控制台-安全组**,开放对应的端口),server_name填写服务器的公网IP,proxy_pass填写上一步gunicorn运行的地址。  配置好之后,启动nginx,浏览器访问服务器地址,可以发现已经成功了。 ### 5. 服务器端常用指令 #### 5.1 列出所有正在运行的端口 ``` netstat -ntlp ```  可以看到端口80由nginx监听,端口8080是我们的python程序 #### 5.2 操作文件(其实可以用WinSCP替代) ``` mkdir dir1 创建 'dir1' 目录 rm -f file1 删除 'file1' rm -rf dir1 删除 'dir1' 目录及其子目录内容 ``` #### 5.3 安装文件 ``` yum install *** ``` #### 5.4 重启gunicorn(代码修改后需要) 首先`pstree -ap|grep gunicorn`查看gunicorn树 然后`kill -HUP 6264`即可关闭gunicorn(6264为gunicorn的主进程号) 最后`gunicorn -D -w 4 -b 127.0.0.1:8080 HelloFlask:app`重新运行程序 #### 5.5 重启nginx ``` /usr/local/nginx/sbin -s stop /usr/local/nginx/sbin/nginx ``` (不行的话`ps -ef|grep nginx`看线程,然后`kill -HUP` 主进程号强制关闭) ``` kill -HUP 主进程号(平滑重启) kill -QUIT 主进程号(从容停止) kill -TERM 主进程号(快速停止) ``` ---   至此,服务器端代码的编写和部署就叙述完毕了,大家可以根据自己的需要进行修改。
点赞
0
分享