1. <ul id="0c1fb"></ul>

      <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
      <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区

      RELATEED CONSULTING
      相關(guān)咨詢
      選擇下列產(chǎn)品馬上在線溝通
      服務(wù)時間:8:30-17:00
      你可能遇到了下面的問題
      關(guān)閉右側(cè)工具欄

      新聞中心

      這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
      SpringMVC中參數(shù)的傳遞方法有哪些

      這篇文章主要介紹“SpringMVC中參數(shù)的傳遞方法有哪些”,在日常操作中,相信很多人在SpringMVC中參數(shù)的傳遞方法有哪些問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”SpringMVC中參數(shù)的傳遞方法有哪些”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

      十多年的興安網(wǎng)站建設(shè)經(jīng)驗,針對設(shè)計、前端、開發(fā)、售后、文案、推廣等六對一服務(wù),響應(yīng)快,48小時及時工作處理。全網(wǎng)整合營銷推廣的優(yōu)勢是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動調(diào)整興安建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計,從而大程度地提升瀏覽體驗。成都創(chuàng)新互聯(lián)從事“興安網(wǎng)站設(shè)計”,“興安網(wǎng)站推廣”以來,每個客戶項目都認(rèn)真落實執(zhí)行。

      1.緣起

      說到 Web 請求參數(shù)傳遞,大家能想到哪些參數(shù)傳遞方式?

      參數(shù)可以放在地址欄中,不過地址欄參數(shù)的長度有限制,并且在有的場景下我們可能不希望參數(shù)暴漏在地址欄中。參數(shù)可以放在請求體中,這個沒啥好說的。

      小伙伴們試想這樣一個場景:

      在一個電商項目中,有一個提交訂單的請求,這個請求是一個 POST  請求,請求參數(shù)都在請求體中。當(dāng)用戶提交成功后,為了防止用戶刷新瀏覽器頁面造成訂單請求重復(fù)提交,我們一般會將用戶重定向到一個顯示訂單的頁面,這樣即使用戶刷新頁面,也不會造成訂單請求重復(fù)提交。

      大概的代碼就像下面這樣:

      @Controller public class OrderController {     @PostMapping("/order")     public String order(OrderInfo orderInfo) {         //其他處理邏輯         return "redirect:/orderlist";     } }

      這段代碼我相信大家都懂吧!如果不懂可以看看松哥錄制的免費的 SpringMVC 入門教程(硬核!松哥又整了一套免費視頻,搞起!)。

      但是這里有一個問題:如果我想傳遞參數(shù)怎么辦?

      如果是服務(wù)器端跳轉(zhuǎn),我們可以將參數(shù)放在 request  對象中,跳轉(zhuǎn)完成后還能拿到參數(shù),但是如果是客戶端跳轉(zhuǎn)我們就只能將參數(shù)放在地址欄中了,像上面這個方法的返回值我們可以寫成:return  "redirect:/orderlist?xxx=xxx";,這種傳參方式有兩個缺陷:

      • 地址欄的長度是有限的,也就意味著能夠放在地址欄中的參數(shù)是有限的。

      • 不想將一些特殊的參數(shù)放在地址欄中。

      那該怎么辦?還有辦法傳遞參數(shù)嗎?

      有!這就是今天松哥要和大家介紹的 flashMap,專門用來解決重定向時參數(shù)的傳遞問題。

      2.flashMap

      在重定向時,如果需要傳遞參數(shù),但是又不想放在地址欄中,我們就可以通過 flashMap 來傳遞參數(shù),松哥先來一個簡單的例子大家看看效果:

      首先我們定義一個簡單的頁面,里邊就一個 post 請求提交按鈕,如下:

                  Title           

      然后在服務(wù)端接收該請求,并完成重定向:

      @Controller public class OrderController {     @PostMapping("/order")     public String order(HttpServletRequest req) {         FlashMap flashMap = (FlashMap) req.getAttribute(DispatcherServlet.OUTPUT_FLASH_MAP_ATTRIBUTE);         flashMap.put("name", "江南一點雨");         return "redirect:/orderlist";     }      @GetMapping("/orderlist")     @ResponseBody     public String orderList(Model model) {         return (String) model.getAttribute("name");     } }

      首先在 order 接口中,獲取到 flashMap 屬性,然后存入需要傳遞的參數(shù),這些參數(shù)最終會被 SpringMVC 自動放入重定向接口的 Model  中,這樣我們在 orderlist 接口中,就可以獲取到該屬性了。

      當(dāng)然,這是一個比較粗糙的寫法,我們還可以通過 RedirectAttributes 來簡化這一步驟:

      @Controller public class OrderController {     @PostMapping("/order")     public String order(RedirectAttributes attr) {         attr.addFlashAttribute("site", "www.javaboy.org");         attr.addAttribute("name", "微信公眾號:江南一點雨");         return "redirect:/orderlist";     }      @GetMapping("/orderlist")     @ResponseBody     public String orderList(Model model) {         return (String) model.getAttribute("site");     } }

      RedirectAttributes 中有兩種添加參數(shù)的方式:

      • addFlashAttribute:將參數(shù)放到 flashMap 中。

      • addAttribute:將參數(shù)放到 URL 地址中。

      經(jīng)過前面的講解,現(xiàn)在小伙伴們應(yīng)該大致明白了 flashMap 的作用了,就是在你進(jìn)行重定向的時候,不通過地址欄傳遞參數(shù)。

      很多小伙伴可能會有疑問,重定向其實就是瀏覽器發(fā)起了一個新的請求,這新的請求怎么就獲取到上一個請求保存的參數(shù)呢?這我們就要來看看 SpringMVC  的源碼了。

      3.源碼分析

      首先這里涉及到一個關(guān)鍵類叫做 FlashMapManager,如下:

      public interface FlashMapManager {  @Nullable  FlashMap retrieveAndUpdate(HttpServletRequest request, HttpServletResponse response);  void saveOutputFlashMap(FlashMap flashMap, HttpServletRequest request, HttpServletResponse response); }

      兩個方法含義一眼就能看出來:

      retrieveAndUpdate:這個方法用來恢復(fù)參數(shù),并將恢復(fù)過的的參數(shù)和超時的參數(shù)從保存介質(zhì)中刪除。

      saveOutputFlashMap:將參數(shù)保存保存起來。

      FlashMapManager 的實現(xiàn)類如下:

      SpringMVC中參數(shù)的傳遞方法有哪些

      從這個繼承類中,我們基本上就能確定默認(rèn)的保存介質(zhì)時 session。具體的保存邏輯則是在 AbstractFlashMapManager 類中。

      整個參數(shù)傳遞的過程可以分為三大步:

      第一步,首先我們將參數(shù)設(shè)置到 outputFlashMap 中,有兩種設(shè)置方式:我們前面的代碼  req.getAttribute(DispatcherServlet.OUTPUT_FLASH_MAP_ATTRIBUTE) 就是直接獲取  outputFlashMap 對象然后把參數(shù)放進(jìn)去;第二種方式就是通過在接口中添加 RedirectAttributes 參數(shù),然后把需要傳遞的參數(shù)放入  RedirectAttributes 中,這樣當(dāng)處理器處理完畢后,會自動將其設(shè)置到 outputFlashMap 中,具體邏輯在  RequestMappingHandlerAdapter#getModelAndView 方法中:

      private ModelAndView getModelAndView(ModelAndViewContainer mavContainer,   ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception {  //省略...  if (model instanceof RedirectAttributes) {   Map flashAttributes = ((RedirectAttributes) model).getFlashAttributes();   HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);   if (request != null) {    RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);   }  }  return mav; }

      可以看到,如果 model 是 RedirectAttributes 的實例的話,則通過 getOutputFlashMap 方法獲取到  outputFlashMap 屬性,然后相關(guān)的屬性設(shè)置進(jìn)去。

      這是第一步,就是將需要傳遞的參數(shù),先保存到 flashMap 中。

      第二步,重定向?qū)?yīng)的視圖是 RedirectView,在它的 renderMergedOutputModel 方法中,會調(diào)用  FlashMapManager 的 saveOutputFlashMap 方法,將 outputFlashMap 保存到 session 中,如下:

      protected void renderMergedOutputModel(Map model, HttpServletRequest request,   HttpServletResponse response) throws IOException {  String targetUrl = createTargetUrl(model, request);  targetUrl = updateTargetUrl(targetUrl, model, request, response);  // Save flash attributes  RequestContextUtils.saveOutputFlashMap(targetUrl, request, response);  // Redirect  sendRedirect(request, response, targetUrl, this.http10Compatible); }

      RequestContextUtils.saveOutputFlashMap 方法最終就會調(diào)用到 FlashMapManager 的  saveOutputFlashMap 方法,將 outputFlashMap 保存下來。我們來大概看一下保存邏輯:

      public final void saveOutputFlashMap(FlashMap flashMap, HttpServletRequest request, HttpServletResponse response) {  if (CollectionUtils.isEmpty(flashMap)) {   return;  }  String path = decodeAndNormalizePath(flashMap.getTargetRequestPath(), request);  flashMap.setTargetRequestPath(path);  flashMap.startExpirationPeriod(getFlashMapTimeout());  Object mutex = getFlashMapsMutex(request);  if (mutex != null) {   synchronized (mutex) {    List allFlashMaps = retrieveFlashMaps(request);    allFlashMaps = (allFlashMaps != null ? allFlashMaps : new CopyOnWriteArrayList<>());    allFlashMaps.add(flashMap);    updateFlashMaps(allFlashMaps, request, response);   }  }  else {   List allFlashMaps = retrieveFlashMaps(request);   allFlashMaps = (allFlashMaps != null ? allFlashMaps : new ArrayList<>(1));   allFlashMaps.add(flashMap);   updateFlashMaps(allFlashMaps, request, response);  } }

      其實這里的邏輯也很簡單,保存之前會給 flashMap 設(shè)置兩個屬性,一個是重定向的 url 地址,另一個則是過期時間,過期時間默認(rèn) 180  秒,這兩個屬性在第三步加載 flashMap 的時候會用到。然后將 flashMap 放入集合中,并調(diào)用 updateFlashMaps 方法存入  session 中。

      第三步,當(dāng)重定向請求到達(dá) DispatcherServlet#doService 方法后,此時會調(diào)用  FlashMapManager#retrieveAndUpdate 方法從 Session 中獲取 outputFlashMap 并設(shè)置到 Request  屬性中備用(最終會被轉(zhuǎn)化到 Model 中的屬性),相關(guān)代碼如下:

      protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {  //省略...  if (this.flashMapManager != null) {   FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);   if (inputFlashMap != null) {    request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));   }   request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());   request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);  }  //省略... }

      注意這里獲取出來的 outputFlashMap 換了一個名字,變成了 inputFlashMap,其實是同一個東西。

      我們可以大概看一下獲取的邏輯 AbstractFlashMapManager#retrieveAndUpdate:

      public final FlashMap retrieveAndUpdate(HttpServletRequest request, HttpServletResponse response) {  List allFlashMaps = retrieveFlashMaps(request);  if (CollectionUtils.isEmpty(allFlashMaps)) {   return null;  }  List mapsToRemove = getExpiredFlashMaps(allFlashMaps);  FlashMap match = getMatchingFlashMap(allFlashMaps, request);  if (match != null) {   mapsToRemove.add(match);  }  if (!mapsToRemove.isEmpty()) {   Object mutex = getFlashMapsMutex(request);   if (mutex != null) {    synchronized (mutex) {     allFlashMaps = retrieveFlashMaps(request);     if (allFlashMaps != null) {      allFlashMaps.removeAll(mapsToRemove);      updateFlashMaps(allFlashMaps, request, response);     }    }   }   else {    allFlashMaps.removeAll(mapsToRemove);    updateFlashMaps(allFlashMaps, request, response);   }  }  return match; }
      • 首先調(diào)用 retrieveFlashMaps 方法從 session 中獲取到所有的 FlashMap。

      • 調(diào)用 getExpiredFlashMaps 方法獲取所有過期的 FlashMap,F(xiàn)lashMap 默認(rèn)的過期時間是 180s。

      • 獲取和當(dāng)前請求匹配的  getMatchingFlashMap,具體的匹配邏輯就兩點:重定向地址要和當(dāng)前請求地址相同;預(yù)設(shè)參數(shù)要相同。一般來說我們不需要配置預(yù)設(shè)參數(shù),所以這一條可以忽略。如果想要設(shè)置,則首先給  flashMap 設(shè)置,像這樣:flashMap.addTargetRequestParam("aa",  "bb");,然后在重定向的地址欄也加上這個參數(shù):return "redirect:/orderlist?aa=bb"; 即可。

      • 將獲取到的匹配的 FlashMap 對象放入 mapsToRemove 集合中(這個匹配到的 FlashMap 即將失效,放入集合中一會被清空)。

      • 將 allFlashMaps 集合中的所有 mapsToRemove 數(shù)據(jù)清空,同時調(diào)用 updateFlashMaps 方法更新 session 中的  FlashMap。

      • 最終將匹配到的 flashMap 返回。

      這就是整個獲取 flashMap 的方法,整體來看還是非常 easy 的,并沒有什么難點。

      到此,關(guān)于“SpringMVC中參數(shù)的傳遞方法有哪些”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>
      標(biāo)題名稱:SpringMVC中參數(shù)的傳遞方法有哪些
      文章URL:http://www.ef60e0e.cn/article/pgdjsh.html

      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区
      1. <ul id="0c1fb"></ul>

        <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
        <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

        崇左市| 泸溪县| 饶河县| 饶河县| 师宗县| 东平县| 德昌县| 札达县| 娱乐| 老河口市| 原平市| 讷河市| 宜宾县| 明溪县| 綦江县| 马鞍山市| 营山县| 收藏| 苍南县| 武安市| 城市| 温泉县| 商南县| 安仁县| 右玉县| 京山县| 温泉县| 胶南市| 和平区| 淅川县| 永宁县| 潮州市| 万盛区| 安宁市| 门源| 静安区| 衡山县| 嘉黎县| 利辛县| 延安市| 临武县|