struts使用中el与ognl

本文基于struts2.1.8.1,xwork2.1.6
1.EL
        EL(Expression Language)源于jsp页面标签jstl,后来被jsp2.0直接支持,因此可以在jsp页面中直接使用EL表达式。其使用语法为${expr}, 如${username},表达式expr中变量的获取,默认使用PageContext.findAttribute(String)方法,也就是从 pageContext隐藏对象中查找,pageContext隐藏对象包含以下隐藏对 象:request,response,session,servletContext.查找范围顺序是page, request,session, and application,找不到则返回null。指定对象查找则使用${implictObject.foo}语法,其中implictObject代表 任意隐藏对象,除pageContext之外,还包 含:param,paramValues,header,headerValues,cookie,initParam以及 pageScope,requestScope,sessionScope,applicationScope等。
        注意:自定义变量如果和隐藏对象同名,${implicitObject}将返回隐藏对象,而不是自定义对象的值。

2.OGNL in Struts2
        struts2使用ActionContext作为OGNL的上下文,也就是ActionContext.context,其默认的root上下文是一个 OGNL的值栈(OgnlValueStack),用于存放action的实例,其访问不需要标记,同时存放了其它的对象,如 request,parameters,session,application,attr等,访问需要#标记并指明对象名称, 如#session.username.由于ActionContext存放到ThreadLocal中,所以是线程安全的。在同一个请求经过不同的 action转发(forward)处理的过程中,这些action实例都会压进root这个值栈中,最后的在最上面,查找变量值也是从上面开始顺序往 下。
        ActionContext是由 org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter进行初 始化的,在doFilter中调用prepare.createActionContext(request, response);追踪下去,核心代码在org.apache.struts2.dispatcher.ng.PrepareOperations中:

Java代码  收藏代码
  1. public ActionContext createActionContext(HttpServletRequest request, HttpServletResponse response) {  
  2.         ActionContext ctx;  
  3.         Integer counter = 1;  
  4.         Integer oldCounter = (Integer) request.getAttribute(CLEANUP_RECURSION_COUNTER);  
  5.         if (oldCounter != null) {  
  6.             counter = oldCounter + 1;  
  7.         }  
  8.           
  9.         ActionContext oldContext = ActionContext.getContext();  
  10.         if (oldContext != null) {  
  11.             // detected existing context, so we are probably in a forward  
  12.             ctx = new ActionContext(new HashMap<String, Object>(oldContext.getContextMap()));  
  13.         } else {  
  14.             ValueStack stack = dispatcher.getContainer().getInstance(ValueStackFactory.class).createValueStack();  
  15.             stack.getContext().putAll(dispatcher.createContextMap(request, response, null, servletContext));  
  16.             ctx = new ActionContext(stack.getContext());  
  17.         }  
  18.         request.setAttribute(CLEANUP_RECURSION_COUNTER, counter);  
  19.         ActionContext.setContext(ctx);  
  20.         return ctx;  
  21.     }  



3.JSP中的使用
        JSP2.0可以直接使用EL表达式,方便变量的获取。使用struts2的标签,可以取到ActionContext中的对象,如action中的成员变量,非root中的变量使用标记方式。
        另外,struts2标签中,非字符类型(如boolean,int型)的属性取值,需要使用%{expr}的方式。在JSP中也可以使用EL表达式获取 Action中的成员属性,原因是struts2对request进行了封装 (org.apache.struts2.dispatcher.StrutsRequestWrapper),重写了 request.getAttribute()方法,查找范围扩大到了ActionContext的root中,核心代码如下:

Java代码  收藏代码
    1. public Object getAttribute(String s) {  
    2.         if (s != null && s.startsWith("javax.servlet")) {  
    3.             // don't bother with the standard javax.servlet attributes, we can short-circuit this  
    4.             // see WW-953 and the forums post linked in that issue for more info  
    5.             return super.getAttribute(s);  
    6.         }  
    7.   
    8.         ActionContext ctx = ActionContext.getContext();  
    9.         Object attribute = super.getAttribute(s);  
    10.         if (ctx != null) {  
    11.             if (attribute == null) {  
    12.                 boolean alreadyIn = false;  
    13.                 Boolean b = (Boolean) ctx.get("__requestWrapper.getAttribute");  
    14.                 if (b != null) {  
    15.                     alreadyIn = b.booleanValue();  
    16.                 }  
    17.       
    18.                 // note: we don't let # come through or else a request for  
    19.                 // #attr.foo or #request.foo could cause an endless loop  
    20.                 if (!alreadyIn && s.indexOf("#") == -1) {  
    21.                     try {  
    22.                         // If not found, then try the ValueStack  
    23.                         ctx.put("__requestWrapper.getAttribute", Boolean.TRUE);  
    24.                         ValueStack stack = ctx.getValueStack();  
    25.                         if (stack != null) {  
    26.                             attribute = stack.findValue(s);  
    27.                         }  
    28.                     } finally {  
    29.                         ctx.put("__requestWrapper.getAttribute", Boolean.FALSE);  
    30.                     }  
    31.                 }  
    32.             }  
    33.         }  
    34.         return attribute;  
    35.     } 
posted @ 2014-08-23 09:21  yanbl  阅读(134)  评论(0)    收藏  举报