{username: "admin", password: "admin"}
我们同样的用jquery的ajax把我们这个请求同样的发送一遍
发现Request-Headers的**Content-Type是application/x-www-form-urlencoded;charset=UTF-8**,URL encode为
username=admin&password=admin
到这里,由于是前端换了一个发送ajax请求的工具,导致从前的接口不能用了,后端朋侪们首先想到的就是我们前端人员写错了,然后我们就要开始苦逼的研究了。
可以看出,两个请求唯一的不同就是**Content-Type**的问题,朋侪们,是Request Headers中的Content-Type哈,不是Response中的哈,不要搞错了。
那不同点找到了,那我们就可以开始搞了,我们大胆的猜想,假如把axios的post请求的Content-Type也酿成**application/x-www-form-urlencoded**,那么问题想必就迎刃而解了。
我们看看axios的源码
axios.create = function create(instanceConfig) { return createInstance(utils.merge(defaults, instanceConfig)); };
create方法就是把我们传入的参数和默认参数合并,然后创建一个axios实例,我们再看看defaults这个配置对象
var utils = require('./utils'); var normalizeHeaderName = require('./helpers/normalizeHeaderName'); /* 这个表明默认的Content-Type就是我们想要的 */ var DEFAULT_CONTENT_TYPE = { 'Content-Type': 'application/x-www-form-urlencoded' }; /* 看方法名就知道,这个是设置ContentType用的(Content-Type没有设置的时候) */ function setContentTypeIfUnset(headers, value) { if (!utils.isUndefined(headers) && utils.isUndefined(headers['Content-Type'])) { headers['Content-Type'] = value; } } /* 这个是用来区别对待浏览器和nodejs请求发起工具的区别的 */ function getDefaultAdapter() { var adapter; if (typeof XMLHttpRequest !== 'undefined') { // For browsers use XHR adapter adapter = require('./adapters/xhr'); } else if (typeof process !== 'undefined') { // For node use HTTP adapter adapter = require('./adapters/http'); } return adapter; } /* 这里终于看到了万众期待的默认配置 */ var defaults = { adapter: getDefaultAdapter(), /* 这个transformRequest配置就厉害了 * 官方形貌`transformRequest` allows changes to the request data before it is sent to the server * 这个函数是接受我们通报的参数,而且在发送到服务器前,可以对其进行更改 * */ transformRequest: [function transformRequest(data, headers) { normalizeHeaderName(headers, 'Content-Type'); if (utils.isFormData(data) || utils.isArrayBuffer(data) || utils.isStream(data) || utils.isFile(data) || utils.isBlob(data) ) { return data; } if (utils.isArrayBufferView(data)) { return data.buffer; } /* 关键点1、假如用URLSearchParams对象通报参数,就可以用我们想要的Content-Type通报 */ if (utils.isURLSearchParams(data)) { setContentTypeIfUnset(headers, 'application/x-www-form-urlencoded;charset=utf-8'); return data.toString(); } /* 关键点2、这里我们看到,假如参数Object的话,就是通过json通报 */ if (utils.isObject(data)) { setContentTypeIfUnset(headers, 'application/json;charset=utf-8'); return JSON.stringify(data); } return data; }], transformResponse: [function transformResponse(data) { /*eslint no-param-reassign:0*/ if (typeof data === 'string') { try { data = JSON.parse(data); } catch (e) { /* Ignore */ } } return data; }], timeout: 0, xsrfCookieName: 'XSRF-TOKEN', xsrfHeaderName: 'X-XSRF-TOKEN', maxContentLength: -1, validateStatus: function validateStatus(status) { return status >= 200 && status < 300; } }; defaults.headers = { common: { 'Accept': 'application/json, text/plain, */*' } }; utils.forEach(['delete', 'get', 'head'], function forEachMethodNoData(method) { defaults.headers[method] = {}; }); utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) { defaults.headers[method] = utils.merge(DEFAULT_CONTENT_TYPE); }); module.exports = defaults;
通过上面的源码注解,我们找到了动手点:
- 用URLSearchParams通报参数
- 改写transformRequest
很显然,假如我们不是通过axios.create方法创建实例,再拿来调用,我们就只能采用第一种解决办法
第一种方法解决方案
改写userService
import axios = import('axios'); let param = new URLSearchParams(); param.append("username", "admin"); param.append("password", "admin"); export async function () { axios.post('/api/doLogin', param) }
果不其然,这就成功了。
假如不想用URLSearchParams,还是以为Json方便,那么我们可以重新配置transformRequest
第二种方法解决方案
改写axios的create的配置
import axios from 'axios'; // 这里我自己重写了一下范例判断的所有方法,固然也可以用util库 import { isFormData, isArrayBuffer, isStream, isFile, isBlob, isURLSearchParams, isObject, isUndefined } from './Type'; function setContentTypeIfUnset(headers, value) { if (!isUndefined(headers) && isUndefined(headers['Content-Type'])) { headers['Content-Type'] = value; } } const instance = axios.create({ baseURL: '/ghcws', timeout: 10000, transformRequest: [function transformRequest(data, headers) { /* 把类似content-type这种改成Content-Type */ let keys = Object.keys(headers); let normalizedName = 'Content-Type'; keys.forEach(name => { if (name !== normalizedName && name.toUpperCase() === normalizedName.toUpperCase()) { headers[normalizedName] = headers[name]; delete headers[name]; } }); if (isFormData(data) || isArrayBuffer(data) || isStream(data) || isFile(data) || isBlob(data) ) { return data; } if (isURLSearchParams(data)) { setContentTypeIfUnset(headers, 'application/x-www-form-urlencoded;charset=utf-8'); return data.toString(); } /* 这里是重点,其他的其实可以照着axios的源码抄 */ /* 这里就是用来解决POST提交json数据的时候是直接把整个json放在request payload中提交过去的情况 * 这里简单处置处罚下,把 {name: 'admin', pwd: 123}这种转换成name=admin&pwd=123就可以通过 * x-www-form-urlencoded这种方式提交 * */ if (isObject(data)) { setContentTypeIfUnset(headers, 'application/x-www-form-urlencoded;charset=utf-8'); let keys2 = Object.keys(data); /* 这里就是把json酿成url情势,并进行encode */ return encodeURI(keys2.map(name => `${name}=${data[name]}`).join('&')); } return data; }] }); export default instance;
固然不用create方法也是可以通过修改axios.defaults.transformRequest实现相同结果。
那么现在问题虽然解决了,但是为什么之前后端就是接收不到json范例的参数呢???
自我先容一下,小编13年上海交大结业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里不绝到现在。
深知大多数Java工程师,想要提升技能,每每是自己摸索发展或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学结果低效又漫长,而且极易碰到天花板技能停滞不前!
因此网络整理了一份《2024年Java开辟全套学习资料》,初志也很简单,就是盼望能够帮助到想自学提升又不知道该从何学起的朋侪,同时减轻大家的负担。
既有适合小白学习的零底子资料,也有适合3年以上履历的小伙伴深入学习提升的进阶课程,根本涵盖了95%以上Java开辟知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点内里都包含大厂面经、学习笔记、源码讲义、实战项目、解说视频,而且后续会持续更新
假如你以为这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
近来我根据上述的技能体系图搜集了几十套腾讯、头条、阿里、美团等公司21年的口试题,把技能点整理成了视频(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的情势给大家展示一部分
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码到场我们的的圈子(技能交换、学习资源、职场吐槽、大厂内推、口试辅导),让我们一起学习发展!
]
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码到场我们的的圈子(技能交换、学习资源、职场吐槽、大厂内推、口试辅导),让我们一起学习发展!
[外链图片转存中…(img-68P4oslu-1712698936668)]
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |