遇到的问题
最近入了 springMVC 的坑,今天在写接口的时候,后端需要接收前端传递的一个字符串数组来批量删除类别,照常写出如下代码:
1 | "delete.do") ( |
1 | let stringArray = ['17'] |
发现上面logger.info
打印出来的数组一直为空,前端采用 axios 来发送请求,但是不管怎么尝试就是接收不到前端传递过来的字符串,改用单纯数组接收参数或者 ArrayList 也一样的。
发现问题原因
之后通过查阅资料发现,axios 默认的 content-type 是 application/json, 这里后端需要用 formdata 的方式,后端才能获取到数据。
问题本到这里就结束了,但是我除了文件上传之类的,通常不太喜欢通过 formdata 的方式提交数据,SO,我认为应该还有别的解决方式。然后导致接下来踩了更多的坑,但是也收获了很多。
解决方案
方案一
方案一就是上面提到的,修改 axios 提交数据时候的 content-type 为 formdata,这个方案后端不需要改动,必须使用(@RequireParam(“idArray[]”) String[] idArray) 接收。
其它提交方式:
使用表单提交: 无法直接使用表单提交,需要转换成jq.ajax等方式提交
使用jq.ajax提交: 直接提交
方案二
indices 索引方式,前端通过 qs 修改 axios 的序列化方式为 indices,即:
1 | example: ?a[0]=1&a[1]=2&a[2]=3 |
后端比较麻烦,需要在 Controller中 注入一个实体,实体里包含List a,类似于方案三的 @RequestBody 方式,但不需要 @RequestBody 注解。
其它提交方式:
使用表单提交: 直接提交
使用jq.ajax提交: 需要自己处理后提交
方案三
后端改为 @RequestBody 的接收参数方式,然后新建一个 DTO实体类接收参数:
1 | public ServerResponse deleteCategory(@RequestBody ProductCategoryDTO categoryIdArray) { |
这里 ProductCategoryDTO 为 DTO实体类,里面就一个私有变量 List
这个方案前端直接用 axios 的 post 方法通过 data 传递字符串数组即可。
一般我在项目中复杂的参数接收,后端都采用这个方式接收参数,但是这里只传递一个数组,我就没有采用该方案。
其它提交方式:
使用表单提交: 直接提交,但是必须修改 content-type 为 application/json
使用jq.ajax提交: 直接提交
方案四
repeat 方式,后端修改接收参数方式为:
1 | public ServerResponse deleteCategory(@RequestParam(value = "idArray", defaultValue="") List<String> categoryIdArray) |
乍一看好像跟第一种方案没差,细心一看,你可以发现少了”[]”,这时候后端需要接收的数组传值方式为:
1 | ?a=1&a=2&a=3 |
前端需要修改 axios 的序列化方式为 repeat:
1 | axios.defaults.paramsSerializer = function (params) { |
通过查阅 qs 的文档可以发现,有4种序列化方式可以改变数组的输出格式:
1 | qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'indices' }) |
其它提交方式:
使用表单提交:无法直接使用表单提交,需要转换成jq.ajax等方式提交
使用jq.ajax提交: jq.ajax提交的时候需要设置属性: traditional:true