阶段性的登陆成功

三个月磨剑 —— 不只是几万行的代码

    Normandy系统,一个B2C垂直平台,已经开发了三个月,这一段时间以来的经历,觉得应该有一个完整的结束。这个系统目前已经完成了前台注册,登陆,购买下单,购物车,支付宝付款,订单同步,过期订单处理,以及多个页面的商品分栏目展示,商品展示等功能,后台完成了首页管理,热报管理(一种类似于系统配置的快捷方式),产品库管理,商品管理,会员管理,权限管理,商品交易查询等,总的进度,应该是在60%左右,剩下的工作,一是要开发新的功能,比如买家个人中心,积分系统,后台相对而言功能也还需要去丰富,二是要针对当前的模块进行调整,现在的部分模块由于之前没有好的思考和设计,带有很大的局限性,下面也会提及。

    首先说说为什么开始了这个工作。

    以前在支付宝工作,持久层框架使用的是Ibatis,这种浅层的封装带有很大的灵活性,而且相对于hibernate而言,有很大的便利性,使用门槛低,没有hibernate讲究的严格的映射关系,而且对于编写DO/DAO/XML文件的体力活,支付宝的首席架构师程立编写了一个自动工具dalgen,可以根据配置文件中的sql,直接生成,很快捷方便。

    来到网易,这些持久层框架开始离我而去,系统中使用的,是基本的springJdbcTemplate,只是封装了获取连接提交关闭连接的基本操作,对于搜索条件的封装,搜索结果的实例化,都需要自己去编写一些耗费体力的代码解决。比如rowMapper,说白了就是从数据库中取出某个字段的值,set到某个DO类中,这个工作如果针对于特定的表结构和特定的DO类,每个不同的结构都会需要新的代码去实现。而惯性思维上讲,这个过程可以抽象出来,变成两个遍历过程,一是从数据库中遍历字段取值,而是遍历DO类设置到特定字段上。所以我们可以抽象一个通用方法,返回值即为指定类型的DO对象,而其做法,就是遍历ResultSet,根据传入的类名,获取其中生命的属性名称,使用这个名称去获取ResultSet中的值,然后通过反射,调用属性对应的set方法,去实现一个设值的动作,最后完成后,整个对象就已经完成了初始化,返回即可。就是如此简单的一个过程。、

    于是尝试着封装了这个过程,做完了后发现其实对于一些数据库操作还有其他很大去思考琢磨的空间,用惯了框架提供的便利性,现在自然还是希望能够有一个功能稍微完善的通用父类,去实现一些基础功能。最后的结果是封装了一系列通用API,大概有30-40个左右,覆盖了增删查改,批量操作等,伴随着后续的系统开发,也逐渐完善。

    做完了这个事情,由于个人所在组,是搜索与挖掘,搜索主要是lucene这个东西,所以就开始接触了lucene,接触后发现这个东西很简单,就开始做一些练习,做一些封装,比如实现数字型的过滤器等。然后就开始针对于通用的搜索服务做一些API,包括采用xml配置文件配置的方式快速搭建针对于数据库中某张表的搜索服务器。做完了搜索服务,需要解决的问题就是数据库的数据和索引文件同步的问题,自然的想到了上面第一步中封装的DAO抽象类,能否通过这个类中提供的一些通用方法直接的去获取数据更新索引,而不需要开发人员去单独开发代码实现呢。

    后来的实现方式,是采用拦截器,拦截方法,当增加,删除,修改等发生后需要更新索引的情况,就在拦截方法中,将影响到的数据记录的ID保存下来,在下次定时任务中自动更新索引。同时跟缓存配合以提升性能。这个过程对于开发人员来说是隐藏的,只需要一个特定格式的配置文件即可。这其中涉及到不少问题,比如我们配置的需要进行建立索引的类型名称是数据库表对应的DO类,其中为了能对应获取数据库的数据并设置到相应的字段,就必须两者之间名称相同,并且对于那些采用下划线分割的情况,也必须保持一致。同时底层严重依赖了上面开发的dao抽象父类,而且对于影响到的数据的捕获,采用的是用sql中的条件动态封装一个查询过程去获取,这无形中会增加一次数据库操作,而且一旦抽象父类出现bug,会导致索引无法被刷新或者刷新错误。这其中对于抽象父类而言,是一个很大的挑战,当然也正是由于有了这样一个通用的抽象封装,才有了这样的一个通过拦截器动态拦截的实现方案。

    当这些工作做完之后,发现这样的一个小模型,其实是可以放到任何地方去尝试一下的,于是正好考虑要做什么类型的网站,一个朋友正好在做B2C的平台,用的是免费的shopex系统,而这方面,也正好是我感兴趣的,于是就决定做一个B2C的购物网站。

    一直到了现在开发了3个多月,伴随而来的是代码量增大的很难去控制,还有就是一些原本不成熟的想法由于考虑不全直接上马带来的恶果。比如上述的DAO抽象父类。这个父类在简单的应用过程中,是能满足各种条件的使用,但是真正在这样一个规模的网站系统上作为底层使用,越来越多的问题暴露出来,比如sql语句的组装问题,单引号和双引号的含义是不同的,而且是必须要区分各种类型的不同封装方法的,这个工作如果不做将带来很大的问题,就是sql生成失败导致无法操作数据库的问题。所以现在决定了放弃这个通用的抽象层而转到自己熟悉并喜欢的ibatis,虽然这其中又会有很多的工作去做。又会有很多的事情由于框架帮你实现了,已经毫无技术含量。

    所以现在这个系统,最大的问题不在于技术,而在于业务。

    再说说其中的一些收获,首先是富文本控件,ckeditor,这个控件可以进行富文本编辑,但是很不幸的,他的上传和服务器图片浏览功能不支持java,所以需要自己开发。通过firebug查看其中的上传窗口的源代码可以知道,其实他就是一个form,而这个formjava中没有实现而已,所以只要对应于其中的url,实现一个自己系统的action就可以了,其中图片怎么存放之类属于自己代码中去控制。图片上传很简单,直接使用apacheServletFileUpload就可以完成。无非是重新命名文件存放后返回地址,所以重点就是两个过程,文件名的重新生成过程和url的拼装过程。由于我们没有专门的图片服务器,所以这里就只能放到自己的应用的特定文件夹中。所以特别注意的是,每次在eclipse中直接重新部署系统都会自动的覆盖掉这个文件夹,所以如果你的这个目录下有一些莫名其妙的文件夹和文件,这些文件都是eclipse工程里的,只要删除其中的再部署就可以了,原来的文件会被删除,所以只能用在测试环境。

    富文本空间完成了,可以用来在后台编辑商品信息。但是商品信息的一些选择项有一些是从产品库表中动态获取的,产品库表的设计初衷是为了能让产品的一些属性在后台动态控制,所以进入商品编辑页面的时候,这些控件的值需要去动态获取渲染,一般而言采用的是ajax的方式,这里涉及到一个问题就是多个ajax请求时间差的问题,先发出的请求可能在后面才发回,后发出的请求可能被先响应了,所以如果采用的调用相同的接口的形式,要注意在代码中控制一种序列化加载的手段,不能同时去发送请求。除非在返回值中有特定的区别,但是那样直接的后果会让返回值返回带有特定的页面值需求,耦合太大。另外一个问题就是使用dwr的回调函数简写的形式,发送了请求出去,然后回调函数采用直接简写在ajax调用方法中只是用于初始化一个类似于全局变量的值,然后下面直接用这个全局变量去渲染控件,也是会有时间差的问题。因为请求虽然发出了,但是回调尚未执行,所以下面直接用这个全局变量去渲染控件,将什么也得不到。

    后台的一些功能,本希望采用一种富客户端的形式,用js+ajax+jst+jquery来实现,这样做的一个直接的后果就是,每个菜单的响应都将是一个js函数,而不是一个连接,这样后续添加了spring security之后发现无法通过配置的方式去控制权限,所以只能在渲染菜单的时候如果用户没有权限,则响应的菜单隐藏。而这种方式并不是安全的,恶意的用户可以直接模拟发送ajax请求来做一些事情,比如给自己的账户添加权限。所以在远程调用的java方法中也是必要加入权限控制,使用了springsecurity的一个secured标签来控制调用当前代码的用户必须具有的权限。但是由于远程调用的方法可能是通用的,所以可能对于一个方法需要配置多个权限,这样带来的直接后果就是那些原本对于一个操作没有权限的用户,由于它具有另一个操作的权限,而两个操作调用的代码相同,所以这个代码会配置两个权限值,而spring security的检查是只要有一个权限匹配就通过,所以导致他也能去操作原本没有权限的操作。

    谈到权限也是花了一些时间去研究,如何将spring security整合到系统中,实现前后台不同方式的登录,将自己的过滤器加入到过滤器链中,控制不同的页面流程等,加入自己的userDetail,这些经历之后,都收获不少,觉得spring security虽然在设计上有一些硬伤,比如过滤器连的方式可能验证错误的准确消息被后续的过滤器连覆盖等问题。但是对于使用者而言,还是有很大的便利性,将开发者从繁杂的权限判断,页面控制过程中解救出来,关注于业务实现。

    到今天这个系统已经是中小规模了,3-4W行代码也是一个很难去维护记忆的事情,很多的代码自己再去看会发现已经看不太明白了,尤其是很早以前写的那些抽象的方法。

    最近完成了跟支付宝的整合,具有支付推动道支付宝,接受结果,同步数据,异步同步订单,自动过期未付款订单等功能。

    到今天,更多的是回头去关注,这样的一个设计,一个一个的功能点的设计,给后面会带来什么样的灾难,比如最开始用的抽象父类,那个抽象度很高的搜索模块等。这次迁移到ibatis,对这两个模块而言,将是改动最大的。

    而且也希望将后台富客户端的方式改掉,这个过程开发的时候很过瘾,也很痛快,但是现在想来并不成熟,在安全上有很大的问题。

    纪念这3个月数不清的熬夜到凌晨和偶尔的几个通宵。

你可能感兴趣的:(阶段性的登陆成功)