Android Volley发起POST请求返回400错误,求排查问题
问题排查与修复方案
核心问题点分析
1. Content-Type请求头冲突
你在getHeaders()里设置了Content-Type: application/x-www-form-urlencoded; charset=utf-8,但同时重写getBodyContentType()返回application/json,导致请求头中Content-Type字段混乱。API服务器无法正确识别请求体格式,直接返回400错误。
2. 关键参数未初始化
emp_num变量仅声明为null,未赋值就放入请求JSON中,导致API接收到的exp_number参数为空,不符合接口要求,触发400错误。
3. 冗余代码无意义
代码中创建了jsonObj但未使用,虽不影响功能,但增加了代码冗余。
修复步骤
统一Content-Type请求头
移除getHeaders()中的Content-Type设置,JsonObjectRequest会通过getBodyContentType()自动设置正确的JSON格式请求头,无需手动添加。初始化emp_num参数
在调用submitdata()前,给emp_num赋值为有效的员工编号(比如从SharedPreferences或Intent中获取)。清理冗余代码
删除未使用的jsonObj变量。
修改后的关键代码片段
修复后的submitdata方法
fun submitdata(url: String?) { progressBar!!.visibility = View.VISIBLE // 确保emp_num已被正确赋值,替换为实际获取逻辑 emp_num = SharedPrefrence.getEmpNumber(applicationContext) val js = JSONObject() try { js.put("year", financialyear!!.selectedItem.toString()) js.put("month", month!!.selectedItem.toString()) js.put("exp_number", emp_num) } catch (e: JSONException) { e.printStackTrace() } val JsonObjectRequest = object : JsonObjectRequest( Request.Method.POST, url, js, Response.Listener { response -> val pdfUrl = response.getString("pdfUrl") fetchPdf(applicationContext, pdfUrl) Toast.makeText(this@PayslipActivity, response.toString(), Toast.LENGTH_LONG).show() progressBar!!.visibility = View.GONE }, Response.ErrorListener { error -> Log.e("Volley", "Error: $error") Toast.makeText(this@PayslipActivity, "请求失败:${error.message}", Toast.LENGTH_LONG).show() progressBar!!.visibility = View.GONE if (error is VolleyError && error.networkResponse != null) { val statusCode = error.networkResponse.statusCode if (statusCode == 400) { Log.e("Volley", "Bad Request: ${error.message}") Toast.makeText(this@PayslipActivity, "参数错误,请检查输入", Toast.LENGTH_LONG).show() } } }) { @Throws(AuthFailureError::class) override fun getHeaders(): Map<String, String> { val headers = HashMap<String, String>() headers["Authorization"] = "Bearer " + SharedPrefrence.getApitoken(applicationContext) headers["x-api-key"] = SharedPrefrence.getApikey(applicationContext)!! // 移除冲突的Content-Type设置 return headers } override fun getBodyContentType(): String { return "application/json; charset=utf-8" // 明确指定编码 } } JsonObjectRequest.retryPolicy = DefaultRetryPolicy( 100000, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT ) val requestQueue = Volley.newRequestQueue(this) requestQueue.add(JsonObjectRequest) }
补充emp_num初始化逻辑
在onCreate()中添加emp_num的赋值逻辑:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_payslip) // ... 其他初始化代码 // 初始化员工编号,替换为实际获取方式 emp_num = SharedPrefrence.getEmpNumber(applicationContext) }
额外建议
- 开启Volley日志调试,对比实际发送的请求头、请求体与Postman的内容,确认是否一致。
- 检查SharedPreferences中存储的token和api-key是否与Postman中使用的完全一致,避免字符截断或空格导致的认证失败。
内容的提问来源于stack exchange,提问作者jyothi
相关产品推荐
相关产品推荐

