jsp取addFlashAttribute值深入理解即springMVC發redirect傳隱藏參數


結論:兩種方式

a.如果沒有進行action轉發,在頁面中el需要${sessionScope['org.springframework.web.servlet.support.SessionFlashMapManager.FLASH_MAPS'][0]['userId']}

b.如果進行了action轉發則el直接${userId}

 

背景:框架中,兩個web工程a,b,我的b工程開發了一個對外action接口,a來連,要實現的功能是,a的頁面發起一個action請求,到達b的springmvc,通過驗證后,打開一個b工程新的tab的新窗口,前端發請求可參考我的另一文章springMVC接受json並打開新頁面

 

1.不進行action轉發

controller代碼:

@Controller
@RequestMapping("/page/login")
public class LoginController {

  @RequestMapping(value = "/redirect.do")
    public String doRedirect(RedirectAttributes redirectAttributes) {
        redirectAttributes.addFlashAttribute("userId", "ID001");
        redirectAttributes.addFlashAttribute("userName", "mike");
     redirectAttributes.addAttribute("flag", "opening");
return "redirect:../public/indexTest.jsp"; } }

jsp

<body>
   here is indexTest.jsp <br>
   userId is ${sessionScope['org.springframework.web.servlet.support.SessionFlashMapManager.FLASH_MAPS'][0]['userId']}<br>
  userName is ${userName}<br> flag is ${flag}
  param_flag is ${param.flag}
</body>

這樣可以正常輸出 url:http://lolcalhost:8080/project/page/public/indexTest.jsp?flag=opening

  here is indexTest.jsp 
    userId is ID001
  userName is

  flag is

  param_flag is opening
在jsp中打印session和request

<%    
System.out.println("page session parameter:"); //final HttpSession session = request.getSession(); final Enumeration se = session.getAttributeNames(); while (se.hasMoreElements()) { final String key = (String) se.nextElement(); System.out.println(key + "==" + session.getAttribute(key)); } System.out.println("print redirectpage page request parameter:"); final Enumeration reqEnum = request.getParameterNames(); while (reqEnum.hasMoreElements()) { final String s = (String) reqEnum.nextElement(); System.out.println(s + "==" + request.getParameter(s)); } System.out.println("print redirectpage page request attribute:"); final Enumeration reqEnum2 = request.getAttributeNames(); while (reqEnum2.hasMoreElements()) { final String s = (String) reqEnum2.nextElement(); System.out.println(s + "==" + request.getAttribute(s)); }
%>

console輸出

page session parameter:
org.springframework.web.servlet.support.SessionFlashMapManager.FLASH_MAPS==[FlashMap [attributes={userId=ID001, userName=mike}
, targetRequestPath=/project/page/public/indexTest.jsp, targetRequestParams={flag=[opening]}]]
print redirectpage page request parameter:
flag==opening
print redirectpage page request attribute:

說明:addFlashAttribute方法將參數放入了session中的flashmap中保存起來了,並且隱藏起來,不在瀏覽器中顯示參數,同時傳大對象也不受瀏覽器限制。而redirectAttributes.addAttribute方法則是將參數放到request域中。而且session.getAttribute("org.springframework.web.servlet.support.SessionFlashMapManager.FLASH_MAPS")出來的值不是標准的數組,用JSON.parse(str)運行時會報錯,只能用el取。

不足:取值過於復雜

 

2.通過action二次轉發

controller

 

@Controller
@RequestMapping("/page/login")
public class LoginController {

  @RequestMapping(value = "/redirect.do")
    public String doRedirect(RedirectAttributes redirectAttributes) {
        redirectAttributes.addFlashAttribute("userId", "ID001");
        redirectAttributes.addFlashAttribute("userName", "mike");
     redirectAttributes.addAttribute("flag", "opening");
        return "redirect:../public/winOpenSucc.do";
    }
  @RequestMapping(value
= "/winOpenSucc.do") public String redirectPage() { return "../public/indexTest.jsp" } }

