编程教育资源分享平台

网站首页 > 技术文章 正文

前端通过axios发送post请求 后端java无法拿到数据

luoriw 2024-01-17 11:14:19 技术文章 21 ℃ 0 评论

场景描述:

如果后端是 Java(springmvc),前端使用 jQuery 的 $.ajax 发送 POST 请求,测试接口是没问题的。但是换做使用 axios 来发送 POST 请求,后端却无法获取数据。

问题的主要原因是后端默认接收的 POST 请求头是 Content-Type 设置为 application/x-www-form-urlencoded 的表单请求,参数形式是 key1=value1&key2=value2 这种形式,后端获取使用 @RequestParam 。jQuery 默认的就是这种请求方式,所以使用 $.ajax 发送请求没有问题。

而如果发送 POST 请求时不指定请求头 Request Header,默认使用的 Content-Type 是 text/plain;charset=UTF-8 或者 application/json ,参数出现在 Request payload 块,其参数形式是标准的 Json 格式,所以后台还是使用 @RequestParam 就无法获取到参数,就需要改用 @RequestBody 获取。

在 axios 中使用 POST 发送数据时,默认是直接把 Json 放到请求体中提交到后端的,属于上述的第二种方式。

后端解决方案

在请求参数使用 @RequestBody 注解替代 @RequestParam:

@ResponseBody
@RequestMapping(value="/save",method=RequestMethod.POST)
public Map<String, String> save(@RequestBody Student student)

前端解决方案:

如果后台处理不了的话,其实这个问题前端同学完全可以自己解决的,其实就是设置请求头而已,以下给出三种方案:

第一种解决方案、前端添加请求头信息,并重新封装请求参数:

const params = 'username=' + this.username + '&userpass=' + this.userpass
axios({
  url: '/api',
  method: 'POST',
  headers: { 'content-type': 'application/x-www-form-urlencoded' },
  data: params
})

第二种解决方案、针对第一种方案手动拼接参数很麻烦:

const params = new URLSearchParams()
params.append('username', this.username)
params.append('userpass', this.userpass)
axios({
  url: '/api',
  method: 'POST',
  headers: { 'content-type': 'application/x-www-form-urlencoded' },
  data: params
})

第三种解决方案、利用内置 qs 模块序列化参数:

import qs from 'qs'
const data = { username: this.username, userpass: this.userpass }
axios({
  url: '/api',
  method: 'POST',
  headers: { 'content-type': 'application/x-www-form-urlencoded' },
  data: qs.stringify(data)
})

当然最好的方式是直接二次封装 axios:

// 对 axios 进行二次封装
import axios from 'axios'
import qs from 'qs' // 引入 qs 模块,该模块不需要安装,用来序列化 post 类型的数据
// 添加一个新的 axios 的实例
const http = axios.create({
  baseURL: '/api', // 统一设置请求地址前缀
  timeout: 6000, // 请求超时时间
  withCredentials: true // 是否允许带 cookie 
})
// 请求拦截,统一在这里处理 POST 数据或者请求时带上 token
http.interceptors.request.use(function (config) {
  if (config.method === "post") { // 这一步主要取决于后端是否可以接受 json
    config.headers = {
      'Content-Type':'application/x-www-form-urlencoded'
    }
    // 参数序列化
    config.data = qs.stringify(config.data);
  }
  // 获取 token
  const token = sessionStorage.getItem('token')
  if(token) {
    // ...
  }
  return config;
}, function (error) {
  return Promise.reject(error)
});
// 响应拦截,处理错误, 如 token 不合法
http.interceptors.response.use(function (response) {
  // ...
  return response;
}, function (error) {
  // ...
  return Promise.reject(error)
})
export default http

这样前端请求还是按照原来的写法直接给 data 传递对象即可,因为每次请求的时候都会自动转换参数形式。


【喜欢我的文章欢迎 转发 点赞 与 关注,我会经常与大家分享前端的知识点的】

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表
最新留言