Mvc4+autofac+jggrid+nhibernate(1) 架构介绍

写这篇博文只是介绍下思路,主要目的是为了找工作,所以细节不是很详细,请大家勿喷

第一章架构介绍

1,架构介绍

先看个整体图

Infrastructure解决方案中使用的基础工具。

Application站点应用层,组织业务逻辑管理业务事务的地方。比如登录,菜单等。Models是用来放UI中所使用的ViewModel即DTO类,以及利用value.injecter进行实体和viewmodel转换的映射类。

Core 核心层,实现ORM的实体类和映射,以及仓储,业务服务类等。

Demo.site.web 即web层。在这里使用了jqgrid表格UI,bootstrap,和jquery验证等增加用户体验的富客户端技术。

2,采用面向接口开发模式,

面向接口开发:好处不用说了,最大的理由,方便解耦。仓储和业务服务层都采用接口设计,有个很大的不便,每个类都要搞个接口。有点小麻烦。下面详细说下这种设计。

在基类NHibernateRepositoryBase中设置共用的增删改(CUD)操作,采用泛型设计,这样更加通用,查询先不设置,因为这里又牵涉到一个知识点。等下再说。下面是基类代码。

//-----------------------------------------------------------------------
// <copyright file="EFRepositoryBase.cs" company="Company">
// Copyright (C) Company. All Rights Reserved.
// </copyright>
// <author></author>
// <summary></summary>
//-----------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using Component.Tools;
using NHibernate;
namespace Component.Data
{

        /// <summary>
        ///     NH仓储操作基类
        /// </summary>
        /// <typeparam name="TEntity">动态实体类型</typeparam>
        /// <typeparam name="TKey">实体主键类型</typeparam>
    public class NHibernateRepositoryBase<TEntity, TKey> : IRepository<TEntity, TKey> where TEntity : Entity
        {
            #region 属性
        /// <summary>
        /// 作为基类,若被继承则必须有无参构造函数,否则报错。或者在继承类中显示调用 有参构造。或者用属性来ioc则不需显示定义无参构造函数。
        /// </summary>
        public NHibernateRepositoryBase() { }

            /// <summary>
            ///     获取 仓储上下文的实例
            /// </summary>

        private IUnitOfWorkContext NHContext;
        public NHibernateRepositoryBase(IUnitOfWorkContext UnitOfWork)
            {
                NHContext = UnitOfWork;

            }
        public virtual ISession Session
        {
            get { return NHContext.Session; }
        }

            /// <summary>
            ///     获取 当前实体的查询数据集
            /// </summary>
            public virtual IQueryable<TEntity> Entities
            {
                get { return NHContext.Set<TEntity, TKey>(); }
            }

            #endregion

            #region 公共方法

            /// <summary>
            ///     插入实体记录
            /// </summary>
            /// <param name="entity"> 实体对象 </param>
            /// <param name="isSave"> 是否执行保存 </param>
            /// <returns> 操作影响的行数 </returns>
            public virtual object Insert(TEntity entity, bool isSave = true)
            {
                PublicHelper.CheckArgument(entity, "entity");
                object obj = NHContext.RegisterNew<TEntity, TKey>(entity);
                if (isSave)
                     NHContext.Commit();
                return obj;
            }

            /// <summary>
            ///     批量插入实体记录集合
            /// </summary>
            /// <param name="entities"> 实体记录集合 </param>
            /// <param name="isSave"> 是否执行保存 </param>
            /// <returns> 操作影响的行数 </returns>
            public virtual void Insert(IEnumerable<TEntity> entities, bool IsUsedStatelessSession)
            {
                PublicHelper.CheckArgument(entities, "entities");
                NHContext.RegisterNew<TEntity, TKey>(entities,IsUsedStatelessSession);

            }

