zoukankan      html  css  js  c++  java
  • struts2 request内幕 为什么在struts2用EL表达式可以取值

    不知道大家有没有想过这样一个问题:为什么在action中的实例变量,没有使用request.setAttribute()方法将值添加到request范围内,却能在jsp中用EL表达式取出?

    众所周知,EL表达式只能取出pageContext,request,session,application属性范围的值。然而,在struts2中能突破这一个限制,成功的取出action中的实例变量值。

    请看例子:

    这是一个action

    package com.wuyou.action;
    
    import com.opensymphony.xwork2.ActionSupport;
    import org.springframework.context.annotation.Scope;
    import org.springframework.stereotype.Controller;
    
    @Controller
    @Scope(value = "prototype")
    public class TestAction extends ActionSupport {
    
        private Integer id = 123;
        private String name = "无忧之路";
    
        public String execute() {
            return "success";
        }
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
    }

    对应的struts配置文件:

     <package name="default" extends="struts-default" namespace="/">
    
            <action name="test" class="testAction">
                <result>/success.jsp</result>
            </action>
    
        </package>

    对应的success.jsp:

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title></title>
    </head>
    <body>
    
    ${id}
    
    </body>
    </html>

    页面输出:123

    其实,在struts2中使用的request并非为tomcat提供的,而是经过了struts2所包装过的org.apache.struts2.dispatcher.StrutsRequestWrapper对象。

    这个类做了些什么事情呢?

    原来,我们在调用EL表达式的时候,或者request.getAttribute(String key)方法的时候,struts2会先在原来的request中调用request.getAttribute()方法获取该值,如果查找不到,则继续往OgnlValueStack查找,由于action对象在ognl值栈,返回action里名为"id"的实例变量值,即可显示在页面上。

    我们可以尝试在jsp中输出request的类名:

    <%=request.getClass()%>

    也可以在action里面输出:

    System.out.println(ServletActionContext.getRequest().getClass());

    均输出:class org.apache.struts2.dispatcher.StrutsRequestWrapper

    这下真相大白了吧!

    附StrutsRequestWrapper类源代码:(点击展开)

    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);
            if (ctx != null) {
                if (attribute == null) {
                    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 && 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;
        }
    }
    View Code
  • 相关阅读:
    C语言笔记
    js学习笔记
    Javascript学习笔记
    Java基础知识
    使用 StackExchange.Redis 封装属于自己的 RedisHelper
    StackExchange.Redis 使用资料
    .NET平台下Redis使用(三)【ServiceStack.Redis学习】
    .NET平台下Redis使用(二)【StackExchange.Redis学习】
    Redis 详解 (一) StackExchange.Redis Client
    .NET中使用Redis
  • 原文地址:https://www.cnblogs.com/wuyou/p/3317023.html
Copyright © 2011-2022 走看看