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

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

请看例子:

这是一个action

  1. package com.wuyou.action;
  2.  
  3. import com.opensymphony.xwork2.ActionSupport;
  4. import org.springframework.context.annotation.Scope;
  5. import org.springframework.stereotype.Controller;
  6.  
  7. @Controller
  8. @Scope(value = "prototype")
  9. public class TestAction extends ActionSupport {
  10.  
  11. private Integer id = 123;
  12. private String name = "无忧之路";
  13.  
  14. public String execute() {
  15. return "success";
  16. }
  17.  
  18. public Integer getId() {
  19. return id;
  20. }
  21.  
  22. public void setId(Integer id) {
  23. this.id = id;
  24. }
  25.  
  26. public String getName() {
  27. return name;
  28. }
  29.  
  30. public void setName(String name) {
  31. this.name = name;
  32. }
  33.  
  34. }

对应的struts配置文件:

  1. <package name="default" extends="struts-default" namespace="/">
  2.  
  3. <action name="test" class="testAction">
  4. <result>/success.jsp</result>
  5. </action>
  6.  
  7. </package>

对应的success.jsp:

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <html>
  3. <head>
  4. <title></title>
  5. </head>
  6. <body>
  7.  
  8. ${id}
  9.  
  10. </body>
  11. </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类源代码:(点击展开)

  1. public class StrutsRequestWrapper extends HttpServletRequestWrapper {
  2.  
  3. /**
  4. * The constructor
  5. * @param req The request
  6. */
  7. public StrutsRequestWrapper(HttpServletRequest req) {
  8. super(req);
  9. }
  10.  
  11. /**
  12. * Gets the object, looking in the value stack if not found
  13. *
  14. * @param s The attribute key
  15. */
  16. public Object getAttribute(String s) {
  17. if (s != null && s.startsWith("javax.servlet")) {
  18. // don't bother with the standard javax.servlet attributes, we can short-circuit this
  19. // see WW-953 and the forums post linked in that issue for more info
  20. return super.getAttribute(s);
  21. }
  22.  
  23. ActionContext ctx = ActionContext.getContext();
  24. Object attribute = super.getAttribute(s);
  25. if (ctx != null) {
  26. if (attribute == null) {
  27. boolean alreadyIn = false;
  28. Boolean b = (Boolean) ctx.get("__requestWrapper.getAttribute");
  29. if (b != null) {
  30. alreadyIn = b.booleanValue();
  31. }
  32.  
  33. // note: we don't let # come through or else a request for
  34. // #attr.foo or #request.foo could cause an endless loop
  35. if (!alreadyIn && s.indexOf("#") == -1) {
  36. try {
  37. // If not found, then try the ValueStack
  38. ctx.put("__requestWrapper.getAttribute", Boolean.TRUE);
  39. ValueStack stack = ctx.getValueStack();
  40. if (stack != null) {
  41. attribute = stack.findValue(s);
  42. }
  43. } finally {
  44. ctx.put("__requestWrapper.getAttribute", Boolean.FALSE);
  45. }
  46. }
  47. }
  48. }
  49. return attribute;
  50. }
  51. }

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. 在java中HttpServletResponse响应中文出现乱码。

    以字符串的形式输出. 1.response.getWriter().write("您好中国hello"); 如果这样输出的话.则浏览器结果为: 2.加上代码 response.se ...

  2. Navicat for mysql linux 破解方法

    安装方法   进入下载页面:http://www.navicat.com.cn/download/navicat-for-mysql ,选择Linux版本进行下载,下载后解压安装包,运行 start_ ...

  3. [android]netd与NetworkManagementService初印象

    [功能]Netd是什么,主要负责什么功能 为什么这次会接触Netd主要是因为在设置防火墙时候碰到了.关于Netd可以干什么可以从Netd的源码中CommandListener中得到答案.按照我的理解, ...

  4. 解决FPDF报错:FPDF error: Not a JPEG file / FPDF error: Not a PNG file

    最近有个项目需要用到FPDF,但是输出的时候报错: FPDF error: Not a JPEG file: http://***/data/attachment/forum/201603/19/10 ...

  5. gson小练习之嵌套复杂数据解析

    package com.zf.demo; import java.util.List; import com.google.gson.Gson; public class JGson { /** * ...

  6. PHP的$_SERVER['HTTP_HOST']获取服务器地址功能详解,$_SERVER['HTTP_X_FORWARDED_HOST']

    uchome的index文件中的二级域名功能判断,使用了php的$_SERVER['HTTP_HOST'],开始对这个不是很了解,所以百度了一下,发现一篇帖子有点意思,转发过来做个记录. 在php中, ...

  7. Huawei HG556a A版 刷 openwrt

    一直想玩玩openwrt,调研了一下 HG556a尽管散热很烂,但性价比超高,于是淘宝入手一台A版,A版和C版区别为wifi芯片: 到货后在网上找了几个教程便开始动手刷openwrt,但刷机的过程中还 ...

  8. Head of a Gang (map+邻接表+DFS)

    One way that the police finds the head of a gang is to check people's phone calls. If there is a pho ...

  9. oracle linux了解基本命令行

    1.      Linux的版本:核心(kernel)版本和发行(distribution)版本 2.      复制.删除和移动文件的命令 cp [选项] 源文件或目录  目标文件或目录 -R,-r ...

  10. SQL学习中(一)序列

    序列可以理解数值序列生成器,通俗的说是按照已经设定的规则自动产生数据的方案对象.--SQL SERVER不支持 个人认为序列类似于SQLSERVER中的identity(1,1),可以用于在表中添加数 ...