            /// <summary>
            ///     删除指定编号的记录
            /// </summary>
            /// <param name="id"> 实体记录编号 </param>
            /// <param name="isSave"> 是否执行保存 </param>
            /// <returns> 操作影响的行数 </returns>
            public virtual int Delete(TKey id, bool isSave = true)
            {
                int isTrue = 0;
                PublicHelper.CheckArgument(id, "id");
                try {
                TEntity entity = NHContext.Set<TEntity, TKey>().Single<TEntity>(t=>t.Id.ToString()==id.ToString());
                if (entity != null)
                     isTrue = Delete(entity, isSave);

                }
                catch(Exception e)
                {
                    PublicHelper.ThrowDataAccessException(e.Message, e);

                }
                return isTrue;
            }
        /// <summary>
        ///
        /// </summary>
        /// <param name="ids"></param>
        /// <param name="IsUsedStatelessSession">不可以级联删除</param>
        /// <returns></returns>
            public int Delete(string ids, bool IsUsedStatelessSession)
            {
                PublicHelper.CheckArgument(ids, "ids");
                return NHContext.RegisterIdsDeleted<TEntity, TKey>(ids, IsUsedStatelessSession);            

            }
            /// <summary>
            ///     删除实体记录
            /// </summary>
            /// <param name="entity"> 实体对象 </param>
            /// <param name="isSave"> 是否执行保存 </param>
            /// <returns> 操作影响的行数 </returns>
            public virtual int Delete(TEntity entity, bool isSave = true)
            {
                PublicHelper.CheckArgument(entity, "entity");
                NHContext.RegisterDeleted<TEntity, TKey>(entity);
              if(isSave)
                  return NHContext.Commit();
              else return 0;
            }

            /// <summary>
            ///     删除实体记录集合
            /// </summary>
            /// <param name="entities"> 实体记录集合 </param>
            /// <param name="isSave"> 是否执行保存 </param>
            /// <returns> 操作影响的行数 </returns>
            public virtual void Delete(IEnumerable<TEntity> entities, bool IsUsedStatelessSession)
            {
                PublicHelper.CheckArgument(entities, "entities");
                NHContext.RegisterDeleted<TEntity, TKey>(entities, IsUsedStatelessSession);                

            }

            /// <summary>
            ///     删除所有符合特定表达式的数据
            /// </summary>
            /// <param name="predicate"> 查询条件谓语表达式 </param>
            /// <param name="isSave"> 是否执行保存 </param>
            /// <returns> 操作影响的行数 </returns>
            public virtual int Delete(Expression<Func<TEntity, bool>> predicate, bool IsUsedStatelessSession)
            {
                PublicHelper.CheckArgument(predicate, "predicate");
                List<TEntity> entities = NHContext.Set<TEntity, TKey>().Where(predicate).ToList();
                if (entities.Count > 0)
                {
                    Delete(entities, IsUsedStatelessSession);
                    return 1;
                }
                else return 0;
            }

            /// <summary>
            ///     更新实体记录
            /// </summary>
            /// <param name="entity"> 实体对象 </param>
            /// <param name="isSave"> 是否执行保存 </param>
            /// <returns> 操作影响的行数 </returns>
            public virtual int Update(TEntity entity, bool isSave = true)
            {
                PublicHelper.CheckArgument(entity, "entity");
                NHContext.RegisterModified<TEntity, TKey>(entity);
                if (isSave)
                    return NHContext.Commit();
                else return 0;
            }

            /// <summary>
            /// 使用附带新值的实体信息更新指定实体属性的值
            /// </summary>
            /// <param name="propertyExpression">属性表达式</param>
            /// <param name="isSave">是否执行保存</param>
            /// <param name="entity">附带新值的实体信息,必须包含主键</param>
            /// <returns>操作影响的行数</returns>
            public void Update(IEnumerable<TEntity> entities, bool IsUsedStatelessSession)
            {

                PublicHelper.CheckArgument(entities, "entities");
                NHContext.RegisterModified<TEntity, TKey>(entities, IsUsedStatelessSession);

            }
            /// <summary>
            ///使用session时用和用linq查询集合时用
            /// </summary>
            /// <param name="args">0为是否用session,1为session对象,剩下的是查询参数</param>
            /// <returns></returns>
            public IQueryable<TEntity> FindBySpecification(Specification<TEntity>[] specifications, params object[] args)
            {
                bool isSuccess = false;
                IQueryable<TEntity> querys;
                if (specifications == null || specifications.Any(s => s == null))
                    throw new ArgumentNullException("specifications");
                if (args.Count()!=0&&bool.TryParse(args[0].ToString(), out isSuccess))
                {
                    args[1] = Session;
                    querys = specifications[0].SatisfyingElementsFrom(args);

                }

                else{
                    querys = specifications.Aggregate(Entities, (current, specification) => specification.SatisfyingElementsFrom(current, args));
                }
                return querys;
            }
            #endregion
            /// <summary>
            /// 用linq查询单个实体时用,注意返回集合实体的重载
            /// </summary>
            /// <param name="candidates"></param>
            /// <param name="args"></param>
            /// <returns></returns>

            public TEntity FindBySpecification(Specification<TEntity> specification,params object[] args)
            {
                if (specification == null)
                    throw new ArgumentNullException("specification");

                return specification.SatisfyingElementsFrom(Entities.AsEnumerable(), args);
            }
        }

}

有了基类NHibernateRepositoryBase 就可以设置储了。所有的仓储都实现接口,每个接口继承基类NHibernateRepositoryBase 的接口,这样如果需求有所变化只需要在仓储接口上加上方法即可。如图所示

业务层同样如此,设计一个业务基类,然后如上所示继承即可。在Demo.site是实现视图逻辑的地方,调用业务层的业务类实现如登录等业务逻辑。然后在Controller中引用接口。进行调用。非常方便。如需修改只需找到相应的接口和实现类即可,其他地方不用修改,从而实现了一定程度上解耦的目的。

上面说了,查询还没有介绍,我在这架构中,把查询放在了业务层方面。利用规约模式,资料在这里http://www.cnblogs.com/daxnet/archive/2010/07/19/1780764.html,仓储基类中只需放置一个调用函数即可。如图。

specification.SatisfyingElementsFrom 即是利用规约调用查询类的代码。规约类即一个查询设置一个类。这样做到了解耦。维护方便,但会出现大量的这种类,使项目臃肿,解决方法上面的连接已经给出。

利用规约和延迟加载将查询在业务类中实现,可以按需查询,不必像以前那样,把所有的公共查询如加载所有数据load,getbyname等定义都放在基类中,如果没有用到,就会使代码臃肿,还有一个不便就是在基类中执行查询再把结果传递到业务层,会把所有结果都加载到内存中,这会大大降低查询效率,解决方案就是利用廷迟加载,传递IQueryable<T>泛型实体集或session类到业务层,进行按需查询,这样就可避免上述情况。

在这个架构中我设计了根据业务层需要,把IQueryable<T>或session传到规约类中进行查询。简单查询可以用Iqueryable复杂一些的用session,如下图

业务层根据args[]第一个参数来决定是否传递session

代码如下

/// <summary>
            ///使用session时用和用linq查询集合时用
            /// </summary>
            /// <param name="args">0为是否用session,1为session对象,剩下的是查询参数</param>
            /// <returns></returns>
            public IQueryable<TEntity> FindBySpecification(Specification<TEntity>[] specifications, params object[] args)
            {
                bool isSuccess = false;
                IQueryable<TEntity> querys;
                if (specifications == null || specifications.Any(s => s == null))
                    throw new ArgumentNullException("specifications");
                if (args.Count()!=0&&bool.TryParse(args[0].ToString(), out isSuccess))
                {//使用session查询
                    args[1] = Session;
                    querys = specifications[0].SatisfyingElementsFrom(args);

                }

                else{//使用linq查询
                    querys = specifications.Aggregate(Entities, (current, specification) => specification.SatisfyingElementsFrom(current, args));
                }
                return querys;
            }

然后在规约类中进行查询即可。重写specification基类方法即可,代码如下。

using System.Collections.Generic;
using System.Linq;
using NHibernate;
namespace Component.Data
{
    public class Specification<T> where T : Entity
    {
               public ISession _session{get;set;}

       /// <summary>
       ///使用session时用
       /// </summary>
       /// <param name="args">0为是否用session,1为session对象,剩下的是查询参数</param>
       /// <returns></returns>
        public virtual IQueryable<T> SatisfyingElementsFrom(params object[] args)
        {
            return null;

        }

        /// <summary>
        /// 用linq查询集合时用
        /// </summary>
        /// <param name="candidates"></param>
        /// <param name="args"></param>
        /// <returns></returns>       

        public virtual IQueryable<T> SatisfyingElementsFrom(IQueryable<T> candidates, params object[] args)
        {
            return null;
        }
        /// <summary>
        /// 用linq查询单个实体时用
        /// </summary>
        /// <param name="candidates"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        public virtual T SatisfyingElementsFrom(IEnumerable<T> candidates, params object[] args)
        {
            return candidates.Where<T>(t => t.Id.ToString() == args[0].ToString()).FirstOrDefault();
        }
     /// <summary>
        ///     id值取回记录
        /// </summary>
        /// <param name="args[0]">id值</param>
        /// <returns>根据id返回的实体</returns>
        //public TEntity GetElementsById<TEntity>(IQueryable<TEntity> candidates, params object[] args) where TEntity : Entity
        //{
        //    PublicHelper.CheckArgument(args, "args");

        //    return candidates.Single<TEntity>(t => t.Id.ToString() == args[0].ToString());
        //}

    }
}

3,领域驱动(DDD)

这是一个很大的话题,有兴趣的可以看这里。http://www.cnblogs.com/xishuai/p/ddd-entity-value-object-follow-up.html。。在这个架构中介绍下DDD驱动中怎样体现聚合和聚合根的实现。先看下实体关系类图。

userAccount和roleUserAccount、Role这三个实体是一个聚合,通过聚合根进行数据操作。

Capability,Menu,RoleCapability,和role,可以划为一个聚合,role划为聚合根,通过它进行数据操作

Capability,Menu,可以分别做为他们聚合的聚合根,进行数据操作。

至于怎样实现数据操作的,当然要靠orm了。因为这里只是为了展现我所会的技术,找工作用,具体详细的DDD可以拜读博客园中一些大牛的文章。

4,nhibernate(orm)

现在大多数公司都使用了EF code first,我学习Nhibernate不知能不能派上用场很是忐忑。nh相信大家已经很熟悉了,不多介绍再这里说一下,他的映射方式

使用fluent nhibernate来进行映射,使用它完全不再用xml了,有智能提示,不再担心手美女飘过时手抖出错的问题了。资料在这里,http://www.fluentnhibernate.org/当然园子里也有中文文档,不过还是原文来的详细些。这里用automapping和fluentmapping结合使用,大大减少编码量,需要特别处理的,如对某个类的cascade级别的修改,id命名策略的处理等,可以通过实现conventions接口来处理。非常方便。看代码

using NHibernate.Cfg;
using FluentNHibernate.Conventions;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using FluentNHibernate.Automapping;
using Demo.Core.NHFluentConfiguring.Conventions;
using FluentNHibernate.Conventions.Helpers;
using System.Reflection;
using System.Data;
using Demo.Core.Models;

namespace Demo.Core.NHFluentConfiguring
{
    public enum CurrentSessionContextClass
    {
        managed_web,
        call,
        thread_static,
        web
    }
    public static class FluentNhCfg
    {

        public static Configuration GetNHConfiguration()
        {
            //也可以用ioc注入
            var cfg = new AutoMappingConfig();
            var model = AutoMap.Assembly(Assembly.Load("Demo.Core.Models"))
                .Where(t => t.Namespace == "Demo.Core.Models" && t.BaseType.Name == "Entity" && t.Name.IsNotAny(new[] { "RoleCapability", "RoleUserAccount" }))

            .IgnoreBase<Component.Data.Entity>()
          .Override<Menu>(map =>map.IgnoreProperty(ig => ig.Children))

             .Conventions.Add(new EnumConvention(),
             new InverseConvention(),
             new HiloIdConvention(),
              DefaultCascade.All(),
              new MenuCascadeCapabilityConvention(),
              new MenuCascadeConvention(),
            DefaultLazy.Always(),
            DynamicInsert.AlwaysTrue(),
            DynamicUpdate.AlwaysTrue(),
            OptimisticLock.Is(x => x.Dirty())
           );

            // Cache.Is(x => x.ReadWrite())

            var nhConfig = Fluently.Configure()
      .Database(MsSqlConfiguration.MsSql2008
      .ConnectionString("Data Source=.;Initial Catalog=FrameworkShan;Integrated Security=True")
                //fnh api中没有的属性可以用raw来设置nh中的属性。
                //•validate:在程序启动时,检查持久化类与映射文件的改变。
                //  •none:不产生任何操作。
               //•create-drop:在程序启动时,自动生成数据库架构并导入到数据库中,在程序关闭时,删除数据库架构,常用在测试中。
                //update 加载hibernate自动更新数据库结构
      .Raw("hbm2ddl.auto", "update")
      .ShowSql()

      .IsolationLevel(IsolationLevel.ReadCommitted)
      .AdoNetBatchSize(20)
      )
      //.CurrentSessionContext("web")在web项目和test项目中分别各自设置

      .Mappings(mappings =>
      {

          mappings.FluentMappings
              .AddFromAssemblyOf<Demo.Core.Models.Mapping.RoleCapabilityMapping>()
              .Conventions.Add(new EnumConvention())
               .ExportTo(@"C:\Users\qishan\Desktop\fnh");
          mappings.AutoMappings.Add(model)
                .ExportTo(@"C:\Users\qishan\Desktop\fnh");
          //Conventions若放在fluentMappings中各设定将不起作用。只有放在autoMapping中才起作用
          //在此设置的默认conventions将被在Mapping文件中设置的属性替换。

      })

      .BuildConfiguration();
            //string[] nhd = nhConfig.GenerateSchemaCreationScript(new NHibernate.Dialect.MsSql2008Dialect());
            return nhConfig;

        }
    }
}

