文章列表
- 从零开始搭建一个联网Android APP(一)—— 工具和基本概念介绍
- 从零开始搭建一个联网Android APP(二)—— 服务器端程序
- 从零开始搭建一个联网Android APP(三)—— Android端程序
本文源码
注:该工程有两个branch,master为离线版本,所有功能集成到Android端,便于使用;online为在线版本,适合喜欢折腾的人
注:本系列博客主要重点在于服务器端的程序开发、部署和Android端如何与服务器端通信,不涉及具体的Android开发内容。
程序介绍
服务器端编程使用的是python语言,涉及flask和sqlite3两个库,其中flask用于构建Web程序(获得并相应用户请求GET/POST),sqlite3用于操作数据库相关的内容。
库文件的安装与使用
1. Flask
一、前期环境配置
首先选择一款你喜欢的IDE或者编辑器,python的话个人推荐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)初始化
from flask import Flask
app = Flask(__name__)
(2)路由和视图函数
- 客户端(例如 Web 浏览器)把请求发送给 Web 服务器
- Web服务器再把请求发送给 Flask程序实例app
- app需要知道:对每个URL请求运行哪些代码,所以保存了一个URL到Python函数的映射关系。处理 URL 和函数之间关系的程序称为路由
在 Flask 程序中定义路由的最简便方式,是使用程序实例提供的 app.route 修饰器,把修饰的函数注册为路由。如:
@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)启动服务器
if __name__ == '__main__':
app.run(debug=True)
(4)把前面几节的拼起来就是一个完整的flask程序了
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
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)
- 增(关键词insert)
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");
- 删(关键词delete)
sql = "delete from Order1 where ID = 2"
c.execute(sql)
print('Delete recordsuccessfully')
conn.commit()
- 改(关键词update)
sql = "update Order1 set isFinish = ? where ID = ?"
c.execute(sql,('true',1))
print('Update record succesfully')
conn.commit()
- 查(关键词select)
c.execute('''select * from Order1 order by creatTime''')
result =c.fetchall()
for column in result:
print(column)
conn.close()
# select * 表示把整张表全部查询出来
关于更多SQLite3的知识可以:点击此处
程序编写
综上所述,我们可以新建两个文件,分别为main.py
和sql.py
,其中main里面写flask的路由函数,sql里面写后端的数据库函数
其中一个标准的flask接口函数为
GET模式:
@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模式:
# 新增订单
@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的源代码在服务器端重新编译生成(虽然麻烦,但是和服务器更兼容)。
第一种方式就是小白教程,一句指令搞定,这里就不说了。
第二种方式可以参考这个博客。
注意一下不同的安装方法对应的启动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,可以参考该博客。
3. 运行flask程序
先进入工程所在目录,再使用以下指令运行代码。
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 主进程号(快速停止)
至此,服务器端代码的编写和部署就叙述完毕了,大家可以根据自己的需要进行修改。