给安卓手机客户端提供数据的工作记录

一、项目背景:
  公司要开发一款安卓手机客户端程序,以实现公司目前PC端程序的功能。负责手机客户端程序开发的同事使用JAVA语言编写,若采用直接远程连接数据库,则有两个问题:一个是同事表示客户端远程连接数据库在程序中实现起来较麻烦,另一个是远程连接数据库有可能会暴露数据库连接字符串(网络通信过程中的加密方式暂时不了解)。而且公司目前没有服务器端程序,只是我负责的网站项目有IIS服务器及ASP.NET服务器端,服务器的系统是win server 2008,web服务器是IIS服务器,数据库是mssqlserver2008,这些也不太适合让同事来单独用JAVA语言实现一个服务器端程序。同时,做手机客户端的同事对服务器端程序要求很简单,只需要服务器端程序能够进行查询数据库数据操作,并且返回的数据是JSON格式字符串即可。服务器端程序不需要非数据库查询操作,那么在IIS下运行的ASP.NET也可以完全胜任这项工作。

二、项目需求:
  同事的手机客户端程序会向服务器发送请求及附带参数(也可能无参数),要求根据请求和参数来按照事先的约定返回指定数据,服务器端的程序主要就是根据请求和参数的不同,构造出不同的数据库查询语句(几乎是查询,增删改暂未涉及),查询数据库并将数据库的结果集根据约定返回指定字段的值,返回的字符串应该符合JSON格式。

三、目前已使用的技术:
  两个网站:一个是.NET2.0经典模式,另一个是.NET4.0经典模式,两个网站使用的都是Website模式,都用到了URL重写模块,并且个别页面还仍然是直接访问物理地址,甚至还有些是集成了WebForm模式的页面。

四、项目的技术选型:
  接到这项任务,我首先考虑的就是采用哪种技术方案来解决。我一直很欣赏ASP.NET中的MVC模式,也自己读了一些相关资料,并做了一些简单的小页面。最近又特别迷VS2013的ONE ASP.NET和Web API2,说句题外话,一直觉得每项任务都应该选用适合它的技术,而不应该将一项具体的任务局限在某种语言或框架下。其实说实话,这项任务在公司当前的情况下来看,最方便的方案就是在现有网站中直接创建一般处理程序(.ashx),来查询数据库并返回结果即可,这里无论采用Website模式还是WebForm模式均可。但是有新东西总想尝试一下(公司里就我对ASP.NET最了解,所以在实现方面几乎不受限制),于是雄心勃勃地决定采用Web API2。这里遇到问题了,服务器上的IIS应用程序池版本是.NET2.0和.NET4.0的,在.NET4.0下好像无法使用Web API,同时现有的两个站点里也没有路由模块,并且我也不确信在为站点添加MVC的路由模块后,会不会影响到原有的物理地址访问和URL重写模块。那么能不能用MVC模式模拟Web API呢?答案是肯定的,正常的MVC模式网站,Action返回的都是View,而这里我只需要返回String字符串即可了,而且.NET4.0是内置MVC2的。各位老师同学莫笑,虽然最新的MVC版本是5,但是我的开发环境可以是5,而服务器环境我就不太会部署配置了。因此用MVC2模拟Web API还是可行的,这里又遇到问题了,公司网站在我开发机的本地项目中是以Website模式创建的,而非WebForm或MVC,这样路由模块如何添加就成了关键,最终通过《用网站(WebSite而不是WebProject)项目构建ASP.NET MVC网站》得到了解决。技术方案确定后,发现连页面文件(如.ashz)都不用创建了,直接将类库项目生成的.dll程序集上传至站点的bin文件夹中即可。可是真心不顺利啊,上传之后在.NET4.0的经典模式下路由模块失效,而改为.NET4.0集成模式,网站原有页面还都报错,这个最后也是东翻西找地解决了。

