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
  • 相关阅读:
    base64是什么东东,base64 图片显示,在线编辑器
    中文字符 与 十六进制Unicode编码 相互转换
    全面理解Python中self的用法
    Python之使用元类MetaClass
    Python之MySQL数据库连接驱动aiomysql的使用
    Python实战网站开发:Day2编写Web App骨架
    Python实战网站开发:Day3编写ORM
    Python之MySQL数据库连接驱动pymysql的使用
    【CV基础】为什么一些深度学习的图像预处理使用mean=[0.485, 0.456, 0.406] and std=[0.229, 0.224, 0.225]来正则化?
    与人合作创业是一门大艺术(转)
  • 原文地址:https://www.cnblogs.com/wuyou/p/3317023.html
Copyright © 2011-2022 走看看