http传参的改进思路
后台语言Java, 基于Servlet规范
前端语言js
1. 普通参数
Map map = request.getParameterMap(); 返回值类型为 Map<String,String[]>
http规范本身可以传递多个相同name的键值
如: $protocol://$ip:$port?name=zhang&name=tian&name=xiao
这个map, key就是表单控件的name, 但value却是一个数组, 而非字符串
而我所知道的, 见过的 xhr请求代码, 更多的是传递json对象, value肯定是个字符串,
不曾考虑value为数组的场景, 可能是因为在过去很长的时间内mysql都不支持数组类型?
间接导致了使用Mysql的程序员也不考虑使用数组类型, 要知道 json不是类型规范
, 但数组是
下边我将用js原生代码收集一个form表单内所有的键值
html:
<form>
<input type="text" name="a" value="1">
<input type="password" name="b" value="2">
<input type="hidden" name="c" value="1">
<input type="hidden" name="d" value="1">
<input type="hidden" name="d" value="2">
<input type="radio" name="e" value="1" checked>
<input type="radio" name="e" value="2">
<input type="radio" name="e" value="3">
<input type="checkbox" name="f" value="1" checked>
<input type="checkbox" name="f" value="2">
<input type="checkbox" name="f" value="3">
<select name="g">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<select name="h" multiple>
<option value="1" selected>1</option>
<option value="2" selected>2</option>
<option value="3">3</option>
</select>
<textarea name="i" cols="30" rows="10">i</textarea>
<br>
<button id="btn" type="button">查看参数</button>
</form>
javascript:
/*
有的表单控件 提交时若值为''则不传递, 添加 if_empty_not_transfer 属性即可
* */
document.getElementById("btn").addEventListener('click', function () {
getFormDataV1(document.querySelector('form'))
})
function getFormDataV1(form_element) {
var elements = form_element.elements;
// set , es6的东东, 会有兼容性问题
var names = new Set();
// 先获取表单内所有表单元素的name值
for (var o of elements) {
names.add(o.name)
}
var kvs = {};
for (var name of names) {
// name为空则跳过
if (name === '') continue;
var element = elements[name];
// console.log(elements[name])
// 单个的 input控件, 文本框, 密码框, radio, checkbox
if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement) {
let value = element.value;
//value 为空字符串, 且存在 if_empty_not_transfer 属性, 不传输
if (value === '' && element.getAttribute('if_empty_not_transfer') != null) {
} else {
kvs[name] = value;
}
}
// 多个同名radio 或 同名checkbox 或 同名input[type="hidden"] 或同名textarea
else if (element instanceof RadioNodeList) {
// console.log(element)
var arr = [];
for (var x of element) {
// 单选
if (x.type === 'radio') {
// 选中
if (x.checked) {
kvs[name] = x.value;
// return
break;
}
}
//
else if (x.type === 'checkbox') {
if (x.checked) {
//value 为空字符串, 且存在 if_empty_not_transfer 属性, 不传输
if (x.value === '' && x.getAttribute('if_empty_not_transfer') != null) {
} else {
arr.push(x.value)
}
}
} else {
//value 为空字符串, 且存在 if_empty_not_transfer 属性, 不传输
if (x.value === '' && x.getAttribute('if_empty_not_transfer') != null) {
} else {
arr.push(x.value)
}
}
}
// 若在单选且选中那一步已赋值, 这里不再赋值
if (kvs[name]) {
} else {
kvs[name] = arr;
}
}
// select 标签
else if (element instanceof HTMLSelectElement) {
// console.log(element)
if (element.multiple) {
kvs[name] = [];
for (let opt of element.selectedOptions) {
kvs[name].push(opt.value)
}
} else {
kvs[name] = element.value
}
}
}
console.log(JSON.stringify(kvs, ' ', ' '))
return kvs;
}
结果
{
"a": "1",
"b": "2",
"c": "1",
"d": [
"1",
"2"
],
"e": "1",
"f": [
"1"
],
"g": "1",
"h": [
"1",
"2"
],
"i": "i"
}
2. 发送Ajax请求
http请求必要的method只有三种, get, post 和 option
get传输小体积数据, 反之用post
option仅在跨域时作为试探性请求, 由浏览器发出
关于浏览器ajax的对象和方法, 如XMLHttpRequest 或 Fetch, 这里不细说, 我们需要关心的东西越少越好,
关于兼容性, 请求进度, 超时处理等, 会有jquery.ajax 或 axios 替我们封装并提供更加人性化的方法
我们还需要做的就是把上一小节中结果的json对象, 转换为 get url
, 或 post FormData
, 然后交由 jquery.ajax 或 axios
3. 上传文件
我个人非常不建议将其他参数
和文件上传
放在同一个请求当中, post请求, 想要获取其他参数, 就必须解析完整的http请求, 包括文件数据,
当需要对其他参数进行校验, 这段时间文件数据会白白占用内存