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并打开新页面

  • 相关阅读:
    Python中所有的关键字
    关于selenium的8种元素定位
    对提示框的操作
    selenium+webservice进行百度登录
    MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled...报错解决
    Vue中使用echarts
    npm WARN deprecated request@2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142解决方法
    插入排序
    冒泡排序优化
    roject 'org.springframework.boot:spring-boot-starter-parent:XXX' not found 解决
  • 原文地址:https://www.cnblogs.com/pu20065226/p/10032048.html
Copyright © 2011-2022 走看看