react-native 实现的移动客户端支持 安卓和苹果手机
NodeJs + Express + MySQL 实现的Restful API后端数据服务接口
需要的组件全部安装完毕后,我们可以看看package.json文件的内容,尤其是版本信息
{
"name": "zigoo",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start",
"test": "jest"
},
"dependencies": {
"body-parser": "^1.18.2",
"express": "^4.16.3",
"mysqli": "^2.2.2",
"react": "^16.3.0-alpha.1",
"react-native": "0.54.3"
},
"devDependencies": {
"babel-jest": "22.4.3",
"babel-preset-react-native": "4.0.0",
"jest": "22.4.3",
"react-test-renderer": "^16.3.0-alpha.1"
},
"jest": {
"preset": "react-native"
}
}
项目文件的层次结构
将MySQL启动服务的目录配置成全局路径:
myths-Mac:~ myth$ pwd
/Users/myth
你忘记了MySQL数据库的root密码
首先在Mac OS系统中关掉MySQL服务程序 步骤是:System Preferences ---> MySQL ---> Stop MySQL Server
myths-Mac:~ myth$ sudo su
Password: 123 登录 Mac OS系统的密码
你必须要修改数据库的编码 默认是拉丁文编码 我们需要的是utf-8编码,不这个干 你的中文数据肯定存储的是乱码:
sh-3.2# cat > /etc/my.cnf
# Example MySQL config file for small systems.
#
# This is for a system with little memory (<= 64M) where MySQL is only used
# from time to time and it's important that the mysqld daemon
# doesn't use much resources.
#
# MySQL programs look for option files in a set of
# locations which depend on the deployment platform.
# You can copy this option file to one of those
# locations. For information about these locations, see:
# http://dev.mysql.com/doc/mysql/en/option-files.html
#
# In this file, you can use all long options that a program supports.
# If you want to know which options a program supports, run the program
# with the "--help" option.
# The following options will be passed to all MySQL clients
[client]
default-character-set=utf8
#password = your_password
port = 3306
socket = /tmp/mysql.sock
# Here follows entries for some specific programs
# The MySQL server
[mysqld]
default-storage-engine=INNODB
character-set-server=utf8
collation-server=utf8_general_ci
port = 3306
socket = /tmp/mysql.sock
skip-external-locking
key_buffer_size = 16K
max_allowed_packet = 1M
table_open_cache = 4
sort_buffer_size = 64K
read_buffer_size = 256K
read_rnd_buffer_size = 256K
net_buffer_length = 2K
thread_stack = 128K
# Don't listen on a TCP/IP port at all. This can be a security enhancement,
# if all processes that need to connect to mysqld run on the same host.
# All interaction with mysqld must be made via Unix sockets or named pipes.
# Note that using this option without enabling named pipes on Windows
# (using the "enable-named-pipe" option) will render mysqld useless!
#
#skip-networking
server-id = 1
# Uncomment the following if you want to log updates
#log-bin=mysql-bin
# binary logging format - mixed recommended
#binlog_format=mixed
# Causes updates to non-transactional engines using statement format to be
# written directly to binary log. Before using this option make sure that
# there are no dependencies between transactional and non-transactional
# tables such as in the statement INSERT INTO t_myisam SELECT * FROM
# t_innodb; otherwise, slaves may diverge from the master.
#binlog_direct_non_transactional_updates=TRUE
# Uncomment the following if you are using InnoDB tables
#innodb_data_home_dir = /usr/local/mysql/data
#innodb_data_file_path = ibdata1:10M:autoextend
#innodb_log_group_home_dir = /usr/local/mysql/data
# You can set .._buffer_pool_size up to 50 - 80 %
# of RAM but beware of setting memory usage too high
#innodb_buffer_pool_size = 16M
#innodb_additional_mem_pool_size = 2M
# Set .._log_file_size to 25 % of buffer pool size
#innodb_log_file_size = 5M
#innodb_log_buffer_size = 8M
#innodb_flush_log_at_trx_commit = 1
#innodb_lock_wait_timeout = 50
[mysqldump]
quick
max_allowed_packet = 16M
[mysql]
no-auto-rehash
# Remove the next comment character if you are not familiar with SQL
#safe-updates
[myisamchk]
key_buffer_size = 8M
sort_buffer_size = 8M
[mysqlhotcopy]
interactive-timeout
开始跳过输入密码这步进入MySQL服务器:
sh-3.2# mysqld_safe --skip-grant-tables --skip-networking &
sh-3.2# mysql -uroot
mysql> use mysql
mysql> UPDATE user SET authentication_string=PASSWORD('!8@e21#tw') WHERE user='root';
mysql> quit
myths-Mac:~ myth$ mysql -uroot -p
回车输入密码 !8@e21#tw
mysql> use mysql --切换数据库失败不要慌张 它强行让你修改上面刚刚设置的密码 你改成裸奔的 123456 作为密码都不成问题
ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement.
mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123456';
Query OK, 0 rows affected (0.00 sec)
你想允许任一IP地址都可以远程去连接你的MySQL数据库服务器,不明白?其中有这样一种情况,你用自己实际的网卡IP去连接数据库是连不上的,我们可以接着执行一条如下的SQL语句即可,其中百分号表示任一IP地址均可访问本数据库服务器,像建立数据库同步账户,就需要这么干:
mysql> GRANT ALL ON *.* TO 'root'@'%' IDENTIFIED BY '123456';
mysql> FLUSH PRIVILEGES;
开始真正步入正题啦 :
创建数据库 mysql> CREATE DATABASE testdb;
创建users数据表:
mysql> CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
`email` varchar(30) DEFAULT NULL,
`mobile` varchar(30) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
创始化2条记录:
mysql> insert into users(`id`,`name`,`email`,`mobile`) values(1,'Jack','[email protected]','13570845544');
mysql> insert into users(`id`,`name`,`email`,`mobile`) values(2,'Jason','[email protected]','1380013800');
mysql> quit
我的苹果系统网卡地址是:192.168.123.47
myths-Mac:~ myth$
我们可以用SQLyog 这样的可视化客户端工具去操作苹果系统中的MySQL服务器了,没这个工具自己在网上随便下载一个
开始使用命令建立一个 react-native 项目:
myths-Mac:~ myth$ react-native init zigoo
myths-Mac:~ myth$ pwd
/Users/myth
myths-Mac:~ myth$ cd zigoo
myths-Mac:~ myth$ yarn add express
myths-Mac:~ myth$ yarn add mysqli
myths-Mac:~ myth$ yarn add body-parser
使用Android Studio 或者其它你喜欢的开发工具在App.js同一目录中建立一个空的server.js代码文件,你可以用命令查看一下:
myths-Mac:zigoo myth$ ls
App.js app.json ios server.js
__tests__ gen node_modules yarn.lock
android index.js package.json
myths-Mac:zigoo myth$ cat server.js
var express = require('express');
var app = express();
var mysql = require('mysql');
var bodyParser = require('body-parser');
app.use(bodyParser.json({type: 'application/json'}));
app.use(bodyParser.urlencoded({extended: true}));
var conn = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '123456',
database: 'testdb'
});
var server = app.listen(9090,function(){
var host = server.address().address
var port = server.address().port
console.log('server start')
});
conn.connect(function(error){
if(!!error) console.log('error');
else console.log('connected');
});
app.get('/users',function(req,res){
conn.query('SELECT * FROM users',function(error,rows,fields){
if(!!error) console.log('error');
else {
console.log(rows);
res.send(rows);
}
})
});
app.post('/users',function(req,res){
conn.query('INSERT INTO users SET ?',req.body,function(error,rows,fields){
if(!!error) console.log('error');
else {
console.log(req.body)
console.log(rows);
res.send(JSON.stringify(rows));
}
})
})
app.get('/users/:id',function(req,res){
conn.query('SELECT * FROM users WHERE id=?',req.params.id,function(error,rows,fields){
if(!!error) console.log('error');
else {
console.log(rows);
res.send(JSON.stringify(rows));
}
})
});
app.delete('/users/:id',function(req,res){
conn.query('DELETE FROM users WHERE id=?',req.params.id,function(error,rows,fields){
if(!!error) console.log('error');
else {
console.log(rows);
res.end('deleted successfully');
}
})
});
app.put('/users',function(req,res){
conn.query('UPDATE users SET name=?,email=?,mobile=? WHERE id=?',
[req.body.name,req.body.email,req.body.mobile,req.body.id],function(error,rows,fields){
if(!!error) console.log('error');
else {
console.log(req.body)
console.log(rows);
res.send(JSON.stringify(rows));
}
})
})
/*
启动方式
myths-Mac:zigoo myth$ node ./server.js
访问数据接口
http://localhost:9090/users
[{"id":1,"name":"Jack","emial":"[email protected]","mobile":"13570845544"},{"id":2,"name":"Jason","emial":"[email protected]","mobile":"1380013800"}]
*/
现在介绍如何用Postman工具来测试上面Restful API 数据操作接口
使用如下命令启动 (MySQL + NodeJs + Express)实现的服务器端服务程序:
$ cd /Users/myth/zigoo && node ./server.js
Restful API 测试工具Postman
(一). 获取所有用户的记录
Method
GET http://192.168.123.47:9090/users
Output Raw
[{"id":1,"name":"Jack","email":"[email protected]","mobile":"13570845544"},
{"id":2,"name":"Jason","email":"[email protected]","mobile":"13800138000"}]
(二). 新增一个用户
Method
{"fieldCount":0,"affectedRows":1,"insertId":16,"serverStatus":2,"warningCount":0,"message":"","protocol41":true,"changedRows":0}
查看刚刚新增的1条用户记录:
myths-Mac:~ myth$ mysql -uroot -p123456
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 516
Server version: 5.7.21 MySQL Community Server (GPL)
Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> use testdb
Database changed
mysql> select * from users;
+----+-------+----------------+-------------+
| id | name | email | mobile |
+----+-------+----------------+-------------+
| 1 | Jack | [email protected] | 13570845544 |
| 2 | Jason | [email protected] | 13800138000 |
| 3 | James | [email protected] | 13800888010 |
+----+-------+----------------+-------------+
3 rows in set (0.00 sec)
mysql>
Method
GET http://192.168.123.47:9090/users/3
Output Raw
[{"id":3,"name":"James","email":"[email protected]","mobile":"13800888010"}]
(四). 根据主键删除一个用户
Method
DELETE http://192.168.123.47:9090/users/3deleted successfully
查看刚刚删除的1条记录(主键 id =3)是否真的不存在,显示它已经被删除:
mysql> select * from users;Method
PUT http://192.168.123.47:9090/users
Headers
Accept application/json
Content-Type application/x-www-form-urlencoded
Body x-www-form-urlencoded
key value
name James
email [email protected]
mobile 13800888010
id 2
Output Pretty
{"fieldCount":0,"affectedRows":1,"insertId":0,"serverStatus":2,"warningCount":0,"message":"(Rows matched: 1 Changed: 1 Warnings: 0","protocol41":true,"changedRows":1}
查看刚刚删修改的1条记录(主键 id =2)是否真的已被更改,显示它已经被修改过了:
mysql> select * from users;
+----+-------+----------------+-------------+
| id | name | email | mobile |
+----+-------+----------------+-------------+
| 1 | Jack | [email protected] | 13570845544 |
| 2 | James | [email protected] | 13800888010 |
+----+-------+----------------+-------------+
2 rows in set (0.00 sec)
mysql>
现在接下来实现移动端react-native 代码,只用到了一个App.js文件,代码如下:
import React, { Component } from 'react';
import {
StyleSheet,
Text,
TextInput,
View,
ScrollView,
TouchableHighlight
} from 'react-native';
export default class App extends Component {
constructor(props){
super(props)
this.state = {
apiData: [],
naData: []
}
this.uid = null;
this.name = null;
this.email = null;
this.mobile = null;
}
onGetUsers = () => {
fetch('http://192.168.123.47:9090/users',{
method: 'GET'
}).then((response) => {
return response.json();
}).then((jsonData) => {
this.setState({
apiData: jsonData,
})
console.log(this.state.apiData);
})
.catch((error) => {
console.warn(error);
}).done();
this.uid = null;
}
onPostUser = () => {
fetch('http://192.168.123.47:9090/users',{
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({ name: this.name, email: this.email, mobile: this.mobile })
}).then((response) => {
return response.json();
}).then((jsonData) => {
this.setState({
naData: jsonData,
})
console.log(this.state.naData);
})
.catch((error) => {
console.warn(error);
}).done();
this.uid = null;
this.name = null;
this.email = null;
this.mobile = null;
}
onGetUser = () => {
fetch('http://192.168.123.47:9090/users/'+ this.uid,{
method: 'GET'
}).then((response) => {
return response.json();
}).then((jsonData) => {
this.setState({
apiData: jsonData,
})
console.log(this.state.apiData);
})
.catch((error) => {
console.warn(error);
}).done();
this.uid = null;
}
onDeleteUser = () => {
fetch('http://192.168.123.47:9090/users/'+ this.uid,{
method: 'DELETE'
}).then((response) => {
console.log(response.rows);
}).catch((error) => {
console.warn(error);
}).done();
this.uid = null;
}
onPutUser = () => {
fetch('http://192.168.123.47:9090/users',{
method: 'PUT',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({ name: this.name, email: this.email, mobile: this.mobile, id: this.uid })
}).then((response) => {
return response.json();
}).catch((error) => {
console.warn(error);
}).done();
this.uid = null;
this.name = null;
this.email = null;
this.mobile = null;
}
render() {
const data = this.state.apiData;
let dataDisplay = data.map(function(jsonData){
return (
)
});
return (
My App Users
onChangeText ={(text) => {this.uid = text}}
value = {this.id}
underlineColorAndroid = 'transparent'
/>
onChangeText ={(text) => {this.name = text}}
value = {this.name}
underlineColorAndroid = 'transparent'
/>
onChangeText ={(text) => {this.email = text}}
value = {this.email}
underlineColorAndroid = 'transparent'
/>
onChangeText ={(text) => {this.mobile = text}}
value = {this.mobile}
underlineColorAndroid = 'transparent'
/>
{dataDisplay}
);
}
}
const styles = StyleSheet.create({
container: {
marginTop: 5,
flex: 1,
alignItems: 'center',
backgroundColor: '#fff',
},
input: {
textAlign: 'left',
height: 30,
width: '90%',
padding: 4,
marginBottom: 7,
fontSize: 16,
fontWeight:'500',
borderWidth: 1,
},
button: {
paddingTop: 10,
paddingBottom: 10,
borderRadius: 25,
marginTop: 3,
marginBottom: 3,
width: '90%',
backgroundColor: '#00bcd4'
},
buttonText: {
color: '#fff',
textAlign: 'center',
fontSize:16,
fontWeight:'500',
}
});
最后来看看iOS&Android模拟器中运行的效果截图吧