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 * */@Controllerpublic 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基础,已经常用的变量.

时间: 2024-11-10 14:03:53

JSP隐含变量和Spring中Model在EL表达式中的读取顺序的相关文章

EL表达式中引用隐式变量

除了在jsp中9大隐式变量(在前面文章也叫预定义变量)在转化成为servlet后_jspService中可以看到: public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response) throws java.io.IOException, javax.servlet.ServletException {

EL表达式中fn函数

JSTL 使用表达式来简化页面的代码,这对一些标准的方法,例如bean的getter/setter方法,请求参数或者context以及 session中的数据的访问非常方便,但是我们在实际应用中经常需要在页面调用对象的某些方法,例如我需要调用字符串的length方法来获取字符串的 长度时,在以往的开发过程中我们必须把对象先转为String类,然后在调用其length方法,这样的代码繁琐而且容易出错. 因此JSTL内置了几个用于字符串操作的方法,可以直接在表达式中使用,大大的简化了代码,提供代码的

EL表达式中的数字类型

今天遇到一个有趣的问题,也很纳闷的问题,不过好在解决了,在此记录下来. 在控制器中定义了一个Map<Integer,String>集合,看似没有问题,将这个集合的对象map传递到一个JSP页面中,我们都知道,用EL表达式 ${map[key]}就可以取得key对应的value了.但是问题就是这么奇怪,这样取不到值.百度,才发现:EL表达式中数字1,2,3,...是Long类型.也就是EL表达式不支持Integer类型的数字作为Map的key. 修改上述集合为:Map<Long,Strin

EL表达式中如何截取字符串

EL表达式中如何截取字符串 可以截取,用fn函数:<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> 下面是JSTL中自带的方法列表以及其描述 函数名 函数说明 使用举例 fn:contains 判定字符串是否包含另外一个字符串 <c:if test="${fn:contains(name, searchString)}"> fn:c

java、el表达式中保留小数的方法

Java中: import java.math.BigDecimal; import java.text.DecimalFormat; import java.text.NumberFormat; public class format { double f = 111231.5585; public void m1() { BigDecimal bg = new BigDecimal(f); double f1 = bg.setScale(2, BigDecimal.ROUND_HALF_UP

EL表达式中fn函数 (转载)

JSTL 使用表达式来简化页面的代码,这对一些标准的方法,例如bean的getter/setter方法,请求参数或者context以及 session中的数据的访问非常方便,但是我们在实际应用中经常需要在页面调用对象的某些方法,例如我需要调用字符串的length方法来获取字符串的 长度时,在以往的开发过程中我们必须把对象先转为String类,然后在调用其length方法,这样的代码繁琐而且容易出错. 因此JSTL内置了几个用于字符串操作的方法,可以直接在表达式中使用,大大的简化了代码,提供代码的

maven创建项目中不能使用EL表达式

maven创建项目中不能使用EL表达式 默默的看雨下 问题 问题 今天在跟着慕课网学习Mybatis时,遇到了在maven创建项目中不能使用EL表达式的问题. 解决方法 1.添加maven依赖 主要有standard.jar与jstl.jar <!-- https://mvnrepository.com/artifact/taglibs/standard --> <dependency> <groupId>taglibs</groupId> <arti

Spring Model存储值在jsp EL表达式中不能正确显示(原样显示)问题

这几天我搭了一个SpringMvc环境,写了一个Controller,并且Controller里面有一个很简单的映射到jsp页面的方法,如下: 这里的Map<String,String>其实就是Model对象的一个替代品,Spring会把它当成Model的.从代码里看到我存了两个值,然后跳转到dashboard.jsp页面.如下: 当我启动项目,并访问时发现EL表达式原样输出,如下: 我查看了我所有配置,发现没有什么问题.百思不得其解,后来经过google一番,发现原来是web.xml版本不对

JSP标签语法、JSTL标签库、EL表达式辨析

<一.JSP > JSP 语法语法格式: <% 代码片段 %>或者<jsp:scriptlet> 代码片段</jsp:scriptlet> JSP声明 <%! declaration; [ declaration; ]+ ... %><%! int i = 0; %> <%! int a, b, c; %> <%! Circle a = new Circle(2.0); %> 或者<jsp:declara