JSP隐含变量和Spring中Model在EL表达式中的读取顺序
偶然中存在着必然,必然中存在着偶然
偶然出现的bug,必然存是由代码的不合理甚至错误的
代码逻辑越长,越复杂,就越容易出现bug
之前项目里几次偶然出现了一个bug,简单的描述就是第一次新增了之后进行一个B操作,之后在新增一次,页面中的一个隐含变量会"记住"这个新增之后的id,因为这个需要连续两次新增且在第一次新增之后进行B操作之后才会出现,所以很长时间里面都是偶然出现.
定位问题的过程就是进行很多次的操作,然后逐个排除.尝试自己的猜测,再次进行代码级的排除.定位这种问题一定要有一定的测试量.就像有一个入口和一个出口的迷宫,答案就是有偶发性bug的路径.
最后发现问题是当时model中的id为null,而在B操作中session中也存了id.
下面一起来看一下,El读取变量的顺序
后台代码
package com.my.innerParam.test; import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext; import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping; /**
* 测试几个内置变量中在EL读取的顺序
* @author rocky
*
*/
@Controller
public class InnerParam
{
@RequestMapping("/innerParamTest")
public String innerParamTest(HttpServletRequest request,HttpServletResponse response,Model model)
{
HttpSession session = request.getSession();
session.setAttribute("session", "session223");
ServletContext application = request.getServletContext();
// application.setInitParameter("appicationParam", "appicationParam");
//Initialization parameters can not be set after the context has been initialized
application.setAttribute("appicationAttr", "applicationAttr");
request.setAttribute("request", "request");
model.addAttribute("model", "model123");
return "/testParam/testParam1";
}
//当变量名字相同时判断EL表达式用哪一个
@RequestMapping("/innerParamTest2")
public String innerParamTest2(HttpServletRequest request,HttpServletResponse response,Model model)
{
HttpSession session = request.getSession();
session.setAttribute("test", "session223");
ServletContext application = request.getServletContext();
// application.setInitParameter("appicationParam", "appicationParam");
//Initialization parameters can not be set after the context has been initialized
application.setAttribute("test", "applicationAttr");
request.setAttribute("test", "request");
model.addAttribute("test", "model123");
return "/testParam/testParam2";
}
//当model是null的时候
@RequestMapping("/innerParamTest3")
public String innerParamTest3(HttpServletRequest request,HttpServletResponse response,Model model)
{
HttpSession session = request.getSession();
session.setAttribute("test", "session223");
ServletContext application = request.getServletContext();
// application.setInitParameter("appicationParam", "appicationParam");
//Initialization parameters can not be set after the context has been initialized
application.setAttribute("test", "applicationAttr");
request.setAttribute("test", "request");
model.addAttribute("test", null);
return "/testParam/testParam3";
}
}
第一种情况,显示
代码
<h3>session : ${session}</h3>
<h3>appicationAttr : '${appicationAttr}'</h3>
<h3>appicationParam : '${appicationParam}'</h3>
<h3>request : '${request}'</h3>
<h3>model : '${model}'</h3> 运行结果
session : session223
appicationAttr : 'applicationAttr'
appicationParam : ''
request : 'request'
model : 'model123'
第二,变量名字相同时
<h3>session : ${test}</h3>
<h3>appicationAttr : '${test}'</h3>
<h3>appicationParam : '${test}'</h3>
<h3>request : '${test}'</h3>
<h3>model : '${test}'</h3> 运行结果
session : model123
appicationAttr : 'model123'
appicationParam : 'model123'
request : 'model123'
model : 'model123'
第三,当model为null时
<h3>session : ${test}</h3>
<h3>appicationAttr : '${test}'</h3>
<h3>appicationParam : '${test}'</h3>
<h3>request : '${test}'</h3>
<h3>model : '${test}'</h3>
运行结果
session : session223
appicationAttr : 'session223'
appicationParam : 'session223'
request : 'session223'
model : 'session223'
第四,当session也为null时
<h3>session : ${test}</h3>
<h3>appicationAttr : '${test}'</h3>
<h3>appicationParam : '${test}'</h3>
<h3>request : '${test}'</h3>
<h3>model : '${test}'</h3> 运行结果
session : applicationAttr appicationAttr : 'applicationAttr' appicationParam : 'applicationAttr' request : 'applicationAttr' model : 'applicationAttr'
结论:1.model > session >application>requset的,其他的就不测试了,这几个是最长用的.
2.慎重使用session变量,这个范围太大了,如果因为一个模块把变量存在session中实现起来更容易,就这样做了,那么这就很容易为后面埋下bug.
如果把变量放到session里,就说明它的作用域是session,它的有效范围是当前会话。 所谓当前会话,就是指从用户打开浏览器开始,到用户关闭浏览器这中间的过程。这个过程可能包含多个 请求响应。也就是说,只要用户不关浏览器,服务器就有办法知道这些请求是一个人发起的,整个过程被 称为一个会话(session),而放到会话中的变量,就可以在当前会话的所有请求里使用。 如果把变量放到application里,就说明它的作用域是application,它的有效范围是整个应用。 整个应用是指从应用启动,到应用结束。我们没有说“从服务器启动,到服务器关闭”,是因为一个服务 器可能部署多个应用,当然你关闭了服务器,就会把上面所有的应用都关闭了。 application作用域里的变量,它们的存活时间是最长的,如果不进行手工删除,它们就一直可以使用。 与上述三个不同的是,application里的变量可以被所有用户共用。如果用户甲的操作修改了application 中的变量,用户乙访问时得到的是修改后的值。这在其他scope中都是不会发生的,page, request,
参考blog:JSP九大内置对象及四个作用域
3.熟悉jsp基础,已经常用的变量.
JSP隐含变量和Spring中Model在EL表达式中的读取顺序的更多相关文章
- JS中如何使用EL表达式中的对象
JS中如何使用EL表达式中的对象 2017年09月25日 15:33:09 lhpnba 阅读数:4859 1.js中使用el表达式要加双引号或单引号:'${list}' 2.js变量获取el表达 ...
- jsp中如何判断el表达式中的BigDecimal==0
比较蠢一点的做法: <c:if test="${not ((someBigDecimal < 0) or (someBigDecimal > 0))}"> ...
- IT兄弟连 JavaWeb教程 EL表达式中的内置对象
EL语言定义了11个隐含对象,它们都是java.util.Map类型,网页制作者可通过它们来便捷地访问Web应用中的特定数据.表1对这11个隐含对象做了说明. 1 EL表达式中的内置对象 这11个隐 ...
- EL表达式中引用隐式变量
除了在jsp中9大隐式变量(在前面文章也叫预定义变量)在转化成为servlet后_jspService中可以看到: public void _jspService(final javax.servle ...
- 在jsp中怎么使用Cookie?el表达式中获取cookie的问题
初学jsp,不清楚cookie的使用方法,希望高手指点一下! 一般来说有两种办法,在JSP中使用Java的嵌入脚本. 例如: 写入Cookie <html> <head>. ...
- EL表达式中fn函数 (转载)
JSTL 使用表达式来简化页面的代码,这对一些标准的方法,例如bean的getter/setter方法,请求参数或者context以及 session中的数据的访问非常方便,但是我们在实际应用中经常需 ...
- java、el表达式中保留小数的方法
Java中: import java.math.BigDecimal; import java.text.DecimalFormat; import java.text.NumberFormat; p ...
- EL表达式中如何截取字符串
EL表达式中如何截取字符串 可以截取,用fn函数:<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/ ...
- 关于EL表达式中requestScope和param区别
今天演示EL表达式的时候发现自己jsp的基础实在是薄弱,在这个很简单的问题上迷惑了很久. 首先在看遇到的问题: 在浏览器地址输入,表示传入一个参数test,值为123 http://localhost ...
随机推荐
- matlab FDR校正
http://home.52brain.com/forum.php?mod=viewthread&tid=27066&page=1#pid170857 http://www.mathw ...
- Github 简明教程
http://www.runoob.com/w3cnote/git-guide.html http://rogerdudler.github.io/git-guide/index.zh.html
- iOS SDWebImage使用详解
这个类库提供一个UIImageView类别以支持加载来自网络的远程图片.具有缓存管理.异步下载.同一个URL下载次数控制和优化等特征. 使用示范的代码:UITableView使用UIImageView ...
- 柯里化/偏函数/Curring用法
把接受多个参数的函数变成一个单一参数的函数,并且返回接受余下的参数而有返回结果的新函数的技术 下面我们以实例说明: var toString = {}.toString; var isString = ...
- sublime 函数跳转插件 — ctags 安装和使用
ctags 是 sublime 下一个函数跳转的插件,可以让你方便地从函数调用的位置跳到函数定义的位置.相对于其他插件,ctags 的安装稍微有点复杂,这里记录下备忘. 首先,假设已经安装 Packa ...
- canvas api
基本骨骼 <canvas id="canvas" width=1000 height=1000 style="border: 1px black dotted&qu ...
- GitHub: Windows 下的简单使用
这段时间在博客园多了很多关于GitHub的文章,但是我的确没怎么看懂.不过这几天简单的看了写资料,亲身操作之后也有了一点体会.这算是最简单的GitHub入门了吧,基本全是鼠标操作.这也是这几天的总结, ...
- 阿里巴巴高新能数据源com.alibaba.druid.pool.DruidDataSource的jar包配置
aspectjweaver-1.7.4.jar druid-0.2.9.jar 两个包,用于提供com.alibaba.druid.pool.DruidDataSource
- webpack入坑之旅(一)不是开始的开始
最近学习框架,选择了vue,然后接触到了vue中的单文件组件,官方推荐使用 Webpack + vue-loader构建这些单文件 Vue 组件,于是就开始了webpack的入坑之旅.因为原来没有用过 ...
- 0924Linux常用命令
写的不错 转载了,有需要的同学们,可以多多学习,适合小白哦 http://blog.csdn.net/xiaoguaihai/article/details/8705992/ 关于最后增加一点 tar ...