jsp頁面代碼不變

輸出 url:http://lolcalhost:8080/project/page/public/winOpenSucc.do?flag=opening

here is indexTest.jsp      

userId is    

userName is mike

flag is

param_flag is opening

 jsp中session,request打印結果

page session parameter:
print redirectpage page request parameter:
flag==opening
print redirectpage page request attribute:
javax.servlet.forward.request_uri==/project/page/login/winOpenSucc.do
javax.servlet.forward.context_path==/project
javax.servlet.forward.servlet_path==/page/login/winOpenSucc.do
javax.servlet.forward.query_string==flag=opening
org.springframework.web.servlet.DispatcherServlet.INPUT_FLASH_MAP==FlashMap [attributes={userId=ID001, userName=mike}, targetR
equestPath=/project/page/login/winOpenSucc.do, targetRequestParams={flag=[opening]}]
userId=ID001
userName=mike

說明:通過action二次轉發(默認 return "forward:url"),session中flashmap消失了,通過model(model,modelmap,@ModelAttribute都可以取到前一個action的包括flashAtrribute等參數)這個springmvc這個默認內置對象來接收第一個action redirect過來session中的參數,並自動保存在返回的model數據模型中,forward request依然延續存活(falg依然在值未變),並最終由spring轉為request 的attribute中( ${userName}取到了值 )。
不足:瀏覽器中 url並沒有改變,顯示為action地址,沒有達到需求

 

3.實現url改變並跟蹤model的變化

3.1controller

@Controller
@RequestMapping("/page/login")
public class LoginController {

  @RequestMapping(value = "/redirect.do")
    public String doRedirect(RedirectAttributes redirectAttributes) {
        redirectAttributes.addFlashAttribute("userId", "ID001");
        redirectAttributes.addFlashAttribute("userName", "mike");
     redirectAttributes.addAttribute("flag", "opening");
        return "redirect:../public/winOpenSucc.do";
    }

  @RequestMapping(value = "/winOpenSucc.do")
    public String redirectPage() {
    
return "redirect:../public/indexTest.jsp" } }

jsp頁面

輸出 url:http://lolcalhost:8080/project/page/public/indexTest?userId=ID001?userName=mike

here is indexTest.jsp      

userId is    

userName is

flag is

param_flag is opening

說明:二次重定向redirect后,前面的request生命周期結束,新的request由於model對象的注入,將flashmap中的參數轉給新的request parameter,

此時${param.userId} ${param.userName}可以取到值

不足:暴露了敏感參數值,flashmap中的對象參數(如3.2的userInfo實例對象,受url不傳對象的限制)及request parameter(flag)轉發后消失

 

3.2跟蹤model

controller

 

@Controller
@RequestMapping("/page/login")
public class LoginController {

  @RequestMapping(value = "/redirect.do")
    public String doRedirect(RedirectAttributes redirectAttributes) {
        User user=new User();
        user.setMyId="ID002";
        user.setMyName="lili";         redirectAttributes.addFlashAttribute("userId", "ID001");
        redirectAttributes.addFlashAttribute("userName", "mike"); //將存入session falshmap中,request刷新后失,優點是隱藏具不用手動清理      redirectAttributes.addAttribute("flag", "opening");
        return "redirect:../public/winOpenSucc.do"; //舊request消亡,將產生新的request,flag參數將存入新request中的parameter
    }

