1. 程式人生 > 其它 >POST和PUT一個比較冷門的區別(自認為)

POST和PUT一個比較冷門的區別(自認為)

當使用ajax傳送POST請求時,data中的資料除字母以外其他會被瀏覽器轉碼成url編碼格式

而PUT請求不會轉碼

後續測試證明,GET和HEAD請求也會轉碼,但是PATCH、UPDATE、DELETE這三個請求也不會將 data 資料轉碼

再之後的測試又發現我測試OPTIONS請求的時候把 ‘S’ 漏了,但是仍然能被Controller接收到,並且資料也沒有被轉碼

之後我猜測ajax請求的type可以自定義,並且能被Controller接收到,所以將 ajax 的 type定義為了 "test"

很奇怪,而且使用這些type(或者叫method)不會將data轉碼,並不是很懂這一部分的原理是什麼,但是記錄一下

2021年7月11日 更新 ---- 大概是破案了

在之前寫的ajax請求中,我只指定了 dataType 引數,即只約束了返回值為json,

 1 $.ajax({
 2         url: url,
 3         type: "POST",
 4         async: false,
 5         data: JSON.stringify(smsData),
 6         dataType: "JSON",
 7         success: function (res) {
 8             status = res.status;
9 }, 10 error: function (res) { 11 status = res.status; 12 } 13 })

但是contentType並沒有約束為json,

1         contentType:'application/json',

所以傳送get和post請求的時候瀏覽器把我的data引數整體當做一個沒有value的key了,這也是我在後臺接收到的post和get請求的值最後面有一個等號的原因

