略微加速

略速 - 互联网笔记

Web应用架构分析之查询传递

2016-02-23 leiting (2782阅读)

标签 架构设计

http://developer.51cto.com/art/201102/244444.htm

在Web应用开发中,最常见也容易变化的一种需求是根据不同的查询条件获取数据列表。如何传递查询条件将影响程序应对需求变化的能力,一定要在架构中重点考虑。


开始时我们使用一堆参数传递查询条件,比如:


List<SiteMsg> GetMsgList(int pageIndex, int pageSize, int RecipientId); 

结果,每个不同的查询都要写一个接口,产生了一堆接口;查询条件改变,接口也随之要改。写程序最痛苦的事莫过于接口的频繁变化。


后来使用查询对像,比如:


List<SiteMsg> GetMsgList(SiteMsgQuery msgQuery); 

这样,查询条件改变时,只需修改SiteMsgQuery的定义,接口保持不变。采用这个方法后,写代码比之前少了很多痛苦。


但使用这个方法有个地方不爽,完成一次查询需要进行两次实例化,一次是查询对象SiteMsgQuery的实例化,一次是领域对象SiteMsgManager(负责业务逻辑)的实例化。在博客园程序架构中,查询对象的实例化是在表现层完成的,如果是ajax调用,json会自动反序列为查询对象;领域对象的实例化在服务层完成。


为了让代码写的更爽一些,我们又进行了尝试,取消查询对象SiteMsgQuery,将它的属性放到领域对象中。这样减少了一次实例化,只需一次,如果是ajax调用,可以实现服务器端“零实例化”。


下面看一下代码示例:


领域模型的定义:


[DataContract]  

public class SiteMsgManager  

{  

public SiteMsgManager()  

{  

}  

 

#region Properies  

 

[DataMember]  

public int PageIndex { get; set; }  

 

[DataMember]  

public int PageSize { get; set; }  

 

[DataMember]  

public int RecipientId { get; set; }  

 

public List<SiteMsg> List { get; set; }  

 

#endregion  

 

public void GetList()  

{  

    using (SpaceObjectContext context = new SpaceObjectContext())  

    {  

        this.List = context.SiteMsgs  

            .Where(msg => msg.RecipientSpaceUserId == this.RecipientId)  

            .OrderByDescending(msg => msg.id)  

            .Skip((PageIndex - 1) * PageSize)  

            .Take(this.PageSize)  

            .ToList();  

    }             

服务实现类(也是WCF的服务实现):


public class MsgService : IMsgService  

{  

    public List<SiteMsg> GetMsgList(SiteMsgManager siteMsgManager)  

    {  

        siteMsgManager.GetList();  

        return siteMsgManager.List;  

    }  

UI层调用代码(WCF调用,ASP.NET MVC控制器):


public class MsgController : Controller  

{  

    //ajax调用  

    [HttpPost]      

    public ActionResult List(SiteMsgManager msgManager)  

    {  

        return View("MsgList", GetInboxMsgList(msgManager));  

    }  

 

    public ActionResult Inbox()  

    {  

        SiteMsgManager msgManager = new SiteMsgManager()  

        {  

            PageIndex = 1,  

            PageSize = 30 

        };          

        return View("Inbox", GetInboxMsgList(msgManager));  

    }  

 

    private List<SiteMsg> GetInboxMsgList(SiteMsgManager msgManager)  

    {  

        int spaceUserId = Util.GetCurrentUser

(System.Web.HttpContext.Current).SpaceUserID;  

        msgManager.RecipientId = spaceUserId;  

        MsgServiceClient client = new MsgServiceClient();  

        List<SiteMsg> siteMsgList = client.GetMsgList(msgManager).ToList();  

        try { client.Close(); }  

        catch { client.Abort(); }  

        return siteMsgList;  

    }  

看看上面供ajax调用的List方法,不需要进行SiteMsgManager的实例化,系统根据ajax客户端传递过来的json参数自动反序列化生成SiteMsgManager对象。


再来看看ajax客户端代码:


function GetMsgList(pageIndex, pageSize) {  

    var msgManager = {}  

    msgManager.PageIndex = pageIndex;  

    msgManager.PageSize = pageSize;  

 

    $.ajaxSettings.dataType = 'plain/text';     

    $.ajaxSettings.url = '/msg/list';  

    $.ajaxSettings.data = '{"msgManager":' + JSON.stringify(msgManager) + '}';  

    $.ajaxSettings.success = function (data) {  

        $("#msg_list").html(data);  

    };  

    $.ajax();  

js传递的也是一个对像。


整个ajax调用的流程是这样的:js对象(msgManager)->json->MsgController(MVC控制器)->代理领域对象SiteMsgManager(WCF客户端代理类的实例)->WCF服务接口->WCF服务实现(自动通过反序列化生成领域对象SiteMsgManager,并调用GetList()方法)->领域对象完成业务逻辑操作返回数据。


采用这种方法,感觉写代码比以前更享受了。我们在实际开发中也开始使用这种架构,并根据实际使用情况进一步改进。


北京半月雨文化科技有限公司.版权所有 京ICP备12026184号-3