目录
1.问题背景:
我在接口开发过程中,前端发送请求后,后端始终无法接收到参数。这导致前端无法获取预期的响应数据,或返回的数据与实际需求不符。经过排查,发现问题的根源在于前端与后端参数名称不一致,造成后端无法正确解析请求中的参数。
(1).前端代码:
页面:
<template>
<Dialog :visible="info" :title="info.title" @close="emit('cancel')" @save="onSave">
<el-table ref="multipleTable" :data="allPermissions" row-key="rid" @selection-change="onSelectionChange">
<el-table-column type="selection" />
<el-table-column label="权限名" prop="permissionName" />
<el-table-column label="资源路径" prop="url" />
</el-table>
</Dialog>
</template>
<script setup>
import { onMounted, ref } from 'vue'
import { Dialog } from '@/components';
import { ElMessage } from 'element-plus';
// 导入提取的API请求函数
import { getAllPermissions, updateRolePermissions } from '@/api/role'
const { info } = defineProps(['info'])
const emit = defineEmits(['cancel'])
const multipleTable = ref(null)
let pids = []
const allPermissions = ref([])
onMounted(() => {
// 获取所有权限 - 使用新的API请求函数
getAllPermissions().then(data => {
allPermissions.value = data;
(info.data.permissions || []).map(row => {
pids.push(row.pid)
setTimeout(() => {
// 默认选中该角色拥有的权限
const target = allPermissions.value.find(item => item.pid === row.pid)
if (target) {
multipleTable.value.toggleRowSelection(target, true);
}
}, 0)
})
})
})
const onSelectionChange = (keys) => {
pids = keys.map(item => item.pid)
}
const onSave = () => {
const form = new FormData()
form.append('rid', info.data.rid)
form.append('pids', pids)
// 更新角色权限 - 使用新的API请求函数
updateRolePermissions(form).then(() => {
ElMessage.success('操作成功')
emit('cancel')
})
}
</script>
封装的请求:
/**
* 为角色更新权限
* @param {Object} data - { rid: number, pids: number[] }
* @returns {Promise}
*/
export function updateRolePermissions(data) {
return request({
url: '/api/role/updatePermissionToRole',
method: 'put',
params: {
rid: data.rid,
pids: data.pids
} // 直接传递JSON对象
})
}
(2).后端代码:
@PutMapping("/updatePermissionToRole")
@PreAuthorize("hasAnyAuthority('/api/role/updatePermissionToRole')")
public Result updatePermissionToRole(@RequestParam Integer rid,@RequestParam Integer[] pids){
userRoleService.updatePermissionToUserRole(rid,pids);
return Result.success(null);
}
(3).问题分析:
前端代码和后端接口存在参数格式不匹配的问题
[1]前端参数构造错误:
const form = new FormData()
form.append('rid', info.data.rid)
form.append('pids', pids) // 错误:将数组直接作为值添加
这会导致:
pids
参数被序列化为字符串"[object Object]"
- 后端接收到的
pids
为null
,触发空指针异常
[2].Api请求配置错误:
export function updateRolePermissions(data) {
return request({
url: '/api/role/updatePermissionToRole',
method: 'put',
params: { // 错误:params会被拼接到URL,且无法正确处理数组
rid: data.rid,
pids: data.pids
}
})
}
这会导致:
- 请求 URL 被构造为
/api/role/updatePermissionToRole?rid=1&pids=1,2,3
- Spring MVC 无法将
pids=1,2,3
正确解析为整数数组
2.解决方案
(1).修改 role.js
中的 API 方法
/**
* 为角色更新权限
* @param {Object} data - { rid: number, pids: number[] }
* @returns {Promise}
*/
export function updateRolePermissions(data) {
// 构建查询字符串参数
const params = new URLSearchParams();
params.append('rid', data.rid);
// 将数组转换为多个同名参数
if (data.pids && Array.isArray(data.pids)) {
data.pids.forEach(pid => {
params.append('pids', pid);
});
}
return request({
url: '/api/role/updatePermissionToRole',
method: 'put',
params: params, // 注意:使用params而非data
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
});
}
(2).前端组件中的调用方式改成下面的而不是继续拼接了
// 组件中的调用代码保持不变
const onSave = () => {
updateRolePermissions({
rid: info.data.rid,
pids: pids // 直接传递数组
}).then(() => {
ElMessage.success('操作成功');
emit('cancel');
});
};
3.总结:
前端开发中严格遵守接口规范能有效避免参数传递错误。数组类型参数需特殊处理,确保与后端接口定义一致。
后端使用@RequestParam
注解时,前端请求需明确设置params
配置。数组参数应拆分为单个数值传递,避免直接传递数组对象。
组件调用遵循方法传参模式,确保参数类型和结构与后端接口匹配。开发过程中定期联调测试,及时发现参数不一致问题。
建议建立统一接口文档规范,明确参数类型和格式要求。前后端团队保持密切沟通,从源头减少参数定义差异。