zoukankan      html  css  js  c++  java
  • struts2:关于EL能够获得action的属性

    今天一个哥们学习struts2,尝试使用OGNL,由于关联性吧,就又跳到EL上面,结果神奇的事情发生,他用EL表达式从request域里面居然拿到了action钟的属性,这个天崩地裂的,大家都知道struts2中存值对象都放在actioncontext中,如下图:
    struts2:关于EL能够获得action的属性 - 康慧敏 - 我的博客
    这幅截图来自于STURTS2 IN ACTIN一书中,由于action是放到valuestack中的,但是valuestack与request貌似没有交集吧。
    他居然拿到了,疑惑开始了,通过在页面中添加<S:DEBUG/>标签发现了一个问题,居然在request里面有struts2.valuestack这么个变量吧,疑团没有散去,却变得更加大了,怎么搞的?
       最后从网上发现了一篇相似的帖子:
    原文链接:http://i.laoer.com/struts2-use-el-jstl.html

    最近在公司里做一些Java Web开发的培训,同时对已经做的一些工程做一些ReView,现在的工程里,工程师直接使用JSTL取得Action里的属性,这个用法我以前到真的没 有用过,因为在我印象中,Struts2的这些Action属性,应该是在ValueStack中,而在某些情况下,从ValueStack取值是件挺麻 烦的事情,在做天乙社区8时, 我就参考Struts2的标记库,自己扩展标记库,从而取得ValueStack里的值,而JSTL应该是从Page、Request、Session和 Application里顺序取值,莫非Struts2将ValueStack里的值也放入了Request?同时我们直接用EL标签也直接取出了 Action的属性值,莫非真的放入了Request?但是打开Struts2的Debug,发现Request里并没有值。

    带着这个疑问,我Google了一下,很快找到答案:

    提问:在Struts2中,如 何使用JSTL来读取Action中的变量?

    这是一个历史悠久的问题。因为事实上,很多朋友(包括我在内)是不使用Struts2自身的标签库,而是使用JSTL的,可能因为JSTL标签库比 较少,简单易用的原因吧。

    我们知道,JSTL默认是从page,request,session,application这四个Scope逐次查找相应的EL表达式所对应 的对象的值。那么如果要使用JSTL来读取Action中的变量,就需要把Action中的变量,放到request域中才行。所以,早在 Webwork2.1.X的年代,我们会编写一个拦截器来做这个事情的。大致的原理是:在Action执行完返回之前,依次读取Action中的所有的变 量,并依次调用request.setAttribute()来进行设置。具体的整合方式,请参考以下这篇文档:http://wiki.opensymphony.com/display/WW/Using+WebWork+and+XWork+with+JSP+2.0+and+JSTL+1.1

    不过随着时代的发展,上面的这种方式,已经不再被推荐使用了。(虽然如此,我们依然可以学习它的一个解决问题的思路)目前来说,自从 Webwork2.2以后,包括Struts2,都使用另外一种整合方式:对HttpServletRequest进行装饰。让我们来看一下源码:


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    
     public class StrutsRequestWrapper extends HttpServletRequestWrapper {
     
         /**
          * The constructor
          * @param req The request
          */
         public StrutsRequestWrapper(HttpServletRequest req) {
             super(req);
         }
     
         /**
          * Gets the object, looking in the value stack if not found
          *
          * @param s The attribute key
          */
         public Object getAttribute(String s) {
             if (s != null && s.startsWith("javax.servlet")) {
                 // don't bother with the standard javax.servlet attributes, we can short-circuit this
                 // see WW-953 and the forums post linked in that issue for more info
                 return super.getAttribute(s);
             }
     
             ActionContext ctx = ActionContext.getContext();
             Object attribute = super.getAttribute(s);
     
             boolean alreadyIn = false;
             Boolean b = (Boolean) ctx.get("__requestWrapper.getAttribute");
             if (b != null) {
                 alreadyIn = b.booleanValue();
             }
     
             // note: we don't let # come through or else a request for
             // #attr.foo or #request.foo could cause an endless loop
             if (!alreadyIn && attribute == null && s.indexOf("#") == -1) {
                 try {
                     // If not found, then try the ValueStack
                     ctx.put("__requestWrapper.getAttribute", Boolean.TRUE);
                     ValueStack stack = ctx.getValueStack();
                     if (stack != null) {
                         attribute = stack.findValue(s);
                     }
                 } finally {
                     ctx.put("__requestWrapper.getAttribute", Boolean.FALSE);
                 }
             }
             return attribute;
        }
    }

    看到了嘛?这个类会在Struts2初始化的时候,替换HttpServletRequest,运行于整个Struts2的运行过程中,当我们试 图调用request.getAttribute()的时候,就会执行上面的这个方法。(这是一个典型的装饰器模式)在执行上面的方法时,会首先调用 HttpServletRequest中原本的request.getAttribute(),如果没有找到,它会继续到ValueStack中去查找, 而action在ValueStack中,所以action中的变量通过OGNL表达式,就能找到对应的值了。

    在这里,在el表达式广泛使用的今天,JSTL1.1以后,也支持直接使用el表达式。注意与直接使用struts2的tag的区别,这里需要使用 el的表示符号:${}

    例如:${user.name}, <c:out value=”${department.name}” />

  • 相关阅读:
    二分练习题4 查找最接近的元素 题解
    二分练习题5 二分法求函数的零点 题解
    二分练习题3 查找小于x的最大元素 题解
    二分练习题2 查找大于等于x的最小元素 题解
    二分练习题1 查找元素 题解
    code forces 1176 D. Recover it!
    code forces 1173 B. Nauuo and Chess
    code forces 1173 C. Nauuo and Cards
    吴恩达深度学习课程笔记-15
    吴恩达深度学习课程笔记-14
  • 原文地址:https://www.cnblogs.com/yht520/p/3589648.html
Copyright © 2011-2022 走看看