不知道大家有没有想过这样一个问题:为什么在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;
}
}

struts2 request内幕 为什么在struts2用EL表达式可以取值的更多相关文章

  1. java实体类的属性名首字母不能大写,不然el表达式无法取值

    摘要:Java命名规范中,实体类属性名以小写字母开头,但并没有说不能以大写字母开头,然而事实告诉我,大写真不行 https://www.cnblogs.com/jnhs/p/10025757.html

  2. struts2的@Result annotation 如何添加params,并且在页面取值

    http://www.bubuko.com/infodetail-2492575.html .............................................. 标签:lai  ...

  3. Struts2技术内幕----深入解析Struts2架构与设计(一)

    Struts2的核心入口程序,从功能上来说必须能够处理Http请求,这是表示层框架的基本要求.为了达到这一目的,Struts2毫无例外地遵循了Servlet标准,通过实现标准的Filter接口来进行H ...

  4. EL表达式详解(常用表达式以及取值)

    EL表达式 学习总结 一. El表达式概念 二. El中的表达式 1. 算术表达式 2. 比较表达式 3. 逻辑表达式 4. 三元表达式 5. 判空表达式 三.EL 从四个作用域中取值 1. 概念 2 ...

  5. EL表达式获取属性值的原理

    EL表达式获取对象属性的原理是这样的:以表达式${user.name}为例EL表达式会根据name去User类里寻找这个name的get方法,此时会自动把name首字母大写并加上get前缀,一旦找到与 ...

  6. 如何将数据库中的值经过servlet传入到jsp页面,并且用EL表达式显示出值

    方法一:通过id查询某一数据库表中具体的行,将值封装在相应的对象中,如下面的对象Notice servlet中 String noticeId=request.getParameter("n ...

  7. jsp使用EL表达式回传boolean值出错的问题

    在最近做的一个项目中使用session回传的属性中有一个为boolean,报出错. 属性名字为"isAdmit",布尔类型.后来我上网查了一下,是因为我使用了Myeclipse的自 ...

  8. HTML5中的时间类型,另外EL表达式的时间值来读取时间,并且还可以更改时间

    HTML5规范里只规定date新型input输入类型,并没有规定日历弹出框的实现和样式.所以,各浏览器根据自己的设计实现日历.目前只有谷歌浏览器完全实现日历功能.相信这种局面很快就会结束,所有的浏览器 ...

  9. 简述jsp之EL表达式和jstl及其使用

    Jsp的指令之include指令include指令:代表的是页面的包含. 作用:可以把一些jsp的页面包含在一起,对外展示. 页面的布局,现在已经不用了,现在都用css+div进行布局.include ...

随机推荐

  1. jQuery 笔记

    1. 选择器  http://www.runoob.com/jquery/jquery-selectors.html 2. toggle()  用来切换 hide() 和 show() 方法   ht ...

  2. 我的博客已搬迁到http://www.lsworks.net

    我的博客已搬迁到http://www.lsworks.net

  3. 什么是MBR?(含图解)

    Mbr位于磁盘的0柱面,0磁头,1扇区. MBR       有三部分构成,主引导程序,硬盘分区表DPT和,硬盘的有效标志55AA.在512个字节的主引导扇区里. 主引导程序占446个字节,dpt占6 ...

  4. 《PHP扩展开发及内核应用》

    https://github.com/walu/phpbook/blob/master/preface.md

  5. 离线文档(DocSet)下载地址汇总

    我分享的百度网盘地址,官网下载慢:http://pan.baidu.com/s/1uOBYQ 名称 下载地址 更新时间 IOS 9.2 031-43202-A.dmg 20151209 OS X 10 ...

  6. th:each

    <tr th:each="user,userStat:${users}">userStat是状态变量,有 index,count,size,current,even,o ...

  7. 同时存在两个或多个homestead 虚拟box

    开发中发现,不同版本的homestead 里面的环境各不相同,里面的node,npm等版本都不一致,如果需要添加 不同版本的homestead同时存在可以按照以下办法处理. tips: 提供可以离线下 ...

  8. Apache+PHP+MySql 的安装及配置

    每一项技术用的人多了,就会有人将其进行优化,做成一个简单.实用.大众化的工具,这对于初识者来说是非常方便的,但是对于长久学习或工作这方面的人技术人员来说是不可取的,所以还是要学习基础的实用方法.因此, ...

  9. ubuntu系统下配置php支持SQLServer数据库

    最近在做一个项目,该项目的数据库是微软公司的的SQLserver ,数据库安装在另一台windows服务器上,而项目却部署在ubuntu server上.那么这样就会涉及到项目在linux上如何链接S ...

  10. DrawWindowFrame

    extern void DrawWindowFrame(HWND hWnd)//画窗口边框 { RECT rc; HWND DeskHwnd = ::GetDesktopWindow(); //取得桌 ...