  @RequestMapping(value = "/winOpenSucc.do")
    public String redirectPage(Model model,HttpServletRequest request) {
  System.out.println("print redirectpage controller model parameter:");
        model.addAttribute("mdbefore", "before");
        final Map map = model.asMap();
        for (final Object obj : map.keySet()) {
            System.out.println(obj.toString() + "==" + map.get(obj));
        }
        model.addAttribute("mdafter", "after"); 
        System.out.println("print redirect controller request parameter:");
        final Enumeration reqEnum = request.getParameterNames();
        while (reqEnum.hasMoreElements()) {
            final String s = (String) reqEnum.nextElement();
            System.out.println(s + "==" + request.getParameter(s));
        }
     System.out.println("print  redirect controller request attribute:");
      final Enumeration reqAttrs = request.getAttributeNames();
      while (reqAttrs.hasMoreElements()) {
         final String s = (String) reqAttrs.nextElement();
         System.out.println(s + "==" + request.getAttribute(s));
      }
System.out.println(
"print redirect controller session parameter:"); final HttpSession session = request.getSession(); final Enumeration se = session.getAttributeNames(); while (se.hasMoreElements()) { final String key = (String) se.nextElement(); System.out.println(key + "==" + session.getAttribute(key)); } return "redirect:../public/indexTest.jsp"; //舊request(帶falg參數)消亡,產生新的request(全新的,不帶任何參數),model將自己的值注入新request.parameter中,並返回。 } }

console

 

print redirectpage controller model parameter:
userInfo==com.xx.vdo.User@16675039  //此對象在redirect后,model注入新的request中時,消失
userId==ID001
userName==mike mdbefore==before print redirect controller request parameter: //后台第二個action中request 只有一個flag==opening參數 flag==opening
print  redirect controller request attribute:
org.springframework.web.servlet.DispatcherServlet.INPUT_FLASH_MAP==FlashMap [attributes={userInfo=com.xx.vdo.User@16675039, userId=ID001,userName=mike}, targetRe
questPath=/ReportsTYKF/page/login/winOpenSucc.do, targetRequestParams={flag=[opening]}]
org.springframework.web.servlet.DispatcherServlet.FLASH_MAP_MANAGER==org.springframework.web.servlet.support.SessionFlashMapManager@c8398e7
org.springframework.web.servlet.DispatcherServlet.OUTPUT_FLASH_MAP==FlashMap [attributes={}, targetRequestPath=null, targetRequestParams={}]
print redirect controller session parameter:

jsp url:http://lolcalhost:8080/project/page/public/indexTest?userId=ID001&userName=mike&mdbefore=before&mdafter=after

jsp 中session,request打印結果:

 

page session parameter:
print redirectpage page request parameter:  //此處已無flag==opning,參數個數為4,即model將值在第二次redirect后注入新的request.parameter中,
userId==ID001
userName==mike
mdbefore
==before mdafter==after print redirectpage page request attribute:

 

4.完美實現flshmap參數安全,url地址改變,參數易存取。

 其實2已經基本實現我們的需求,只是url沒有變,如果我們要實現url的跳轉,可以在jsp中增加代碼。

前提:需求是外系統有一個菜單列表,點擊后打開一個新窗口,跳轉到本系統,並對連接進行安全檢查,通過后相關信息存session,同時在頁面初始化共公參數如操作員信息,同時做到不暴露敏感信息,最后進入本系統具體的頁面。

<html>
<head>
<% 
String id="bb11234";
//out.println("<script language='javascript'>window.location='"+"page/public/carList.jsp?reqId="+id+"';</script>"); %> </head> <body> </body> <script type="text/javascript">
  //這里可以對共公變量進行初始化,然后再進行頁面轉發
  project.userInfo.userId=${userInfo.myId};
  project.userInfo.userName=${userInfo.myName};
  project.current.operatorName=${userName}; var operatorId=${userId};
window.location="page/public/reportList.jsp?id="+operatorId; </script > <html>

 

后記:如果jsp發請求打開外系統新頁面,只能選擇window.open,或者form提交。需要解決跨域問題且格式不好控制。ajax發請求只能等返回信息然后再在本系統中打開頁面。相當於至少兩次請求。后面會再寫一篇關於springMVC打開新頁面springMVC接受json並打開新頁面


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM