日期:2014-05-16 浏览次数:20989 次
??? 最近用SSH框架做个小应用,在页面上显示数据库的表数据,并且对每行数据都可以进行编辑和删除操作,编辑和删除提交后,利用Ajax发送请求到后台处理数据库的操作,并且更新页面的显示数据。现在问题就来了,删除提交后,页面由4条数据变为3条,但是如果按F5或手动刷新页面后,数据又变为4条,根本没变。问题出在哪里呢?
??? 首先:查看后台数据库,发现表里的数据确实少了一条,即删除操作是成功的,不是数据库操作的原因,那是什么问题呢?
??? 这时候自然地想到了缓存机制,因为应用的是SSH框架,对数据库的管理是通过Spring和Hibernate进行的,而Spring只是一个管理器而已,并非与数据库直接交流的,所以缓存机制是采用的Hibernate的缓存机制(hibernate缓存机制介绍见文章末尾),但是根据Hibernate缓存机制的描述,对程序和配置进行了检查之后,也相应的做了一些改动,但是结果并没有预想的那样,问题还是没有解决,这下彻底茫然了。
??? 当然思考仍在继续,我的工作也没有白做,因为前两个步骤至少证明了一个问题,那就是问题不是出现在服务器端,既然如此,那么肯定是客户端的问题了。
??? 直到这时,问题才初露端倪,客户端说到底就是一个浏览器,因为确定是缓存问题,那么首先就在页面上禁用缓存,设置方法如下:
????? 1、在服务端加 header("Cache-Control: no-cache, must-revalidate");
2、在ajax发送请求前加上 xmlHttpRequest.setRequestHeader("If-Modified-Since","0");
3、在ajax发送请求前加上 xmlHttpRequest.setRequestHeader("Cache-Control","no-cache");
可能不止这几种,具体的做法就是禁止缓存,或者设置内容过期时间等。当然,这时候问题就解决了。这时候回过头来看一下,这页面缓存是什么引起的呢?因为每次删除操作提交后,都是通过Ajax发送请求从数据库里直接拿数据的,应该每次都是不同的呀,为什么会有缓存现象呢?难道是Ajax的原因,就在网上搜了下Ajax缓存,这下就明白了,原来根源是在这里,先把Ajax缓存的原理贴出来:
????? 当Ajax第一次发送请求后,会把请求的URL和返回的响应结果保存在缓存内,当下一次调用Ajax发送相同的请求时,注意,这里相同的请求指的是URL完全相同,包括参数,浏览器就不会与服务器交互,而是直接从缓存中把数据取出来,这是为了提高页面的响应速度和用户体验。这种设计使客户端对一些静态页面内容的请求,比如图片,css文件,js脚本等,变得更加快捷,提高了页面的响应速度,也节省了网络通信资源。但是对于一些后台数据的提取时就需要做一些改变,否则虽然数据在后台已经发生改变,但是页面缓存中并没有改变,对于相同的URL,浏览器只是简单的从缓存中拿数据(有点罗嗦了)。问题找到了,怎么解决呢?其实办法很简单,只要让每次请求的URL不同就可以了。方法是在URL后面加一个参数,参数的值每次都不同,可以是一个随机数(Math.random()),也可以是当前时间(new Date().getTime()),只要满足条件即可。当然,以上这些只是针对Ajax发送的GET请求,如果你用POST方法发送请求,所有的工作都省了。但是你真的愿意这么做么?
附:hibernate缓存机制介绍(传送门:http://tenn.iteye.com/blog/120559):
1:Hibernate缓存概述
首先在介绍Hibernate缓存之前,笔者在这里做一个小小的比喻,让大家先知道利用缓存的好处。
这个比喻设计的事物有四个,一个是消费者,一个是该消费者附近的电脑城,一个是联想笔记本,一个是联想公司。笔记本是现在普及的商品,消费者想要去买一台联想笔记本,大家想想看,是去附近的电脑城买得快?还是去联想公司买得快?..当然是在电脑城买得快咯,总不能跑到联想公司去买吧?在这里消费者被比做应用程序,电脑城被比做缓存,联想笔记本被比做数据,联想公司被比做数据库。正像我们比喻的那样,应用程序查找我们需要的数据是从缓存中找得快,还是去数据库找得快?答案应该就不用我讲了吧!
缓存是介于物理数据源与应用程序之间,是数据库数据在内存中的存放临时copy的容器,是其作用是为了减少应用程序对物理数据源访问的次数,从而提高了应用的运行性能。
Hibernate在进行读取数据的时候,根据缓存机制在相应的缓存中查询,如果在缓存中找到了需要的数据(我们把这称做“缓存命中”),则就直接把命中的数据作为结果加以利用,避免的了建立数据库查询的性能损耗。说白话点就是,数据放在缓存中,当应用程序还需要他们的时候,就不必再去查数据库了,根据缓存策略从内存中查找速度就会快很多了。
2:Hibernate缓存分类
Hibernate缓存我们通常分两类,一类称为一级缓存也叫内部缓存,另一类称为二级缓存。Hibernate的这两级缓存都位于持久化层,存放的都是数据库数据的拷贝,那么它们之间的区别是什么呢?为了理解二者的区别,需要深入理解持久化层的缓存的一个特性:缓存的范围。
缓存的范围决定了缓存的生命周期以及可以被谁访问。缓存的范围分为三类。
(1) 事务范围:缓存只能被当前事务访问。缓存的生命周期依赖于事务的生命周期,当事务结束时,缓存也就结束生命周期。在此范围下,缓存的介质是内存。事务可以是数据库事务或者应用事务,每个事务都有独自的缓存,缓存内的数据通常采用相互关联的的对象形式, 一级缓存就属于事务范围。
(2) 应用范围:缓存被应用