Android Studio连接Oracle数据库时JSP返回多值导致登录失败的修复咨询
问题分析与修复方案
你的问题核心在于JSP返回多值的格式不规范,以及Android端没有正确解析多值返回结果,同时JSP内部还有逻辑覆盖和资源泄漏的问题,下面一步步拆解修复:
1. 核心问题:JSP返回值格式导致Android判断失效
当前JSP通过out.println(returns); out.println(names);直接输出两个值,最终返回给Android的是两个字符串拼接(带换行),比如状态码2加用户名张三,实际返回内容是:
2 张三
而你的Android代码在onPostExecute里只判断data.equals("2"),显然永远匹配不上,所以直接进入登录失败的分支。
修复方案:用JSON格式结构化返回数据
JSON是跨端传递多值的标准格式,能清晰区分不同字段。修改JSP的输出部分:
修改后的JSP关键代码
// 替换原来的finally块内容 finally { // 构建JSON格式返回值 StringBuilder jsonResult = new StringBuilder(); jsonResult.append("{"); jsonResult.append("\"status\":\"").append(returns).append("\","); jsonResult.append("\"username\":\"").append(names).append("\""); jsonResult.append("}"); out.println(jsonResult.toString()); System.out.println(jsonResult.toString()); // 关闭数据库连接(之前漏了,必须加上避免连接泄漏) if(conn != null){ try{ conn.close(); }catch(Exception e){ e.printStackTrace(); } } }
另外还要注意JSP里的逻辑问题:你的第二个查询(login_sec_sql)会覆盖returns的值,比如第一个登录验证通过得到returns="2",但如果第二个查询没找到数据,会把returns改成3,这显然不符合逻辑。你需要调整这部分逻辑,比如只有第一个验证通过后才执行第二个查询,或者明确两个验证的优先级。
2. Android端修改:解析JSON返回值并处理
现在JSP返回的是JSON字符串,Android端需要解析它来获取状态码和用户名,修改HttpConnection的onPostExecute方法:
修改后的Android关键代码
@Override protected void onPostExecute(String data) { super.onPostExecute(data); try { // 解析JSON JSONObject jsonObject = new JSONObject(data); String status = jsonObject.getString("status"); String username = jsonObject.getString("username"); if (status.equals("2")) { // 登录成功,传递用户名到下一个页面 Intent intent = new Intent(Kfc_Login.this, Kfc_Birth.class); intent.putExtra("username", username); startActivity(intent); finish(); } else { // 根据不同状态码提示不同错误(可选) String errorMsg = switch (status) { case "1" -> "账号密码不匹配"; case "3" -> "二次验证失败"; default -> "登录失败"; }; Toast.makeText(getApplicationContext(), errorMsg, Toast.LENGTH_SHORT).show(); } } catch (JSONException e) { e.printStackTrace(); Toast.makeText(getApplicationContext(), "数据解析失败", Toast.LENGTH_SHORT).show(); } }
注意:需要在Android项目中导入JSON相关类,如果是AndroidX项目,默认已经包含;如果是旧项目,可能需要添加依赖。
3. 额外的优化建议
- JSP中的数据库操作:使用try-with-resources自动关闭资源,避免手动关闭遗漏,比如:
try(Connection conn = DriverManager.getConnection(...); PreparedStatement login_fir_pstmt = conn.prepareStatement(login_fir_sql)){ // 执行查询逻辑 }catch(Exception e){ e.printStackTrace(); } - Android端的网络请求:建议使用更现代的库(比如Retrofit、OkHttp)替代
AsyncTask,因为AsyncTask已经被废弃,且现代库更易用、更稳定。 - 密码传递:当前是明文传递密码,非常不安全,建议在JSP和Android端都添加加密逻辑(比如SHA256),同时优先使用HTTPS传输数据。
内容的提问来源于stack exchange,提问作者Kangsman
相关产品推荐
相关产品推荐

