级联控件大数据解决方案

级联控件是在web开发中经常使用的,特别是在信息录入页面。级联控件也是我们开发人员及其头痛的开发之一(至少我是这样的),特别是当级联数目相当多时这个问题就更明显了。设想我们要编写一个省、市、县、乡、村的5级级联,如果这要完全动手写,那么……

  1. JAVA与级联:
            现阶段JSP页面(不考虑WEB2.0技术和他的AJXA实现)的级联控件都是以客户端脚本的形式出现的(javascript),实现方式有很多种,但是原理是一样的,主要是预先将级联控件中可能出现的值预先写到JSP页面上,当用户的选择发生改变的时候读取预先设定好的值显示给用户。
            这样的做法的好处是速度快——这是在客户端的IE浏览器上运行的脚本,速度能不快吗?
            但是这样做也有明显的不足。
           a、数据容量不足:试想你需要对省、市(市级行政区)、区/县、乡,还不包括村的4级联动,那么这里到底有多少数据呢?我们保守点估计1*10*20*100,想一想我们需要在IE页面上维护20000条数据记录!所以这种方式只能用于数据量较少的3级或2级联动。
           b、维护困难:这种将数据写在客户端脚本的方式通常是通过硬编码的方式来实现的,而不是将数据存储为若干对象或者是这些对象的集合,这是如果用户的需求发生了变化,比如用户现在不再需要显示某个市下面字母“A”开头的所有区/县信息,那么我们就要对页面上的编码做疯狂的修改(永远都要记住面向变更设计),噩梦中……

            当然有时我们也会采用“变动一次查询一次的方式”来实现一个级联控件,这样就可以解决如上所提到的第一个问题,但是这就带来了一个大问题和一个小问题。
            小问题是所有的IE页面都是无状态保持的,那么一旦发生信息请求,用户填写的其他信息就可能丢失!这可以用弹出页面的方式来解决,所以这是一个小问题。
            大问题就是:数据库压力大大增加!我们再试想一下这样的情况:一个开发者做了一个四级联动,并为每一个子控件的都做了处理(这一并不是一次变动就查询一次数据库,而是最多可能一次变动查询三次数据库),我们做一个择中:一次变动查询2次数据库。这时假使有20个用户在进行这样的操作(这在并发压力测试中算是比较少的用户情况了),那么数据库在一个单位时间内将会出现40次额外的操作,这是一笔可观的资源支出。
  2. Net与级联控件。
            首先不得不佩服.Net的工程师们,他们成功的模仿了JAVA的成功之处、弥补了JAVA的不足、想到了大家都很容易想到,但是却没有想到的问题。
            .Net下处理级联就要比Java灵活得很多了,这就得益于.Net下为Web开发提供的页面视图状态“ViewState”还有为数据处理提供的“DataSet”了,他们为小批量数据的级联控件处理带来了福音,但是在处理大批量数据级联控件的时候仍存在着不足。笔者分析如下:
            DataSet不但可以存储较为庞大的数据(这些数据可以分布在一个或多个DataTable中),而且可以通过类似于sql的过滤语句对这个数据集中的数据进行过滤显示,不但如此更重要的是对数据的操作全部都在内存中完成,不会去请求数据库联接,但是这也只能处理小批量的级联控件数据,为什么呢?原来瓶颈出在页面视图状态“ViewState”上面。ViewState的原理是将.Net页面的显示信息(当然包括数据信息)串行化到IE页面,当页面发出请求时再将这些串行化的数据回读,这样页面的状态就可以保存下来,而问题也就出现在这个过程中,笔者曾用700条记录进行试验,这是ViewState就已经吃不消了,更何况是上万条的数据?
  3. 笔者的解决方法。
    前提分析:
            a、数据量前提:就如上所提到的例子中,20000条数据对IE页面来说确实是一个天文数字,但是对于服务器内存来说就是一个小数目了,我们可以考虑将级联空间所涉及的数据存放在内存中,就如同.Net中提供的DataSet一样,在Java中我们也可以做到,数据访问对象(数据持久层)的数据实体对象/实体对象集合为我们提供了解决的途径(entity bean),再通过单例模式我们就可以将这些数据存储在内存中(生命周期为一个Web服务开启的周期,除非服务器重启,不然内存中的数据不会消失。至于单例模式我想就不用多说了吧,不知道的朋友建议参看一下其他资料),而数据的过滤算法就只有大家自己写了,尽量考虑效率就行了。
            如果各个级联控件多读取的数据总量不超过100000条,那么可以考虑笔者所介绍的方法,如果超过了100000条可以考虑笔者介绍的方法和数据库读取的方法联合使用。

            b、状态保持:上文已经提到在.Net中有ViewState帮助保存状态,但是并不建议将数据存存在ViewState中(如果您考虑了用单例模式将数据永久存储在内存中,也就不需要存在ViewState中了)。对于Java来说就稍微难了一点,笔者的方法是通过弹出式页面来进行级联数据的选择,这样就不会因为回传而是其他数据丢失了。速度方面当然要比建立数据库联接要快得多。
原文地址:https://www.cnblogs.com/liulaolaiu/p/11744349.html