5,控制反转(ioc)

在选择ioc时很纠结是用spring,ninject,还是其他,最后想想还是以效率为优吧,就选了这个autofac,官方推荐是以构造函数注入的,不过也支持属性注入

对很多功能都进行了集成,比如,对controller,modelbinder等直接在global.cs中一行代码就搞定,还有注入模块支持,一些功能所需要的注入可以写在一个模块中统一注入,这个功能很优雅。还有聚合服务注入,这个在controller中最好用,把controller中所用的服处,放在一个聚合接口中,调用时直接调用接口,就可以调用服务,官方文档这里http://autofac.readthedocs.org/en/latest/,使用方式,看下代码就好了。

  protected void Application_Start()
        {
            HibernatingRhinos.Profiler.Appender.NHibernate.NHibernateProfiler.Initialize();
            var builder = new ContainerBuilder();

            builder.RegisterModelBinders(Assembly.GetExecutingAssembly());

            builder.RegisterModelBinderProvider();

            builder.RegisterControllers(Assembly.GetExecutingAssembly()).PropertiesAutowired();

            //To make use of property injection for your filter attributes
            builder.RegisterFilterProvider();

            builder.RegisterModule<AutofacWebTypesModule>();

            builder.RegisterModule<NHibernateModule>();

            // builder.RegisterModule<ControllersModule>();
            builder.RegisterAssemblyTypes(Assembly.GetAssembly(typeof(RoleRepository)))
                .Where(t => t.Name.EndsWith("Repository"))

                .AsImplementedInterfaces();
            builder.RegisterAssemblyTypes(Assembly.GetAssembly(typeof(UserAccountMapper)))
                 .Where(t => t.Name.EndsWith("Mapper"))

                .AsSelf();

            builder.RegisterAssemblyTypes(Assembly.GetAssembly(typeof(RoleService)))
                 .Where(t => t.Name.EndsWith("Service"))

                 .AsImplementedInterfaces();

            builder.RegisterAssemblyTypes(Assembly.GetAssembly(typeof(DataPagingViewService)))
                  .Where(t => t.Name.EndsWith("ViewService"))
                  .AsImplementedInterfaces();

            builder.RegisterType<ExtensibleActionInvoker>().As<IActionInvoker>().InstancePerRequest();

           IContainer Container = builder.Build();
           IoC.Container = new AutofacDependencyResolver(Container);
            DependencyResolver.SetResolver(IoC.Container);

            AreaRegistration.RegisterAllAreas();

            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            ValueProviderFactories.Factories.Insert(0, new JsonNetValueProviderFactory());
            ModelBinders.Binders.Add(typeof(Component.Data.Entity), new JsonNetModelBinder());
            // Component.Data.Entity
        }

这里注意 IoC.Container = new AutofacDependencyResolver(Container);是使用依赖解析器注入的,不是用工厂模式。当业务需要使用controller工厂时在返回controller实例方法中要这样调用:定义一个ioc静态类

using System;

using Autofac;
using Autofac.Integration.Mvc;
namespace Component.Tools
{
    public static class IoC
    {

        public static AutofacDependencyResolver Container
       {
           get;set;

       }

        public static object Resolve(Type type)
        {
            return Container.GetService(type);
        }
    }
}

在global.cs中设置Container属性,然后在工厂方法里调用。IoC.Resolve(controllerType)来得到实例。

好了,架构这节先说到这里吧

时间: 2024-11-07 18:00:46

Mvc4+autofac+jggrid+nhibernate(1) 架构介绍的相关文章

Mvc4+autofac+jggrid+nhibernate(2)权限管理

写这篇博文只是介绍下思路,主要目的是为了找工作,所以细节不是很详细,请大家勿喷. 不说废话了先上图. 上面是表之间关系.字段没有写完全,只写了重要的项目中要用到的字段 UserAccount表用户表,保存用户信息, Role表很重要,做为聚合根来使用,其他与之关联的表,可以通过它来实现,更新,插入,查询操作. RoleUserAccount多对多关系的关联表. Menu菜单表,用来生成 树形菜单.他它的字段内容可以根据你使用的树形菜单UI来设计. Capalibity权限表,一个菜单对应一个权限