/*** @modifyType 修改型別標記* 100000 修改密碼* 100001 修改手機* 100002 修改郵箱* 100003 修改暱稱*/var modifyType = 100000;var recipient;
// 計時相關var isVerifyBtnTiming = false;var isModifyBtnTiming = false;var clock_second = 60;
// 模態框的響應式樣式if (document.body.clientWidth <= 576) { $('.modal-dialog').toggleClass("modal-dialog-centered")} else { $('.modal-dialog').toggleClass("")}
$('#verifyModal').on('show.bs.modal', function (event) { var button = $(event.relatedTarget); recipient = button.data('whatever'); var verifyOption = $('#verify-type>option'); var isPhoneBind = false, isMailBind = false;
/*設定身份驗證選單*/ /*手機*/ if (sessionStorage.getItem("uPhone") == null) { isPhoneBind = false verifyOption[0].className = verifyOption[0].className.replace('d-block', 'd-none'); verifyOption[0].selected = false; verifyOption[0].innerHTML = ""; } else { isPhoneBind = true; verifyOption[0].className = verifyOption[0].className.replace('d-none', 'd-block'); verifyOption[0].innerHTML = hideVerifyString(sessionStorage.getItem("uPhone").trim(), "phone"); verifyOption[0].selected = true; } /*郵箱*/ if (sessionStorage.getItem("uMail") == null) { isMailBind = false verifyOption[1].className = verifyOption[1].className.replace('d-block', 'd-none'); verifyOption[1].selected = false; verifyOption[1].innerHTML = ""; } else { isMailBind = true verifyOption[1].className = verifyOption[1].className.replace('d-none', 'd-block'); verifyOption[1].innerHTML = hideVerifyString(sessionStorage.getItem("uMail"), "mail"); verifyOption[1].selected = !isPhoneBind; }
/*通過變數isPhoneBind, isMailBind判斷是否未繫結手機郵箱,如果都沒有繫結則跳過身份驗證*/ if (!isPhoneBind && !isMailBind) { // $('#verify-type')[0].remove('option'); $('#toBind')[0].className = $('#toBind')[0].className.replace("d-none", "d-block"); // $('#verify-thrid-btn')[0].className = $('#verify-thrid-btn')[0].className.replace("btn-primary", "btn-secondary"); $('#btn-verifyModal-submit')[0].className = $('#btn-verifyModal-submit')[0].className.replace("btn-primary", "btn-secondary"); // $('#verify-thrid-btn')[0].style.cursor = "not-allowed"; $('#btn-verifyModal-submit')[0].style.cursor = "not-allowed"; } else { // $('#verify-thrid-btn')[0].style.cursor = "pointer"; $('#btn-verifyModal-submit')[0].style.cursor = "pointer"; // $('#verify-thrid-btn')[0].className = $('#verify-thrid-btn')[0].className.replace("btn-secondary", "btn-primary"); $('#btn-verifyModal-submit')[0].className = $('#btn-verifyModal-submit')[0].className.replace("btn-secondary", "btn-primary"); }});$('#modifyModal').on('show.bs.modal', function (event) { var button = $(event.relatedTarget); recipient = !button.data('whatever') ? recipient : button.data('whatever'); var modal = $(this); var modalBtn = $("#modifyModal .form-group input[type='button']"); var modalText = $("#modifyModal .form-group input[type='text']"); var modalTip = $("#modifyModal .modal-tip"); var modalTipP = $("#modifyModal .modal-tip>p"); var modalTipSpan = $("#modal-thrid-tip span"); var modalTipSwitch = $("#modal-thrid-tip a")[0]; modal.find('.modal-title').text(recipient); $('#modal-first-text')[0].className = $('#modal-first-text')[0].className.replace("border-danger", "border-gray"); $('#modal-second-text')[0].className = $('#modal-first-text')[0].className.replace("border-danger", "border-gray"); $('#modal-thrid-text')[0].className = $('#modal-first-text')[0].className.replace("border-danger", "border-gray"); switch (recipient) { case "修改密碼": //將樣式切換為修改密碼對應的樣式 modalBtn[0].className = modalBtn[0].className.replace("d-block", "d-none"); //隱藏第二行的功能按鈕 modalBtn[1].className = modalBtn[1].className.replace("d-block", "d-none"); //隱藏第三行的功能按鈕 modalText[0].readOnly = false; //取消第一行的文字框的只讀屬性 modalText[1].className = modalText[1].className.replace("w-65", "w-100"); //把第二行的文字框還原到100%寬度 modalText[2].className = modalText[2].className.replace("w-65", "w-100"); //把第三行的文字框還原到100%寬度 modalTip[0].className = modalTip[0].className.replace("d-block", "d-none"); //隱藏第二行的資訊提示框 modalTip[1].className = modalTip[1].className.replace("d-block", "d-none"); //隱藏第三行的資訊提示框
//更改文字輸入框的提示文字 modalText[0].placeholder = "原密碼"; modalText[1].placeholder = "新密碼"; modalText[2].placeholder = "確認密碼"; modifyType = 100000; break; case "修改手機": //將樣式切換為修改手機對應的樣式 modalBtn[0].className = modalBtn[0].className.replace("d-block", "d-none"); //隱藏第二行的功能按鈕 modalBtn[1].className = modalBtn[1].className.replace("d-none", "d-block"); //顯示第三行的功能按鈕 modalText[0].readOnly = true; //新增第一行的文字框的只讀屬性 modalText[1].className = modalText[1].className.replace("w-65", "w-100"); //把第二行的文字框還原到100%寬度 modalText[2].className = modalText[2].className.replace("w-100", "w-65"); //把第三行的文字框設定為65%寬度 modalTip[0].className = modalTip[0].className.replace("d-block", "d-none"); //隱藏第二行的資訊提示框 modalTip[1].className = modalTip[1].className.replace("d-block", "d-none"); //隱藏第三行的資訊提示框
//更改文字輸入框的提示文字 modalText[0].placeholder = sessionStorage.getItem("uPhone") == null ? "" : sessionStorage.getItem("uPhone"); //要做判斷,存在就設定為使用者的舊手機,不存在就把文字設定為“未繫結” modalText[1].placeholder = "新手機"; modalText[2].placeholder = "請輸入驗證碼"; modifyType = 100001; break; case "修改郵箱": //將樣式切換為修改郵箱對應的樣式 modalBtn[0].className = modalBtn[0].className.replace("d-block", "d-none"); //隱藏第二行的功能按鈕 modalBtn[1].className = modalBtn[1].className.replace("d-none", "d-block"); //顯示第三行的功能按鈕 modalText[0].readOnly = true; //新增第一行的文字框的只讀屬性 modalText[1].className = modalText[1].className.replace("w-65", "w-100"); //把第二行的文字框還原到100%寬度 modalText[2].className = modalText[2].className.replace("w-100", "w-65"); //把第三行的文字框設定為65%寬度 modalTip[0].className = modalTip[0].className.replace("d-block", "d-none"); //隱藏第二行的資訊提示框 modalTip[1].className = modalTip[1].className.replace("d-block", "d-none"); //隱藏第三行的資訊提示框
//更改文字輸入框的提示文字 modalText[0].placeholder = sessionStorage.getItem("uMail") == null ? "" : sessionStorage.getItem("uMail"); //要做判斷,存在就設定為使用者的舊郵箱,不存在就把文字設定為“未繫結” modalText[1].placeholder = "新郵箱"; modalText[2].placeholder = "請輸入驗證碼"; modifyType = 100002; break; case "修改暱稱": //將樣式切換為修改暱稱對應的樣式 modalBtn[0].className = modalBtn[0].className.replace("d-none", "d-block"); //隱藏第二行的功能按鈕 modalBtn[1].className = modalBtn[1].className.replace("d-none", "d-block"); //顯示第三行的功能按鈕 modalText[0].readOnly = true; //新增第一行的文字框的只讀屬性 modalText[1].className = modalText[1].className.replace("w-100", "w-65"); //把第二行的文字框還原到100%寬度 modalText[2].className = modalText[2].className.replace("w-100", "w-65"); //把第三行的文字框設定為65%寬度 modalTip[0].className = modalTip[0].className.replace("d-block", "d-none"); //隱藏第二行的資訊提示框 modalTip[1].className = modalTip[1].className.replace("d-none", "d-block"); //顯示第三行的資訊提示框
// 設定暱稱修改時的校驗方式 modalTipP[0].innerHTML = "向" modalTipP[1].innerHTML = "傳送驗證碼, " modalTipSwitch.innerHTML = "切換驗證方式" if (sessionStorage.getItem("uMail") != "") { modalTipSpan.attr("data-title", "mail") modalTipSpan[0].innerHTML = hideVerifyString(sessionStorage.getItem("uMail"), "mail"); } else if (sessionStorage.getItem("uPhone") != "") { modalTipSpan.attr("data-title", "phone") modalTipSpan[0].innerHTML = hideVerifyString(sessionStorage.getItem("uPhone"), "phone"); } else { modalTipP[0].innerHTML = "" modalTipP[1].innerHTML = "" modalTipSwitch.innerHTML = "" modalTipSpan.attr("data-title", "") modalTipSpan[0].innerHTML = "請先繫結驗證手機或郵箱"; }
//更改文字輸入框的提示文字 modalText[0].placeholder = sessionStorage.getItem("uNickName")==null ? "" : sessionStorage.getItem("uNickName"); //將文字設定為使用者的舊暱稱, modalText[1].placeholder = "新暱稱"; modalText[2].placeholder = "請輸入驗證碼"; modifyType = 100003; break; }});
$('#modifyModal').on('hidden.bs.modal', function (event) { // 模態框退出行為 $('#modifyModal input[type=text]').val("") // 模態框退出時清空輸入框的內容});
// 身份驗證模態框 - 獲取驗證碼,$('#verify-thrid-btn').click(function () { if (!isVerifyBtnTiming) { let verify_option = $("#verify-type>option"); let data = {}; let verify_type; if (verify_option[0].selected && !verify_option[1].selected) { data.to = sessionStorage.getItem("uMail"); verify_type = 0; } else if (verify_option[1].selected && !verify_option[0].selected) { data.to = sessionStorage.getItem("uPhone"); verify_type = 1; } let resCode = sendCode(verify_type, data); if (resCode === "100000") { // 傳送成功 timer(this, "verify"); layer.msg("驗證碼已傳送, 請注意查收"); } else { layer.msg("驗證碼傳送失敗, 錯誤碼" + resCode); } }});// 資訊修改模態框 - 獲取驗證碼$('#modal-thrid-btn').click(function () { if (!isModifyBtnTiming) { sendCode(); timer(this, "modify"); }});// 身份驗證模態框 - submit$('#btn-verifyModal-submit').click(function () { // 繫結業務第一次身份驗證後的提交動作 if (this.style.cursor != "not-allowed") { var isCodePass = true; // 預設應該為false,現在除錯臨時改成true // ajax將使用者輸入的驗證碼傳送至伺服器校驗,結果用isCodePass儲存 if (isCodePass) { $('#verifyModal').modal('toggle'); $('#modifyModal').modal('toggle'); } else { // 提示“驗證碼錯誤” } }});// 資訊修改模態框 - submit$('#btn-modifyModal-submit').click(function () { switch (modifyType) { case 100000: // 校驗原密碼 var inputPassword = this.value; var isTruePWD = false; // ajax將使用者輸入的密碼傳到伺服器比對,需要傳使用者id、輸入的原密碼(inputPassword) // 伺服器建議做一次md5加密和一次MySQL的Password加密,即資料庫儲存password(md5("密碼原文")) if (isTruePWD) { // 通過原密碼校驗後執行下一個動作 $('#modal-first-text')[0].className = $('#modal-first-text')[0].className.replace("border-danger", "border-gray"); } else { // 未通過則將原密碼輸入框標紅警告 $('#modal-first-text')[0].className = $('#modal-first-text')[0].className.replace("border-gray", "border-danger"); } break; case 100001: case 100002: // 繫結業務第一次身份驗證後的提交動作 var isCodePass = true; // 預設應該為false,現在除錯臨時改成true // ajax將使用者輸入的驗證碼傳送至伺服器校驗,結果用isCodePass儲存 if (isCodePass) { break; // 通過break關鍵字跳出switch語句,從而執行修改操作 } else { // 提示“驗證碼錯誤”,然後return return } break; case 100003: break; }
var modifyResult = 110000; // 預設應該是無引數,這裡除錯將變數設定為"修改成功"的狀態碼 /* 通過ajax將modal-second-text的內容提交到伺服器,modify(content: modal-second-text, type: modifyType) 伺服器會返回修改結果(狀態碼),使用變數modifyResult儲存 */ if (modifyResult == 110000) { $('#modifyModal').modal('toggle'); } else { // 提示“修改失敗,錯誤碼xxxxxx” }});// 資訊修改模態框 - 密碼格式控制(6-16位)$('#modal-second-text').on('input', function () { var thisTip = $(this).siblings("#modal-second-tip")[0]; var thisElem = this; switch (modifyType) { case 100000: if (thisElem.value.length < 6) { thisTip.innerHTML = "密碼應設定為6-16位" thisTip.style.color = "red"; thisTip.className = thisTip.className.replace("d-none", "d-block"); thisElem.className = thisElem.className.replace("border-gray", "border-danger") } else { thisTip.className = thisTip.className.replace("d-block", "d-none"); thisElem.className = thisElem.className.replace("border-danger", "border-gray") } break; case 100003: break; }});// 資訊修改模態框 - 密碼確認$('#modal-thrid-text').on('input', function () { if (modifyType == "100000") { var thisTip = $(this).siblings("#modal-thrid-tip")[0]; var thisElem = this; var targetPwd = $('#modal-second-text')[0].value; if (this.value != targetPwd) { thisTip.innerHTML = "兩次輸入的密碼不一致" thisTip.className = thisTip.className.replace("d-none", "d-block"); thisElem.className = thisElem.className.replace("border-gray", "border-danger") } else { thisTip.className = thisTip.className.replace("d-block", "d-none"); thisElem.className = thisElem.className.replace("border-danger", "border-gray") } }});// 資訊修改模態框 - 暱稱修改(校驗可用性: 敏感詞、重複性、特殊字元)$('#modal-second-btn').click(function () { // var isAccess = "100001"; // 用於儲存校驗的結果,100000 可以使用,其他不可以使用(暫時設定為100000,當所有狀態碼設計完之後統一修改) var isAccess = $('#modal-second-text')[0].value; var inputNickName = $(this).siblings("#modal-second-text")[0]; var thisTip = $(this).siblings("#modal-second-tip")[0]; // 通過ajax提交到伺服器做校驗, 返回狀態碼,用變數isAccess儲存 switch (isAccess) { case "100000": thisTip.innerHTML = "暱稱可用"; thisTip.style.color = "green" thisTip.className = thisTip.className.replace("d-none", "d-block"); inputNickName.className = inputNickName.className.replace("border-danger", "border-success"); inputNickName.className = inputNickName.className.replace("border-gray", "border-success"); break; case "100001": thisTip.innerHTML = "已存在的暱稱"; thisTip.style.color = "red" thisTip.className = thisTip.className.replace("d-none", "d-block"); inputNickName.className = inputNickName.className.replace("border-success", "border-danger"); inputNickName.className = inputNickName.className.replace("border-gray", "border-danger"); }});// 資訊修改模態框 - 暱稱修改(驗證方式切換)$('#modal-thrid-tip > a').click(function () { var thisSpan = $('#modal-thrid-tip > span'); var currentType = thisSpan.attr("data-title"); if (currentType == "mail") { if (sessionStorage.getItem("account_phone") != "") { thisSpan[0].innerHTML = hideVerifyString(sessionStorage.getItem("account_phone"), "phone") thisSpan.attr("data-title", "phone") } } else if (currentType == "phone") { if (sessionStorage.getItem("account_mail") != "") { thisSpan[0].innerHTML = hideVerifyString(sessionStorage.getItem("account_mail"), "mail") thisSpan.attr("data-title", "mail") } } else { return; }});
// util functionfunction isTiming(obj) { var isTimeout = true; // 臨時改成true除錯按鈕倒計時功能 // ajax queryLastSendTime(send id: obj), obj為verify或modify,代表身份驗證或資訊修改的驗證碼傳送行為, 用變數isTimeout儲存查詢結果 return isTimeout}
function timer(elem, timingAction) { /** * elem 當前執行計時動作的物件 * timingAction 執行的行為(modify或者verify) */ if (elem == null || timingAction == null) { //先判斷有沒有傳入引數到elem和timingAction,沒有的話直接返回 return; } if ((elem.id == "modifyModal" && isModifyBtnTiming) || (elem.id == "verifyModal" && isVerifyBtnTiming)) { return } else { // 計時開始的操作 if (isTiming(timingAction)) { // 以下是成功傳送驗證碼後的前端操作 if (timingAction == "modify") { isModifyBtnTiming = true; } else if (timingAction == "verify") { isVerifyBtnTiming = true; } elem.className = elem.className.replace("btn-primary", "btn-secondary"); elem.style.cursor = "not-allowed"; let clock_temp = clock_second; let timer = setInterval(function () { if (clock_temp > 0) { elem.value = clock_temp-- + "s"; } else { // 計時結束後的操作 isVerifyBtnTiming = false; elem.value = "獲取驗證碼"; elem.className = elem.className.replace("btn-secondary", "btn-primary"); elem.style.cursor = "pointer"; clearInterval(timer); // 清除定時器 } }, 1000); } else { // 距離上一次驗證碼傳送沒有超過設定的冷卻時間,提示“傳送驗證碼失敗(錯誤碼: xxxxxx)” } }}
/*** 傳送驗證碼的邏輯* @param smsType 驗證碼型別* 0: 郵箱* 1: 手機* @param data 附加資料,json格式* data.to 待發送的手機號* @return {string} 返回介面狀態碼*/function sendCode(smsType, smsData) { let url = ""; let status; // smsType格式檢查 if (smsType == 0) { url = "./sms/send/mail" } else if (smsType == 1) { url = "./sms/send/phone" } $.ajax({ url: url, type: "POST", async: false, data: JSON.stringify(smsData), contentType:'application/json', dataType: "JSON", success: function (res) { status = res.status; }, error: function (res) { status = res.status; } }) return status.toString();}
/**** @param string 要做處理的字串* @param stringType 字串的型別("mail" 或 "phone")* @returns {string|null} 字串格式合法則返回處理好的字串(string),不合法則返回null*/function hideVerifyString(string, stringType) { if (string != "" && stringType == "mail") { // 比如 [email protected] ,返回123****[email protected] return string.slice(0, 3) + "****" + string.slice(string.search("@"), string.length); } else if (string != "" && stringType == "phone") { // 比如 19956563636, 返回199****3636 return string.slice(0, 3) + "****" + string.slice(-4) } else { return ""; }}