zoukankan      html  css  js  c++  java
  • Web应用架构探索笔记 —— 查询

    在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()方法)->领域对象完成业务逻辑操作返回数据。

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

    注:这篇随笔只是我们在探索博客园Web应用架构过程中的笔记,并不代表这是更好更合理的方法。写出来一是为了分享,二是帮助自己更好的思考,三是记录架构演变的过程。

  • 相关阅读:
    数据库创建标量值函数
    大并发大数据量请求的处理方法
    模态对话框 bootstrap-modal.js
    创建测试表,批量插入数据的存储过程,分页存储过程
    android:强大的图片下载和缓存库Picasso
    压缩图片链接
    Css3:transform变形
    css中 padding属性的数值赋予顺序为
    Css3颜色值RGBA得表示方式
    css3 box-shadow让我们实现图层阴影效果
  • 原文地址:https://www.cnblogs.com/dudu/p/web_architecture_think_1.html
Copyright © 2011-2022 走看看