简单总结一下常用的传参方式,一些前后端分离项目接口调试时经常出现传参格式错误问题。
前后端进行交互时方法一般就分为get和post,至于后面的delete和put都是基于post进行封装而出的。
Http请求中不同的请求方式会设置不同的Content-Type,参数的传递方式就会不一样,主要分为以下三种:Query String Parameters
、Form Data
、Request Payload
;
下面使用的axios请求都是经过封装的,文章最后有对应的封装方法
GET请求
我们发送get请求时,参数是通过url的形式进行传递,即url中?后面拼接的参数,以&做连接,参数直接表现在url中。
例如:http://localhost:8801/api/selectDetail?id=1&userName="zhang"
前端通过query String parameters
方式传参,axios中指明使用params
export function selectList(params) {return request({url: 'api/xxx/selectList',method: 'get',params})
}
POST请求
Post请求有两种传递参数的形式:form data
和request payload
的形式
发起post请求时若未指定content-type,则默认content-type为application/x-www-form-urlencoded
,参数是在请求体中,参数以form data的形式传递,不会出现在请求的url中。
若content-type为application/json,则参数会以request payload的形式进行传递,数据格式为json形式,请求表单的参数在request payload中,不会出现在请求的url中,使用原生的Ajax post请求不指定请求头默认的参数就是出现在request payload中。
前端通过formData
方式传参,axios中指明使用data
export function selectList(data) {return request({url: 'api/xxx/selectList',method: 'post',data})
}
前端通过request payload
方式传参
export function selectList(data) {return request({url: 'api/xxx/selectList',method: 'post',data})
}
SpringBoot注解对应传参方式
@RequestParam()
默认接收application/x-www-form-urlencoded
编码格式的参数
@RequestBody()
默认接收json
格式的参数
- spring通过
@requestParam (queryParam)
(路径传参-默认传参注解)接收的参数都是url拼接 将参数放到query String parameters,前端可以通过下面三种方式传参- params 传参 (推荐) – params
- formData传参 – data (需要修改Content-Type)
- Qs传参 – data ,需要手动处理header “Content-Type”: “application/x-www-form-urlencoded”
spring boot接口
@GetMapping(value = "/hello")public ResponseEntity getUser(@RequestParam String username){
}
//http://lcoalhost:8080/hello?username=1111
axios调用
#params 传参
export function find(params){return request({url: `${API}/info/find`,method: 'get',params:params})
}
- spring通过
@requestBody
,通过post提交消息主体中参数,参数值为json格式,默认就是json格式不需要进行处理
- 通过data传参
springboot 接口
@PostMapping
public ResponseEntity<Record> add(@RequestBody Record record) {return ResponseEntity.ok(this.recordService.insert(record));
}
axios调用方法(这里的axios是经过封装后的)
export function add(data){return request({url: `${API}/record/add`,method: 'post',data})
}
请求信息:
POST http://localhost:5138/record/
Content-Type: application/json
--- 参数内容
{"objective": 1.0,"objRate": 1.0,"objDate": "2022/1/8 12:05:00","outputPrice": 1.0,
}
@pathVariable(@pathParam)
url路径中参数
- 拼接url
springboot接口
@DeleteMapping(value = "/job/{id}")public ResponseEntity delete(@PathVariable(value = "id", required = false, defaultValue = "0") Long id){
}
//http://localhost:8080/job/1
axios调用
export function queryById(id){return request({url: `${API}/info/queryById/${id}`,method: 'get'})
}
axios对应的封装方法
// 封装axios:使用请求与响应拦截器
import axios from 'axios'
import { ElMessage, ElMessageBox } from 'element-plus'
// 引入qs
import qs from 'qs'
import useUserStore from '@/store/modules/user'// 利用axios对象的create方法,创建axios实例(其他的配置:基础路径、超时时间)
const service = axios.create({//基础路径baseURL: '/',timeout: 5000, // 超时时间的设置
})
// 第二步:request实例添加请求与响应拦截器
service.interceptors.request.use((config) => {// 获取用户仓库内的token,登录成功后携带公共参数let userStore = useUserStore()if(userStore.token) {config.headers['Authorization'] = userStore.token}return config
})// 第三步:配置相应拦截器
service.interceptors.response.use((response) => {// 获取返回成功数据的状态码code和错误信息messageconst { code, message } = response.data;if(code) {// 有状态码判断是否为200,除此皆为异常响应if(code == 200) {return response.data}else if (code < 200 || code > 300) {ElMessage({message: message || '系统出错',type: 'error'});return Promise.reject('error')}else {// 其他类型的状态码ElMessage.error(message)return Promise.reject(response.data)}} else {// 未返回状态码直接返回响应信息ElMessage.error('系统服务连接失败')return Promise.reject(response)}},(error) => {// 失败的回调:处理http网络错误//定义一个变量:存储网络错误信息let message = ''if(error.code === 'ECONNABORTED') {message = '连接超时中止,请稍后重试!'} else {// http状态码const status = error.response.statusswitch (status) {case 401:message = '无权访问'breakcase 404:message = '请求地址错误'breakdefault:message = '网络出现问题'break}}// 提示错误信息ElMessage({type: 'error',message,})return Promise.reject(error)},
)// 利用axios对象的create方法,创建axios实例(其他的配置:基础路径、超时时间)
interface ReqParamsType {url:stringdata?: anyparams?:anymethod?:string,type?:stringtimestamp?:booleantimeout?:number
}
const request = ({url,data,params,method= 'post',type='json',timestamp = false,timeout,}:ReqParamsType): Promise<T> => {let config = {method,url,baseURL: '/',withCredentials: true,responseType: 'json',headers: {'Access-Control-Allow-Origin': '*','X-Requested-With': 'XMLHttpRequest'},timestamp: timestamp,timeout: timeout};if (method === 'get') {if (timestamp) {config.url += config.url.indexOf('?') > 0 ? '&' : '?';config.url += `timestamp=${+new Date()}`;}Object.assign(config, {params});}else {if (type === 'form') {config.headers['Content-Type'] = 'application/x-www-form-urlencoded';Object.assign(config, {data: qs.stringify(data)});config.url = config.url+'?'+qs.stringify(data)} else if (type === 'json') {config.headers['Content-Type'] = 'application/json';Object.assign(config, {data: data});} else if (type === 'formData') {let formData = new FormData();for (let i in data) {if(data[i] != null) {formData.append(i, data[i]);}}config.headers['Content-Type'] = 'multipart/form-data';Object.assign(config, {data: formData});}else if(type === 'picture'){config.headers['Content-Type'] = 'application/x-www-form-urlencoded';Object.assign(config, {data: data});}if(timestamp) {const code = `${(new Date()).getTime()}_${Math.round(Math.random()*10000)}`}}return new Promise((resolve, reject) => {service(config).then((response) => {resolve(response);}, (error) => {reject(error);}).catch((error) => {reject(error);});});
}
// 对外暴露
export default request