<ul id="qxxfc"><fieldset id="qxxfc"><tr id="qxxfc"></tr></fieldset></ul>


      概述

      作為一枚菜鳥(niǎo),前后端交互可是大問(wèn)題,經(jīng)常數(shù)據(jù)交互失敗,不知道怎么跳轉(zhuǎn)。在這分享一下交互的小心得。

      我們不妨先大概了解一下整個(gè)訪問(wèn)流程:

      用戶從輸入網(wǎng)址按下回車,交互就已經(jīng)開(kāi)始了。

      瀏覽器會(huì)將請(qǐng)求按照http協(xié)議(或者其他https,ftp等)將請(qǐng)求數(shù)據(jù)封裝包從電腦的端口發(fā)出 -> 路由器 -> 運(yùn)營(yíng)商(域名解析之類的)->
      目標(biāo)服務(wù)器(可能會(huì)有代理,負(fù)載均衡等等)

      最終從服務(wù)器開(kāi)放的端口,進(jìn)入到服務(wù)器(TCP三次握手和四次揮手,Tomcat之類的,會(huì)根據(jù)協(xié)議的內(nèi)容進(jìn)行解析)-> web項(xiàng)目進(jìn)行具體的邏輯處理 ->
      返回?cái)?shù)據(jù) -> 瀏覽器接收數(shù)據(jù)(根據(jù)協(xié)議內(nèi)容進(jìn)行解析)

      整個(gè)過(guò)程,協(xié)議很重要,因?yàn)榭蛻舳撕头?wù)器都是通過(guò)協(xié)議來(lái)解析和發(fā)送信息的,最常見(jiàn)的http協(xié)議,協(xié)議頭部的參數(shù)常用的哪幾個(gè),有什么影響。

      Http協(xié)議的簡(jiǎn)介,說(shuō)的很有意思:https://blog.csdn.net/u010256388/article/details/68491509/
      <https://blog.csdn.net/u010256388/article/details/68491509/>

      還有緩存問(wèn)題(cookie、session、localstorage、cashe-controller等),不僅提高效率,而且有時(shí)候你
      更改了代碼測(cè)試卻沒(méi)變化的重要原因:https://www.jianshu.com/p/9ed3e8759ce3
      <https://www.jianshu.com/p/9ed3e8759ce3>

      相應(yīng)的后臺(tái)tomcat的緩存處理:
      http://www.360doc.com/content/17/0721/17/41344223_673116604.shtml
      <http://www.360doc.com/content/17/0721/17/41344223_673116604.shtml>(了解即可)

      ?

      具體到使用分為:前端交互,分為同步和異步。

      同步交互

      常見(jiàn)的from表單提交(post方式帶參數(shù)),URL直接訪問(wèn)(get方式,有參數(shù)在地址欄可見(jiàn),特殊符號(hào)需要轉(zhuǎn)義,不安全)。

      異步交互

      關(guān)鍵是XMLHttpRequest對(duì)象,平時(shí)說(shuō)的ajax只是一種交互模式,并不是什么新技術(shù)
      ,其原理就是對(duì)XMLHttpRequest的封裝。所以對(duì)XMLHttpRequest深入全面的了解可以幫助我們更好的掌握異步交互。

      可以看這篇精品文章了解:https://www.jianshu.com/p/b037f71af548
      <https://www.jianshu.com/p/b037f71af548>
      ,里面涉及到了在傳送過(guò)程中各個(gè)參數(shù)的用法,會(huì)觸發(fā)的事件,返回值等等很實(shí)用的知識(shí)。(雖然能設(shè)置同步交互,但不推薦)

      其中傳輸類型 contentType就非常重要,這個(gè)值設(shè)置決定了后臺(tái)怎么去解析http協(xié)議。

      ?

      *
      上圖所示,如果格式前后端發(fā)送和接收對(duì)不上,那是獲取不了數(shù)據(jù)。如圖的最后一步返回,如果想頁(yè)面跳轉(zhuǎn),則不需要@ResponseBody,改為返回ModelAndView
      *
      @RequestBody主要用來(lái)接收前端傳遞給后端的json字符串中的數(shù)據(jù)的(請(qǐng)求體中的數(shù)據(jù)的);GET方式無(wú)請(qǐng)求體,所以使用@RequestBody接收數(shù)據(jù)時(shí),前端不能使用GET方式提交數(shù)據(jù),而是用POST方式進(jìn)行提交。
      * @RequestParam接收的是key-value里面的參數(shù),所以GET方式的數(shù)據(jù)和表單提交,可以接收。
      * @RequestBody和@RequestParma的使用知識(shí),更輕松的全面掌握:
      https://blog.csdn.net/justry_deng/article/details/80972817
      <https://blog.csdn.net/justry_deng/article/details/80972817>
      前端交互類

      前端我創(chuàng)建了兩個(gè)工具類,來(lái)負(fù)責(zé)交互。

      異步交互類

      我把jQuery的ajax進(jìn)行了封裝,主要是獲取和計(jì)算信息,代碼如下:
      1 /* 2 * 以下為程序錯(cuò)誤碼 3 */ 4 //通用的請(qǐng)求失敗,包括未知原因 5 var EXPECTATION_FAILED = 417;
      6 var EXPECTATION_QUERY = 404; 7 8 /** 9 * 訪問(wèn)后臺(tái)的對(duì)象,為ajax封裝 10 *
      @constructor 11 */ 12 var Query = function (url, param, callback, contentType)
      { 13 this.url = url; 14 15 //先確認(rèn)參數(shù)存在,如果不存在則創(chuàng)建空map 16 if (!param) { 17 param
      =new Map(); 18 } 19 //注意,要根據(jù)不同的傳輸格式來(lái)確定傳輸?shù)闹档念愋? 20 if (contentType ==
      Query.NOMAL_TYPE) { 21 this.param = JSON.parse(this._convertParam(param)); 22 }
      else { 23 this.param = this._convertParam(param); 24 } 25 26 27 this
      .callback = callback; 28 this.contentType = contentType; 29 //請(qǐng)求超時(shí),默認(rèn)5秒 30
      this.timeout = 5000; 31 //是否異步請(qǐng)求,默認(rèn)異步 32 this.async = true; 33 } 34 35
      Query.JSON_TYPE = 'application/json'; 36 Query.NOMAL_TYPE =
      'application/x-www-form-urlencoded'; 37 38 /** 39 * ajax請(qǐng)求的訪問(wèn) 40 * @param
      url 要訪問(wèn)的地址 41 * @param paramMap 傳給后臺(tái)的Map參數(shù),key為字符串類型 42 * @param callback
      回調(diào)函數(shù) 43 * @param contentType 傳輸數(shù)據(jù)的格式 默認(rèn)傳輸application/x-www-form-urlencoded格式
      44 */ 45 Query.create = function (url, paramMap, callback) { 46 return new
      Query(url, paramMap, callback, Query.NOMAL_TYPE); 47 } 48 49
      Query.createJsonType =function (url, paramMap, callback) { 50 return new
      Query(url, paramMap, callback, Query.JSON_TYPE); 51 } 52 53 /** 54 *
      將ParamMap轉(zhuǎn)為json格式,目前只支持Map對(duì)象,以后會(huì)擴(kuò)展 55 * @param paramMap 56 * @private 57 */
      58 Query.prototype._convertParam = function (param) { 59 60 if (param
      instanceof Map) { 61 return strMap2Json(param); 62 } 63 } 64 65 /** 66
      * 對(duì)ajax回調(diào)函數(shù)的封裝 67 * @param callBack 68 * @private 69 */ 70
      Query.prototype._callback =function (queryResult) { 71 72 //取消加載框 73 if (this
      .loadDom) { 74 $(this.loadDom).remove("#loadingDiv"); 75 } 76 77 //Query對(duì)象
      78 var self = queryResult.queryObj; 79 var data =
      $.parseJSON(queryResult.responseText); 80 //記錄請(qǐng)求是否有錯(cuò)誤 81 self.queryException =
      false; 82 var handleError; 83 84 if (queryResult.status ==
      EXPECTATION_FAILED || queryResult.status == EXPECTATION_QUERY) { 85 var error =
      queryResult.responseText; 86 self.queryException = true; 87 } 88 89 //
      調(diào)用回調(diào)函數(shù),如果返回結(jié)果為true,則對(duì)于出錯(cuò)不會(huì)默認(rèn)錯(cuò)誤處理 90 if (self.callback instanceof Function) {
      91 handleError = self.callback(data); 92 } 93 94 //
      如果出現(xiàn)了異常并且沒(méi)有被處理,那么將進(jìn)行默認(rèn)錯(cuò)誤處理 95 if (self.queryException && !handleError) { 96
      window.location.href = "/system/error/" + error.code + "/" + error.msg; 97 }
      98 99 //如果需要跳轉(zhuǎn),則進(jìn)行跳轉(zhuǎn) 100 if (data.redirect_url) { 101 window.location.href =
      data.redirect_url;102 } 103 } 104 105 /** 106 * 正式發(fā)送ajax 107 * @private 108
      */ 109 Query.prototype.sendMessage = function () { 110 var self = this; 111 var
      xhr = $.ajax( 112 { 113 type: "post", 114 url: this.url, 115 contentType: this
      .contentType,116 data: this.param, 117 // ajax發(fā)送前調(diào)用的方法,初始化等待動(dòng)畫 118 // @param
      XHR XMLHttpRequest對(duì)象 119 beforeSend: function (XHR) { 120 //綁定本次請(qǐng)求的queryObj 121
      XHR.queryObj = self; 122 if (self.beforeSendFunc instanceof Function) { 123
      self.beforeSendFunc(XHR);124 } 125 126 if (self.loadDom instanceof
      HTMLElement) {127 self.loadDom.innerText = ""; 128 $(self.loadDom).append("<div
      id='loadingDiv' class='loading'><img src='/image/loading.gif'/></div>"); 129 }
      else if (self.loadDom instanceof jQuery) { 130 self.loadDom.empty(); 131
      self.loadDom.append("<div id='loadingDiv' class='loading'><img
      src='/image/loading.gif'/></div>"); 132 } 133 }, 134 complete: this._callback,
      135 timeout:this.timeout, 136 async:this.async 137 } 138 ); 139 140 } 141 142
      /** 143 * 檢測(cè)是否有錯(cuò)誤,返回ture有錯(cuò)誤,或者false 144 */ 145 Query.prototype.checkEception =
      function () { 146 return this.queryException; 147 } 148 149 //
      ------------------------以下為對(duì)Query的參數(shù)設(shè)置--------------------------- 150 /** 151
      * 在ajax發(fā)送前設(shè)置參數(shù),可以有加載的動(dòng)畫,并且請(qǐng)求完成后會(huì)自動(dòng)取消152 * @param loadDom 需要顯示動(dòng)畫的dom節(jié)點(diǎn) 153 *
      @param beforeSendFunc ajax發(fā)送前的自定義函數(shù)154 */ 155 Query.prototype.setBeforeSend =
      function (loadDom, beforeSendFunc) { 156 this.loadDom = loadDom; 157 this
      .beforeSendFunc = beforeSendFunc; 158 } 159 160 /** 161 * 設(shè)置超時(shí)時(shí)間 162 * @param
      timeout163 */ 164 Query.prototype.setTimeOut = function (timeout) { 165 this
      .timeout = timeout; 166 } 167 168 Query.prototype.setAsync = function (async) {
      169 this.async = async; 170 }
      封裝的好處:

      * 可以省略很多重復(fù)的代碼,如$.ajax傳參數(shù)那一長(zhǎng)串(111-136行)
      * 可以規(guī)定統(tǒng)一的前端交互流程,并且修改這個(gè)流程也方便。
      *
      * 根據(jù)傳輸類型
      也對(duì)參數(shù)進(jìn)行轉(zhuǎn)換(20-24行),并且_convertParam()方法能繼續(xù)擴(kuò)展參數(shù)類型,直到后面可以把絕大多數(shù)參數(shù)都轉(zhuǎn)換成正確的格式(那發(fā)送基本不用考慮參數(shù)格式了,只要確定傳輸?shù)念愋途秃茫   ?
      ? ? ? ??
      * 統(tǒng)一回調(diào)流程(70-103行)可以對(duì)異常做統(tǒng)一處理(ajax)像我這樣跳轉(zhuǎn)到錯(cuò)誤頁(yè)面,或者有些異步請(qǐng)求返回時(shí)需要跳轉(zhuǎn),也能統(tǒng)一跳轉(zhuǎn)
      * 統(tǒng)一請(qǐng)求發(fā)送前的處理(119-133行)可以對(duì)請(qǐng)求等待統(tǒng)一的設(shè)置等待動(dòng)畫,最后再回調(diào)流程統(tǒng)一取消動(dòng)畫
      同步交互類

      from表單創(chuàng)建類,主要是進(jìn)行有參數(shù)傳輸?shù)捻?yè)面跳轉(zhuǎn),因?yàn)橹苯覷RL跳轉(zhuǎn)參數(shù)會(huì)暴露不安全
      1 /** 2 * 訪問(wèn)后臺(tái)的類,構(gòu)造form表單來(lái)進(jìn)行post請(qǐng)求 3 * @param url 4 * @param paramMap
      參數(shù)map 5 * @constructor 6 */ 7 var QueryForm = function (url,paramMap) { 8 //
      form表單的JQ對(duì)象 9 this.form = $("<form></form>"); 10 this.form.attr("action",url);
      11 this.form.attr("method","post"); 12 //遍歷Map 13 for(var [key,value] of
      paramMap){14 var inputDom = $("<input/>") ; 15 inputDom.attr("name",key); 16
      inputDom.attr("value",value); 17 this.form.append(inputDom); 18 } 19 //
      必須要放入body里面,不然請(qǐng)求發(fā)不出去 20 var bodyDom = $("body"); 21 bodyDom.append(this.form);
      22 this.sendMessage(); 23 24 //發(fā)送完后銷毀 25 this.destroy(); 26 } 27 28
      QueryForm.create =function (url, paramMap) { 29 return new
      QueryForm(url,paramMap);30 } 31 32 QueryForm.prototype.sendMessage = function
      () {33 this.form.submit(); 34 } 35 36 QueryForm.prototype.destroy = function ()
      {37 this.form.remove(); 38 }
      后端交互類


      普通的Controller,在@RequestMapping中填寫正確的路徑,根據(jù)前端傳輸?shù)臄?shù)據(jù)類型來(lái)獲取參數(shù)(見(jiàn)上文),根據(jù)邏輯來(lái)確定要不要@ResponseBody來(lái)返回信息,還是ModelAndView來(lái)進(jìn)行頁(yè)面跳轉(zhuǎn)

      路徑


      經(jīng)常404怎么辦,那就是路徑有問(wèn)題。得先明白,java虛擬機(jī)運(yùn)行的不是java文件而是編譯后的.calss文件,所以最先檢查的是target文件夾下是否有你URL寫的這個(gè)文件,是否路徑正確



      平時(shí)網(wǎng)上看到的classpath,就是指target下的classes文件夾

      順帶提一句,如果是eclipse,右鍵點(diǎn)擊新建,你會(huì)發(fā)現(xiàn)有幾個(gè)文件夾可以選



      folder:就是普通的文件夾,它和我們window下面使用的文件夾沒(méi)有任何區(qū)別


      source folder:文件夾是一種特別的文件夾,如果你用面向?qū)ο蟮乃枷肴タ创@個(gè)source
      folder,那么他是folder的一個(gè)子集,作為子集,肯定是有folder的所有功能,而且還有自己特別的功能,他的特別之處,就是在source
      folder下面的java文件都會(huì)被編譯,編譯后的文件會(huì)被放在我們?cè)O(shè)置的某個(gè)文件夾下面(一般我們?cè)O(shè)置成WEB-INF/classes),source
      folder下面的非java文件會(huì)被copy一份放在我們的設(shè)置的文件夾下面


      package:文件夾也是一種特別的文件夾,他的特別之處在于:他必須存在于source
      folder下面,上下級(jí)通過(guò).來(lái)區(qū)分,他的路徑最后組成了每一個(gè)類的包路徑名

      ?

      所以當(dāng)出現(xiàn)404,請(qǐng)先檢查路徑,如果是springboot項(xiàng)目,則要遵守一些默認(rèn)路徑規(guī)則,比如模板必須放在templates,靜態(tài)文件必須放在static

      ?

      友情鏈接
      ioDraw流程圖
      API參考文檔
      OK工具箱
      云服務(wù)器優(yōu)惠
      阿里云優(yōu)惠券
      騰訊云優(yōu)惠券
      京東云優(yōu)惠券
      站點(diǎn)信息
      問(wèn)題反饋
      郵箱:[email protected]
      QQ群:637538335
      關(guān)注微信

        <ul id="qxxfc"><fieldset id="qxxfc"><tr id="qxxfc"></tr></fieldset></ul>
          欧美老年人性生活视频 | 久草青青| av中文字幕在线 爱爱网站大片视频 | 久久午夜激情电影 | 日漫艳母在线观看 | 亚洲国产18禁 | 嗯灬啊灬用力别停老师使用方法 | www.vkvta.com | 成人网站在线观看一区高清无码 | 中国理伦片在线 |