Apache Shiro 使用手册(一)Shiro架构介绍

一.什么是Shiro Apache Shiro是一个强大易用的Java安全框架,提供了认证.授权.加密和会话管理等功能: 认证 - 用户身份识别,常被称为用户"登录": 授权 - 访问控制: 密码加密 - 保护或隐藏数据防止被偷窥: 会话管理 - 每用户相关的时间敏感的状态. 对于任何一个应用程序,Shiro都可以提供全面的安全管理服务.并且相对于其他安全框架,Shiro要简单的多. 二.Shiro的架构介绍 首先,来了解一下Shiro的三个核心组件:Subject. Security

GlusterFS架构介绍及运维说明

官方网站:http://www.gluster.org/ 下载地址:http://download.gluster.org/pub/gluster/glusterfs/ GlusterFS架构介绍 一.GlusterFS 外部架构 GlusterFS总体架构与组成部分如图2所示,它主要由存储服务器(BrickServer).客户端以及NFS/Samba 存储网关组成.不难发现,GlusterFS 架构中没有元数据服务器组件,这是其最大的设计这点,对于提升整个系统的性能.可靠性和稳定性都有着决定性

Kafka剖析:Kafka背景及架构介绍

<Kafka剖析:Kafka背景及架构介绍> <Kafka设计解析:Kafka High Availability(上)> <Kafka设计解析:Kafka High Availability (下)> <Kafka设计解析:Replication工具> <Kafka设计解析:Kafka Consumer解析> Kafka是由LinkedIn开发的一个分布式的消息系统,使用Scala编写,它以可水平扩展和高吞吐率而被广泛使用.目前越来越多的开源分

IOS面向协议的MVVM架构介绍(来着网络的链接)

https://academy.realm.io/cn/posts/doios-natasha-murashev-protocol-oriented-mvvm/   面向协议的 MVVM 架构介绍 http://www.cocoachina.com/ios/20160108/14911.html    猿题库 iOS 客户端架构设计

0809LNMP架构介绍

12.1 LNMP架构介绍 LNMP代表的就是:Linux系统下Nginx+MySQL+PHP这种网站服务器架构 PHP是以fastcgi的方式结合Nginx的,可以理解为Nginx代理了PHP的fastcgi和LAMP不同的是,LNMP中提供web服务的是Nginx 在LNMP架构中PHP是作为一个独立的服务存在的,这个服务叫做php-fpm Nginx直接处理静态请求(支持的并发更高,速度比Apache快),动态请求转发给php-fpm处理 12.2 MySQL安装 MySQL的安装没有变化

大型网站技术架构介绍--squid

一.大型网站技术架构介绍 1.pv高  ip高 并发量 2.大型网站架构重点 1. 高性能:响应时间,TPS,系统性能计数器.缓存,消息队列等. 高可用性High Availability   99.99% 7*24 2.衡量标准:假设环境中一台或者多台服务器宕机,服务是否依然可用.解决关键办法:冗余.资源定位,健康检查.负载均衡,关键服务器冗余:web DB ,及时有效的监控和报警 3.高伸缩性[高可维护性] 是否可以用多台服务器构建集群,是否容易向集群添加新的服务器,新服务是否可提供相同的服

beego的MVC架构介绍

beego 的 MVC 架构介绍 beego 是一个典型的 MVC 框架,它的整个执行逻辑如下图所示: 通过文字来描述如下: 在监听的端口接收数据,默认监听在 8080 端口. 用户请求到达 8080 端口之后进入 beego 的处理逻辑. 初始化 Context 对象,根据请求判断是否为 WebSocket 请求,如果是的话设置 Input,同时判断请求的方法是否在标准请求方法中(“get“”post“”put“”delete“”patch“”options“”head“),防止用户的恶意伪造

三层架构介绍

对比以上两图,我们可以看出: 1)数据库好比猪圈 ,所有的猪有序地按区域或编号,存放在不同的猪栏里. 2)DAL 好比是屠宰场 ,把猪从猪圈取出来进行(处理)屠杀,按要求取出相应的部位(字段),或者进行归类整理(统计),形成整箱的猪肉(数据集),传送给食品加工厂( BLL ).本来这里都是同一伙人既管抓猪,又管杀猪的,后来觉得效率太低了,就让一部分人出来专管抓猪了( DBUtility ),根据要求来抓取指定的猪. 3)BLL 好比食品加工厂 ,将猪肉深加工成各种可以食用的食品(业务处理). 4