如何基于Android客户端用户名从MySQL数据库获取指定消息
解决方案:筛选用户专属消息并验证用户有效性
好的,我来帮你一步步搞定这个需求。咱们分两个核心部分来实现:只展示当前用户作为发送方/接收方的消息,以及验证发起请求的用户名是否存在,同时调整你的PHP和Android代码适配需求。
一、修改PHP后端:验证用户+筛选消息
首先,你的现有PHP查询没有添加用户筛选条件,而且需要先验证用户名是否存在于users表中。这里我们用预处理语句来避免SQL注入,同时保证安全性。
1. 完整PHP代码示例
<?php // 假设你已经建立了MySQL连接($conn变量) $conn = new mysqli("localhost", "db_username", "db_password", "db_name"); if ($conn->connect_error) { die(json_encode(["error" => "Database connection failed"])); } // 接收Android端传递的用户名(POST方式更安全) if (!isset($_POST['username'])) { echo json_encode(["error" => "Username parameter missing"]); exit; } $username = $_POST['username']; // 第一步:验证用户名是否存在于users表 $checkUserStmt = $conn->prepare("SELECT id FROM users WHERE username = ?"); $checkUserStmt->bind_param("s", $username); $checkUserStmt->execute(); $userResult = $checkUserStmt->get_result(); if ($userResult->num_rows === 0) { // 用户不存在,返回错误信息 echo json_encode(["error" => "User does not exist"]); $checkUserStmt->close(); $conn->close(); exit; } // 获取当前用户的ID $user = $userResult->fetch_assoc(); $currentUserId = $user['id']; $checkUserStmt->close(); // 第二步:查询当前用户作为发送方或接收方的消息 // 注意:假设你的messages表有msg_fk_sender_id(发送方ID)和msg_fk_receiver_id(接收方ID)字段 // 如果你的字段名不同,请自行替换 $msgStmt = $conn->prepare(" SELECT u.username, m.message FROM messages m JOIN users u ON m.msg_fk_sender_id = u.id WHERE m.msg_fk_sender_id = ? OR m.msg_fk_receiver_id = ? "); $msgStmt->bind_param("ii", $currentUserId, $currentUserId); $msgStmt->execute(); $msgResult = $msgStmt->get_result(); // 整理消息数据为JSON格式 $messages = []; while ($row = $msgResult->fetch_assoc()) { $messages[] = $row; } echo json_encode($messages); // 关闭连接和语句 $msgStmt->close(); $conn->close(); ?>
关键说明:
- 用
prepare+bind_param实现预处理,彻底避免SQL注入风险。 - 先验证用户存在性,不存在则返回明确的错误提示,避免无效查询。
- 查询时通过
OR条件筛选出当前用户是发送方或接收方的所有消息,同时关联users表获取发送方的用户名。
二、修改Android客户端:传递用户名+处理响应
你的现有Android代码用的是GET请求,无法传递用户名参数,需要改成POST请求,同时处理后端返回的错误信息。
1. 修改downloadJSON方法(发送POST请求)
首先,你需要获取当前登录的用户名(比如从SharedPreferences、登录页面Intent传递,这里提供一个示例方法):
// 替换成你实际获取当前用户名的方式 private String getCurrentUsername() { // 示例:从SharedPreferences读取登录用户信息 SharedPreferences prefs = getSharedPreferences("UserSession", MODE_PRIVATE); return prefs.getString("current_username", ""); }
然后修改doInBackground方法,发送POST请求并传递用户名:
@Override protected String doInBackground(Void... voids) { try { URL url = new URL(urlWebService); HttpURLConnection con = (HttpURLConnection) url.openConnection(); // 设置请求方式为POST con.setRequestMethod("POST"); con.setDoOutput(true); con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); // 构造POST参数,编码避免乱码 String username = getCurrentUsername(); String postData = "username=" + URLEncoder.encode(username, "UTF-8"); // 写入参数到请求体 OutputStream os = con.getOutputStream(); os.write(postData.getBytes()); os.flush(); os.close(); // 读取后端响应 StringBuilder sb = new StringBuilder(); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(con.getInputStream())); String json; while ((json = bufferedReader.readLine()) != null) { sb.append(json + "\n"); } return sb.toString().trim(); } catch (Exception e) { e.printStackTrace(); return null; } }
2. 修改loadIntoListView方法(处理错误+展示消息)
需要判断后端返回的是错误信息还是消息列表,给用户明确反馈:
private void loadIntoListView(String json) throws JSONException { if (json == null) { Toast.makeText(this, "Failed to connect to server", Toast.LENGTH_SHORT).show(); return; } // 先检查是否是错误响应(JSON对象格式) try { JSONObject errorResponse = new JSONObject(json); if (errorResponse.has("error")) { Toast.makeText(this, errorResponse.getString("error"), Toast.LENGTH_SHORT).show(); return; } } catch (JSONException e) { // 不是JSON对象,说明是消息数组,继续处理 } // 解析消息数组并展示到ListView JSONArray jsonArray = new JSONArray(json); String[] messageList = new String[jsonArray.length()]; for (int i = 0; i < jsonArray.length(); i++) { JSONObject obj = jsonArray.getJSONObject(i); messageList[i] = obj.getString("username") + ": " + obj.getString("message"); } ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, messageList); listView.setAdapter(arrayAdapter); }
额外注意事项:
- 确保你的AndroidManifest.xml中添加了网络权限:
<uses-permission android:name="android.permission.INTERNET" /> AsyncTask在Android 11及以上版本已被废弃,长期来看建议改用Coroutines、Volley或Retrofit来实现网络请求,不过上面的代码可以在当前版本正常运行。
三、数据库表结构确认
确保你的messages表包含以下关键字段(如果字段名不同,自行调整PHP和Android代码中的对应名称):
msg_fk_sender_id:发送方用户ID(外键关联users.id)msg_fk_receiver_id:接收方用户ID(外键关联users.id)message:消息内容
内容的提问来源于stack exchange,提问作者Andry Jhonas
相关产品推荐
相关产品推荐

