(十一)Struts2进阶之EL和OGNL读取值栈数据对比

上篇文章中说了OGNL在Struts2中的使用方法。然而,EL其实也是可以读取值栈中的数据,那么EL读取值栈的数据和OGNL读取值栈的数据有什么不同呢?



还记得之前那个第八篇文章中的例子吗?代码都和它们一样,只是改一下getvalue.jsp

    
        
        
        
    
    
使用jstl
${user.username} ${user.password}

两种方式输出的结果一样。

那么我们就来探讨一下为啥EL也能获取到值栈中的数据?是怎么获取的呢?

带着这个问题,我们来看看Struts2的默认核心控制器,因为它的实质是一个过滤器,过滤所有的页面,所以我们从它下手。

进入它的源码,看它的doFilter方法,里面有这么一句

request = prepare.wrapRequest(request);

这和request有联系,我们进入wrapRequest方法,里面只有这么一句话

request = dispatcher.wrapRequest(request);

那么我们继续进入这个wrapRequest方法,在该方法中,我们有这么一行

request = new StrutsRequestWrapper(request, disableRequestAttributeValueStackLookup);

继续进入StrutsRequestWrapper类,终于到达目的地,该类中有这么一个方法

public class StrutsRequestWrapper extends HttpServletRequestWrapper {
    // 获取request中的属性值
    public Object getAttribute(String key) {
        if (key == null) {
            throw new NullPointerException("You must specify a key value");
        }

        if (disableRequestAttributeValueStackLookup || key.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(key);
        }
        // 获取ActionContext实例
        ActionContext ctx = ActionContext.getContext();
        // 通过key获取对应的值
        Object attribute = super.getAttribute(key);
        // 如果在request中没有找到对应的值,如果找到了,直接返回
        if (ctx != null && attribute == null) {
            if (!alreadyIn && !key.contains("#")) {
                try {
                    ctx.put(REQUEST_WRAPPER_GET_ATTRIBUTE, Boolean.TRUE);
                    // 取得值栈
                    ValueStack stack = ctx.getValueStack();
                    if (stack != null) {
                        // 从值栈中寻找对应的值
                        attribute = stack.findValue(key);
                    }
                } finally {
                    ctx.put(REQUEST_WRAPPER_GET_ATTRIBUTE, Boolean.FALSE);
                }
            }
        }
        // 返回找到的值
        return attribute;
    }
}

通过上面的代码,可以很清楚的看到EL表达式是怎么获取值栈中的值。

总结如下

其实是Struts2底层增强了getAttribute方法
(1)首先从request域获取值,如果找到了,直接返回
(2)如果没有找到,则去值栈中找,然后把值放入域对象中

可以看出使用EL表达式获取值栈中的值效率低,因为它经历了好多步。所以尽量避免使用EL去获取值栈中的值。

你可能感兴趣的:((十一)Struts2进阶之EL和OGNL读取值栈数据对比)