ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

B4A连接MySQL做登录注册:避开直连陷阱的HTTP接口方案

B4A连接MySQL做登录注册:避开直连陷阱的HTTP接口方案 简介对于刚接触移动开发的读者这是一套用Basic4AndroidB4A连接MySQL数据库实现登录注册功能的完整工程资料覆盖从界面布局、连接配置到业务逻辑的闭环。全部内容压缩在五十三个文件、一点八四兆字节中除B4A工程源码外还包含home和reger等BAS逻辑模块、Java辅助类、XML布局、编译生成的APK安装包以及元数据等辅助文档方便对照学习和直接运行验证。该资源已有七百零九人学习下载。包内不仅包含可运行的APK还保留了完整的B4A工程结构便于在IDE中重新编译调试同时保留Android工程配置与构建产物可还原完整开发流程。home与reger模块分别对应登录和注册界面逻辑数据库连接参数、密码哈希、SQL注入防范及连接关闭等安全与资源管理细节均体现在代码中。整体适合移动开发初学者作为课程设计或毕业设计参考。1. 用 B4A 连 MySQL 做登录注册一条被很多教程带偏的老路B4ABasic4Android在 Android 原生开发的小圈子里一直有稳定拥趸尤其适合从 VB、Delphi 转过来的老开发以及想快速出内部工具类 App 的团队。而“连接 MySQL 实现登录注册”几乎是每个 B4A 新手必经的一关——论坛里隔三差五就有人问“怎么直连 MySQL”“为什么我的 App 一登录就卡死”“为什么过一会儿就连不上”。这个需求的本质不是写两个界面、两张表而是解决一个核心矛盾Android 设备不是一个可以长期持有数据库连接的终端MySQL 也不是为移动端设计的通信协议。真正能落地的方案是让 B4A 走 HTTP 接口、由服务端代管数据库访问而不是在手机上直连 3306 端口。这篇文章按我实际做过的路线来写先说清楚为什么直连方案会翻车再给一套服务端接口 B4A 端登录注册的最小可跑通实现最后把我在 MySQL 8、SSL、字符集和并发上踩过的坑一条条列出来。读者里如果有正在用 B4A 做内部管理系统、进销存、员工考勤这类带账号体系的 App这套方案可以直接抄作业如果你只是想先在本机跑通验证后面的每一步也都能照着复现不需要提前懂 PHP 或 MySQL 运维。2. 先搞清楚 B4A 和 MySQL 之间的路该怎么走直连、JDBC 与 HTTP 的取舍2.1 B4A 里常见的三种“连数据库”方式对比B4A 官方库和社区库提供了至少三条路去触碰 MySQL 数据。很多教程默认推荐第一条B4A 自带的MySQL库它封装了 JDBC 驱动写起来确实像那么回事——MySQLConnection、ExecuteQuery、ExecuteNonQuery语法非常接近桌面端的 ADO。但这条路的隐藏成本极高Android 设备的 IP 是运营商随机分配的Wi-Fi 和 4G 切换时连接必然断开MySQL 默认的wait_timeout是 8 小时但移动端的 TCP 连接可能几十秒就被系统回收更致命的是把数据库账号密码和 SQL 语句全部打进 APK 里任何人反编译就能直接连你的库。我见过一个外包项目用这种方式上线两个月后数据库被删了因为连接字符串里明文写着 root 密码。第二条路是社区库里的OkHttp或HttpUtils2配合服务端脚本。App 端只发 HTTP 请求服务端PHP、Java、Node 都行去连 MySQL取完数据返回 JSON。这条路的本质是把数据库关在服务端防火墙后面App 永远不接触 3306 端口。登录注册这种场景请求频率不高、单次数据量小、对延迟不敏感HTTP JSON 的代价几乎可以忽略。这也是我要重点展开的方案。第三条路是引入WebView 网页端——把登录注册页面直接做成响应式网页B4A 里开一个 WebView 加载它再用 JavaScriptBridge 把登录结果传回原生层。这种方式在团队里已经有现成 Web 端时很省事但用户体验割裂而且 Cookie、Session 的管理绕了一圈还是回到了 HTTP 语义上不如直接在原生层做。2.2 为什么我不建议在 B4A 里直连 MySQL从连接生命周期说起要理解直连为什么不行得先看一条 SQL 查询在直连模式下经历了什么。B4A 的 MySQL 库在Connect之后会维持一个 TCP 长连接每次ExecuteQuery都是在这个连接上发送文本协议的数据包。问题出在移动网络的 NAT 超时上——运营商的网关通常会在 30 到 120 秒内回收没有流量的 TCP 映射而你的 App 不可能保证每 30 秒发一次心跳。于是表现就是App 刚打开时能登录放后台几分钟再操作ExecuteQuery直接抛连接异常。你当然可以在BeforeFirstResult里捕获异常然后重连但每次重连的握手成本在弱网环境下要 2 到 5 秒用户感知就是“转圈、卡死、又闪退”。另一个被忽略的点是 MySQL 的并发连接数。默认max_connections通常是 151一个直连模式的 App 如果装机量上千活跃用户同时操作时瞬间就能把连接池打爆而且这些连接大多处于 Sleep 状态——因为移动端断连后 MySQL 要等 TCP 超时才会回收。服务端可以改wait_timeout缩短回收时间但这治标不治本。服务端接口方案天然是短连接PHP 请求结束即释放连接配合连接池能支撑的并发量完全不在一个量级。2.3 服务端接口方案的最小架构三种组成各自干什么我常用的服务端方案是三件套PHP 接口脚本 MySQL 数据库 共享的配置文件。PHP 在这里不是因为它性能最好而是因为部署最无脑——任意一台装着 Nginx/Apache PHP 的机器都能跑MySQL 的mysqli扩展是标配不依赖复杂的编译环境。数据库负责存储用户表接口负责接收 B4A 发来的用户名和密码校验后返回登录令牌或注册结果。用户表的设计尽量精简我用过的最小结构是四张核心表都算多实际上users一张表就能支撑登录注册id主键自增username用户名唯一索引password加密后的密码散列created_at注册时间App 端每次请求接口时用 POST 把username和password放进表单体里。PHP 拿到后先做参数校验再用参数化查询Prepared Statement去查库避免 SQL 注入。返回的 JSON 里固定三个字段code200 成功、400 参数错误、401 密码错误、500 服务端异常、message给人看的提示、data登录成功后可以放昵称、头像地址等额外信息。B4A 端拿到 JSON 后解析出code决定跳转主页还是弹出错误提示。架构上看这条路绕开了移动端直连 MySQL 的所有坑代价仅仅是多一层 HTTP 往返。在登录注册这种低频操作下多出来的 50 到 100 毫秒用户根本感知不到而换来的是数据库不裸奔、连接稳定、并发可控。值。3. 落地一套最小登录注册从建表到 B4A 界面逐个打通3.1 数据库准备建库建表与一个需要注意的排序规则开始之前先确认你的 MySQL 能对外提供服务。以 MySQL 8.0 为例在服务器上用 root 登录后执行以下建库建表语句。这个设计里没有用外键、没有存储过程因为登录注册业务用不到加了反而是后续维护的负担。CREATE DATABASE IF NOT EXISTS app_auth DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE app_auth; CREATE TABLE IF NOT EXISTS users ( id INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 主键, username VARCHAR(50) NOT NULL COMMENT 用户名, password VARCHAR(255) NOT NULL COMMENT 密码散列, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 注册时间, PRIMARY KEY (id), UNIQUE KEY uk_username (username) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_unicode_ci COMMENT用户表;这里两个参数对新人有坑我直接标出来。第一个是utf8mb4而不是utf8——MySQL 的utf8字符集最多存 3 字节遇到 Emoji 表情或生僻字会直接报错或者变成乱码utf8mb4是完整版。第二个是COLLATEutf8mb4_unicode_ci这个排序规则在处理用户名校验时是大小写不敏感的也就是说Admin和admin会被当成同一个用户名避免用户注册时用小写、登录时用大写导致的神秘问题。如果你希望用户名严格区分大小写就改成utf8mb4_bin。执行完成后可以用SHOW CREATE TABLE users\G确认表结构。另外提醒一句别在生产库里用 root 账号跑业务连接建议单独建一个账号只授予app_auth库的权限这是后话。本地测试阶段先用 root 跑通再说。3.2 服务端 PHP 接口注册与登录共用一套返回协议服务端我写成两个入口文件和一个公共配置db.php放连接参数register.php处理注册login.php处理登录。公共部分先写这一步出错后面全白搭。?php // db.php - 数据库连接公共文件 date_default_timezone_set(Asia/Shanghai); $host 127.0.0.1; // 用IP不用localhost避免PHP解析socket路径出错 $port 3306; $dbname app_auth; $user app_user; // 生产环境用独立账号测试可用root $pass your_password; mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); $conn new mysqli($host, $user, $pass, $dbname, $port); $conn-set_charset(utf8mb4); function response(int $code, string $message, array $data []): void { echo json_encode([code $code, message $message, data $data], JSON_UNESCAPED_UNICODE); exit; } ?db.php里有三个容易被坑到的点。第一连接地址写的127.0.0.1而不是localhost——PHP 在某些版本里解析localhost会走 Unix SocketSocket 路径不对就报error 2002 (HY000): Cant connect to local MySQL server through socket /tmp/mysql.sock而用 IP 会强制走 TCP 3306 端口问题直接消失。第二开了mysqli_report到异常模式这样 SQL 执行出错时 PHP 会直接抛异常而不是返回 false配合后面的 try-catch 能把真实错误打印出来而不是传给 App 一个含糊的“数据库错误”。第三json_encode加了JSON_UNESCAPED_UNICODE保证 message 里的中文直接输出而不是变成\uXXXX。接下来是注册接口。注册的逻辑是接收用户名和密码检查用户名是否已被占用没占用就把密码加密后插入。实现如下?php // register.php - 用户注册接口 require db.php; $username trim($_POST[username] ?? ); $password $_POST[password] ?? ; if ($username || strlen($password) 6) { response(400, 用户名不能为空密码至少6位); } $password_hash password_hash($password, PASSWORD_DEFAULT); try { $stmt $conn-prepare(INSERT INTO users (username, password) VALUES (?, ?)); $stmt-bind_param(ss, $username, $password_hash); $stmt-execute(); response(200, 注册成功, [username $username]); } catch (mysqli_sql_exception $e) { if ($e-getCode() 1062) { response(400, 用户名已存在); } error_log($e-getMessage()); response(500, 服务端异常请稍后重试); } ?这段代码里最关键的是password_hash()和bind_param()这两个函数。password_hash默认生成 bcrypt 散列每次结果都不同即使两个人密码一样库里的散列值也不一样这是防彩虹表和撞库的基础比 MD5 加盐还要稳。bind_param(ss, ...)是参数化查询用户名和密码都被当作字符串参数传进去无论用户输入单引号还是OR 11MySQL 都只会把它当成字面值SQL 注入从根上断了。捕获1062错误是因为uk_username唯一索引在并发注册时可能让两个请求同时通过“用户名是否已存在”的检查这时唯一索引兜底返回友好提示。再看登录接口。登录要比注册多做两件事校验密码、标记登录状态。实现如下?php // login.php - 用户登录接口 require db.php; session_start(); $username trim($_POST[username] ?? ); $password $_POST[password] ?? ; if ($username || $password ) { response(400, 用户名和密码不能为空); } try { $stmt $conn-prepare(SELECT id, username, password FROM users WHERE username ? LIMIT 1); $stmt-bind_param(s, $username); $stmt-execute(); $result $stmt-get_result(); $user $result-fetch_assoc(); if (!$user || !password_verify($password, $user[password])) { response(401, 用户名或密码错误); } $_SESSION[user_id] $user[id]; $_SESSION[username] $user[username]; response(200, 登录成功, [username $user[username]]); } catch (mysqli_sql_exception $e) { error_log($e-getMessage()); response(500, 服务端异常请稍后重试); } ?这里用了 PHP 的原生 Session 来标记登录状态。B4A 端后续每次请求接口时带上Cookie头服务端用$_SESSION[user_id]判断是否已登录。不过要说明白Session 只是登录状态的“短期标记”如果要做“记住我”或者移动端离线登录需要引入 token 机制这个我放到最后进阶部分讲。用password_verify校验密码时即使账号不存在也会走一遍校验逻辑故意构造一个永远验证失败的散列避免通过响应时间差枚举用户名——这是一个很容易被忽略的安全细节。3.3 B4A 端核心代码用 HttpUtils2 发 POST、解析 JSONB4A 侧的客户端我假设你已经建好了带两个输入框和两个按钮的登录界面这里只放核心的逻辑代码。B4A 用的是类似 VB 的事件驱动写法我依赖的库是HttpUtils2它在 B4A 的 SDK Manager 里直接可以勾选不需要额外下载。 登录按钮点击事件 Sub btnLogin_Click Dim job As HttpJob job.Initialize(login_job, Me) job.PostString(http://your.server.com/login.php, _ username EditTextUsername.Text password EditTextPassword.Text) End Sub HttpUtils2 回调 Sub JobDone(Job As HttpJob) If Job.Success Then Dim parser As JSONParser parser.Initialize(Job.GetString) 把响应文本交给JSON解析器 Dim root As Map parser.NextObject Dim code As Int root.Get(code) Dim msg As String root.Get(message) If code 200 Then Log(登录成功: root.Get(data)) StartActivity(MainActivity) Else ToastMessageShow(msg, False) End If Else Log(Job.Error) ToastMessageShow(网络请求失败, False) End If Job.Release 必须释放否则内存泄漏 End Sub这是一个用 B4A 实现登录后跳转的最小案例。PostString会把内容以application/x-www-form-urlencoded格式 POST 给 PHPPHP 端用$_POST拿参数。回调里先判断Job.Success它代表 HTTP 层面是否收到了响应注意200这个状态码并不代表业务成功——业务成功要看 JSON 里的code字段。有次我把这两个概念搞混接口返回400参数错误HTTP 层面依然是200Job.Success还是 true最终是靠 JSON 里的 code 才定位到问题。所以在 B4A 端永远要养成“HTTP 成功不代表业务成功”的条件反射。注册按钮的逻辑几乎一样区别只是把login.php换成register.php。如果你希望请求超时时间可控HttpJob里可以这样设置job.Timeout 10000 单位毫秒10秒没响应就算超时默认 20 秒对移动端来说太长了弱网环境下用户体验不好10 秒比较合适。如果请求在 2G 网络下经常超时再放宽到 15 秒。3.4 PHP 端和 B4A 端联调时怎么快速定位先裸测接口再连手机我最怕的是两头都写了代码然后直接联调一旦出错你根本不知道是 App 的锅还是服务端的锅。正确顺序是先用 Postman 或者浏览器插件裸测接口确认服务端没问题再碰 B4A。裸测方法很简单# 先用 curl 测注册接口 curl -d usernametestuserpassword123456 http://127.0.0.1/register.php # 期望输出: {code:200,message:注册成功,data:{username:testuser}} # 再测登录接口 curl -d usernametestuserpassword123456 http://127.0.0.1/login.php # 期望输出: {code:200,message:登录成功,data:{username:testuser}}如果 curl 返回error 2002或者Connection refused先别动 B4A检查db.php里的$host和$port是否跟SHOW VARIABLES LIKE port一致。如果返回的是 404检查 Nginx 的root配置是否指向了 PHP 文件所在目录。接口裸测通过之后再让手机连同一个 Wi-Fi把your.server.com换成电脑的局域网 IP。这里有个高频坑手机连上 Wi-Fi 后访问127.0.0.1访问的是手机自己而不是电脑。电脑 IP 用ipconfigWindows或ifconfigmacOS/Linux查看B4A 里填http://192.168.x.x/login.php。4. 避坑指南B4A 连接 MySQL 登录注册的 5 个典型翻车现场4.1 MySQL 8 密码插件导致 PHP 连接报错看到的错误和真正的原因差两层现象db.php里用 root 连接PHP 报PDO::__construct(): Connection refused或者Access denied for user rootlocalhost但用 Navicat 连同一个 MySQL 却是好的。原因MySQL 8 默认的认证插件是caching_sha2_password而 PHP 7.4 以下的mysqli扩展不认识这个插件。这不是密码错误也不是防火墙问题纯粹是握手协议不兼容。解决不用改全局配置给专用账号指定旧插件即可。ALTER USER app_user% IDENTIFIED WITH mysql_native_password BY your_password; FLUSH PRIVILEGES;注意%表示允许任意主机连接。如果你跳过了CREATE USER这一步得先创建用户再改插件顺序不能反。MySQL 5.7 及以下版本没有这个问题所以网上老教程不提这个坑但用 MySQL 8 就绕不开。另外顺带提醒如果 B4A 里用了 JDBC 直连 MySQL 8也要在连接串上加useSSLfalseallowPublicKeyRetrievaltrue不然同样会被caching_sha2_password卡住——这就是为什么我更推荐走 HTTP 接口插件兼容问题直接在服务端消化掉B4A 端感知不到。4.2 B4A 能连上接口但中文乱码三处编码必须一致现象注册成功后 Toast 弹出的“注册成功”变成“注ååæå”或者写入 MySQL 的中文变成???。原因PHP 文件本身不是 UTF-8 编码、MySQL 连接字符集不是 utf8mb4、B4A 解析 JSON 时没按 UTF-8 解码三处只要有一处不一致就会乱。解决步骤按顺序排查第一确保 PHP 文件保存成“UTF-8 无 BOM”格式带 BOM 会导致接口第一个字符前多一个隐藏字符PHP 解析没问题但 JSON 解析会报错第二db.php里执行过$conn-set_charset(utf8mb4)没加这一行即使建表时用了 utf8mb4连接还是默认 latin1第三B4A 端Job.GetString返回的字符串本身就是 UTF-8 解码过的一般不用额外处理。最隐蔽的是JSONParser解析时遇到非法 UTF-8 序列会直接抛异常而 B4A 默认不会弹出异常信息只在 Logcat 里打一行。我遇到过案例是 B4A 端日志显示JSONParser.Initialize失败怎么调都报错最后发现是 PHPjson_encode把数据里的一个特殊字符转义成了无效序列。治本的办法是在 PHP 里对输出做一次mb_check_encoding($data, UTF-8)校验不合法就直接返回 500别把脏数据传给 App。4.3 error 2002 (HY000) Socket 连不上localhost 和 TCP 的玄学差异现象接口部署到 Linux 服务器上后PHP 连接 MySQL 报error 2002 (HY000): Cant connect to local MySQL server through socket /tmp/mysql.sock但命令行里mysql -u root -p明明能登录。原因PHP 的mysqli扩展在localhost时会优先找 Unix Socket而 Socket 文件路径因 MySQL 版本和发行版不同而异——Ubuntu 上通常在/var/run/mysqld/mysqld.sockCentOS 上可能在/var/lib/mysql/mysql.sock/tmp/mysql.sock根本不存在。解决最省事的是在db.php里把 host 从localhost改成127.0.0.1强制走 TCP。如果你因为安全原因必须用 Socket则显式指定 Socket 路径$conn new mysqli($host, $user, $pass, $dbname, $port, /var/run/mysqld/mysqld.sock);但这有一个隐患mysqli一旦显式传了 Socket 路径它会忽略 host 和 port 参数。所以两个方案二选一别混用。4.4 手机访问电脑上的接口不通防火墙、IP 绑定和 Wi-Fi 隔离现象电脑上用 curl 测接口是通的手机用同一个 Wi-Fi 访问http://192.168.x.x/login.php转圈超时。原因有三类按概率排序第一Windows 防火墙拦截了 PHP 开发服务器的入站端口需要放行 80 或 8080第二MySQL 的bind_address默认是127.0.0.1只接受本机连接你需要把 PHP 和 MySQL 放在同一台机器上或者改my.cnf让 MySQL 监听0.0.0.0第三路由器开了“AP 隔离”同一 Wi-Fi 下的设备互相不能访问常见于公司访客网络和部分家用路由的“客人网络”。排查顺序是在手机上先用浏览器访问接口地址如果浏览器能打开而 B4A 不行问题在 App如果浏览器也打不开一步步检查防火墙和 IP 绑定。一个在 Android 上容易被忽略的细节是明文 HTTP 限制。Android 9API 28开始默认禁止明文 HTTP 流量如果你的接口是http://而不是https://B4A 请求会被系统直接拦下来报错信息是CLEARTEXT communication to 192.168.x.x not permitted。解决方式有两个开发阶段在 B4A 工程里添加网络权限并允许明文流量或者干脆把 B4A 的 targetSdkVersion 调低到 27 以下——但后者只是缓兵之计发布版本建议还是上 https。4.5 用户量稍微上来后登录变慢是不是少了索引和连接池现象注册用户到几千之后登录接口响应从 50 毫秒涨到 500 毫秒甚至偶尔超时。原因users表数据量增大后全表扫描的成本线性上升同时 PHP 默认短连接模式下每次请求新建 mysqli 连接高并发时握手开销被放大。解决分两层第一层是看EXPLAIN SELECT id, username, password FROM users WHERE username x的type列是不是ref或const如果不是确认uk_username唯一索引存在——只要建表时带了UNIQUE KEY这一步通常没问题第二层是给 PHP 加持久化连接把new mysqli(...)换成$conn-pconnect的语义。PHP 的mysqli不太适合 pconnect我一般引入连接池方案如 ProxySQL 或 Swoole 的协程池之前先用max_connections监控判断瓶颈——如果连接数没打满而 CPU 高是查询慢如果连接数打满是连接管理问题这时候再考虑上池。5. 进阶与验证给登录注册加上会话令牌与接口自检5.1 从 Session 到 Token移动端更合适的会话方案PHP 的 Session 依赖浏览器 Cookie 机制B4A 的HttpJob虽然能手动携带 Cookie 头但移动端对 Cookie 的处理不如桌面端透明而且 Session 存储在服务端内存或文件里横向扩展时需要额外同步。更稳妥的做法是自造一个简单的 Token登录成功后生成一个随机字符串存到数据库的tokens表同时返回给 B4AB4A 在后续请求的 Header 里带Authorization: Bearer token服务端查表校验。用户注销时删掉 token就实现了“下线”功能。这个方案的关键是 token 必须足够随机并且有过期时间。用bin2hex(random_bytes(16))生成过期时间设为 7 天。B4A 端把 token 存在File.DirInternal里而不是全局变量里这样 App 进程被杀后重新打开仍然保持登录状态。注册、登录、下线三个接口的完整闭环比只用 Session 更适合移动端。5.2 接口自检一条 SQL 确认系统健康的快捷方式每次部署完新版本我会先执行一组自检指令确认数据库和接口都活着。不是把所有验证写进代码里而是直接用命令行快速判断-- 检查连接数是否打满 SHOW STATUS LIKE Threads_connected; SHOW VARIABLES LIKE max_connections; -- 检查是否有慢查询 SHOW GLOBAL STATUS LIKE Slow_queries; -- 查看当前所有连接和它们的执行状态 SHOW FULL PROCESSLIST;SHOW FULL PROCESSLIST里如果看到大量Sleep状态的连接并且Time超过几十秒说明连接池回收不及时可以调低wait_timeout。这条命令还能看到是否有SELECT长时间卡在Sending data那就是查询慢或者表锁了。配合KILL id可以干掉异常连接——有一次存储过程死循环把表锁住就是靠这条命令救回来的。5.3 参数清单登录注册系统里值得抄走的 8 个关键参数参数推荐值说明php 请求超时10000 msB4A 端job.Timeoutbcrypt 成本因子12PASSWORD_DEFAULT 即可越高越慢太高会拖慢登录token 过期7 天超过后强制重新登录MySQL wait_timeout60 s手机端短连接足够MySQL max_connections按内存定默认 151不够就排查服务端连接泄漏utf8mb4 排序规则utf8mb4_unicode_ci用户名大小写不敏感Session 名自定义别用默认 PHPSESSID降低被工具扫描的风险密码最小长度8 位6 位太容易暴力破解这组参数是经验值不保证每个项目最优。比如 B4A 端如果主要跑在 Wi-Fi 环境超时调到 15 秒也合理bcrypt 成本因子在性能较低的手机上可能把登录压到 1 秒以上这时降到 10 是值得的。参数的意义在于给你一个可调的起点而不是标准答案。最后回到工作习惯上。我从 B4A 写第一行连 MySQL 的代码到现在最深的教训是所有“突然连不上”的诡异问题一半出在编码不一致上另一半出在没先裸测接口就拉联调。现在我每次接到登录注册相关的活儿都先把 curl 命令存在文档里改一行 PHP 就测一次接口再回到 B4A 调界面数据库永远只给业务账号最小权限手机连不上先开浏览器访问而不是反复改代码。这套流程不酷但确实能让我少熬几个夜。希望帮到你。本文还有配套的精品资源点击获取
返回列表