五、项目完成过程:
  因为上一个任务跟本次任务操作的数据库表示同一个,而上一个任务采用的是WebForm模式,因此就考虑能否将这两个功能集成在一起,在数据访问层进行合并,以达到代码复用的目的。于是先设计一下整体结构,网站原项目也有类似结构,但是由多个部分拼凑且代码较混乱,同时网站使用的数据库表与这两个任务的不一样,所以就未使用网站里的三层架构项目。
  整体结构是这么规划的:
    DAL层中包含SQLHelper工具类和各表的DAL层类,并做约定,SQLHelper中只有ADO.NET和数据库连接字符串,不允许有其他的逻辑代码,只能返回ADO.NET方法返回的类型;而每一个表对应一个类,每个类中提供数据库访问的方法,只能返回DataSet、int、bool或object;各个表的DAL类中重复的代码放到CommonDAL类中。
    BLL层分项目设立,包含各表的BLL层类,并做约定,每一个项目对应一个工程,每一个表对应一个类,每个类中提供调用DAL层的方法,返回值根据项目确定,如之前的WebForm项目返回DataTable和int、bool、object,而新做的仿MVC的类库项目则返回List<T>和int、bool、object,BLL层中要将业务项目传入的参数解析并组装成DAL层所使用的参数形式;每个工程中各个表的BLL类中重复的代码放到CommonBLL类中。
    Model实体,没有考虑过EF,因为EF太重量级了,一开始想用linq操纵数据,考虑过LINQ to SQL class这个比较轻量级,根据数据库生成.dbml文件,但是后来考虑要兼容之前的那个WebForm项目,这个实体可能会导致那个项目移植和集成时的工作量的增加,于是也放弃。最终老老实实使用了普通的类,Model项目中还有一些公共的实体,如后面使用分页器时需要传多个参数,显得方法的参数列表比较长,于是就将跟分页器相关的参数定义到PagerContext这个实体类中了。
    具体业务项目也是分项目设立。
  先开始完成新任务,这里要说说如何用VS2010和类库文件将MVC的路由模块添加到Website模式中。
  根据前面提到的博客文章一步一步来(这里说到的在那篇博客中都有,并且那篇博客会更详细),首先是新建一个Website网站,这是解决方案中会增加一个文件夹,里面也有Web.config、bin之类的文件(夹),这个虽然在实际使用中用不到,但是我后来做了一个测试页面放到这里。添加Global.asax文件,再添加System.Web.Mvc 2.0.0.0版本的引用,如果你的VS是2012或2013的话,一定要注意添加的MVC版本号,我这里使用到的是2.0,添加引用后会在web.config中增加一个配置节system.web->compilation->assemblies-><add assembly="System.Web.Mvc, Version=2.0.0.0,.../>。然后再添加一个类,类名一定是以Controller结尾,这个类保存在App_Code文件夹中(如果是WebForm项目,因为该项目会生成一个统一的dll程序集,而.cs文件根本都不部署到服务器上,所以.cs文件放在何处不要紧,但Website网站的dll程序集是临时生成的,.cs文件也要上传到服务器上,所以要放到系统保护的App_Code这类文件夹下比较安全)。至于Action就是一个public的方法名,Action返回应该是View视图,但是我实际返回的是字符串,不过这里先说说返回视图的情况。在Website文件夹下新建一个Views文件夹,再用Controller的名字命名一个子文件夹,然后在这个文件夹中创建一个aspx页面,一定要记住将【将代码放在单独的文件中】选项的勾选去掉,这样添加后不生成aspx.cs文件,在@Page指令中,增加一行“Inherits="System.Web.Mvc.ViewPage"”,就可以了。如果是返回字符串,连这个文件都不需要有了,因为服务器会给客户端响应一段文本信息。
  接下来是最重要的路由模块的添加,因为没有路由,就没法实现MVC模式。先说明路由模块需要引入System.Web.Routing 4.0.0.0版,路由模块其实跟MVC模块不是一回事,甚至你也可以在WebForm项目中使用路由模块。然后在之前创建的Global.asax文件中的Application_Start方法中添加一条路由注册的语句:RouteTable.Routes.MapRoute(名字,规则,默认值),如果你没在web.config文件的system.web->pages->namespaces配置节点中添加命名空间,就要在Global.asax文件中用@Import指令添加命名空间。然后一定要在web.config文件中配置这一项:system.webServer-><modules runAllManagedModulesForAllRequests="true"/>,这样路由模块才能正式生效。最后生成一下网站,无论是返回视图还是返回字符串,在浏览器中都能看到内容。但是我并没有采用这种模式,而是采用那篇博客作者的升级模式,就是将路由注册部分提出到单独的类库文件中。将Website中的Global.asax文件删除掉,然后在业务项目(也就是Controller所在的项目)中新建一个类文件,在namespace命名空间的外面加入一行:[assembly:System.Web.PreApplicationStartMethod(typeof(该类带有命名空间的完整名称), "RegisterRouting")],将这个类改写为公共静态类,类名最好为RoutingRegister,在类中添加一个公共静态方法(不带返回值),将原先的路由注册语句放到这个方法中就OK了,让Website引用该项目即可。至此,我所需要的功能就都完成了,那篇博客文章还涉及很多其他技术,有兴趣的同学可以翻看。
  再下来就是三层的构建以及SQL语句的编写,这里我就不细说了,唯一想说明的是刚开始写了几个DAL,发现里面有大量的语句重复,于是乎提出到那个CommonBLL/DAL类的静态方法中。后来根据业务情况,需要增加几个查询方法,发现那个静态方法的代码虽然可以复用,但是个性化定义却不好实现,也不是不能实现,而是实现后,发现还不如开始就不提出到静态方法中,感觉代码量反而增加了。后来又想了想面向对象的OO理念,可是又对继承和多态的体会不是很深,所以暂时也没有优化。
  新任务完成后开始对之前那个WebForm项目进行移植,这里也不细说,只总结一点。WebForm中的页面调用方法不改动,也就是aspx.cs中调用的方法(方法名和参数列表),而新写的DAL层中的数据库访问方法也基本不改动,然后想办法将原来项目中实现数据增删改查的方法放到BLL层里实现(及实现对DAL层的调用)。这样移植后BUG比较少,而且大部分代码可以复制粘贴。
  接下来就是向网站上部署新完成的功能。这里也遇到了一个大问题,就是前面说到的在服务器.NET4.0经典模式下路由失效的问题。改用集成模式路由生效,但是网站原有页面报错,经典模式下路由失效如何解决没有找到答案,于是乎我就想办法解决集成模式报错的问题。发现原因是这样的经典模式和集成模式配置HttpHandlers模块和HttpModules模块的方式不同,经典模式在system.web-><httpHandlers>下配置<add .../>节点或<httpModules>下配置<add .../>节点,而集成模式是在system.webServer-><handlers>下配置<add .../>节点或<modules>下配置<add .../>节点。原来网站运行在经典模式下,在system.web中配置过httpHandlers和httpModules节点,换成集成模式后,这两个配置不适用与集成模式,导致站点报错,后来将这两项配置节点注释后,问题解决。之后再访问公司网站,可以正常显示页面,我的功能也能正常实现,同时网站的Url重写模块也正确运行。
  公司网站现在是Website做主体,其中混有WebForm项目,同时还有我新加入的MVC路由项目,真的是很乱。不过如果这是通过技术手段有意为之的项目融合呢?没错,那就是现在VS2013上的One ASP.NET了。这里还没有使用真正的Web API,同时WCF和WebService也没有用到,还有一个神奇的SignalR。我的理想中应该是一个服务器端支持不同的客户端类型,浏览器的B应该也属于C/S中C的一种,使不同客户端得到的数据统一,使服务器端的代码得到复用,使项目成为平台级并易于扩展。服务器端只处理数据,而把表现完全交给客户端,实现真正的界面逻辑与数据分离。

六、项目小结:
  现在手机客户端已经可以拿到自己想要的数据了,并且还可以随时为手机客户端业务需求的变化,增加或修改提供数据的方式。在手机客户端的数据自定义性,我做出这样的约定:一般情况下BLL层都会返回数据表的所有字段信息,当手机客户端只需要部分字段时,为了节省网络流量,我会给客户端响应指定的字段,这里用linq和匿名类实现,代码量很小且性能暂时在接受范围内。像这种给其他同事提供服务或接口的项目,自己应该完成一个模拟使用方的测试程序或页面,我在项目中创建一个Website网站,在里面创建一个html页面,然后用ajax请求服务器端,并将服务器端返回的字符串显示出来。最后十分感谢《用网站(WebSite而不是WebProject)项目构建ASP.NET MVC网站》的作者Ivony,学到了很多知识并且解决我的问题,如果有同学对此感兴趣,请到原文章里学习,本文抄录了一些内容,再次向原作者表示感谢!这篇文章只是用来记录工作中解决问题的一些方法或思路,因此没有具体的代码,并且也不保证所有的知识点都是正确,欢迎各位老师和同学批评和指正!

posted @ 2014-03-27 14:42  守护晴天  阅读(339)  评论(0编辑  收藏  举报