zoukankan      html  css  js  c++  java
  • 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并打开新页面

  • 相关阅读:
    IntelliJ Idea 常用快捷键列表
    JSON,字符串,MAP转换
    学习总是无效,是因为你没有稳定的输出系统
    华为离职副总裁徐家骏:透露年薪千万的工作感悟,太震撼了!
    Junit测试Spring应用Dubbo测试框架之-Excel 工具类
    Junit参数化测试Spring应用Dubbo接口
    TestNG参数化测试Spring应用Dubbo接口
    TestNG测试报告美化
    TestNG系列之四: TestNg依赖 dependsOnMethods
    【Java】Java_08 字符型与布尔值
  • 原文地址:https://www.cnblogs.com/pu20065226/p/10032048.html
Copyright © 2011-2022 走看看