• ABP之动态WebAPI(二)


    HttpControllerDescriptor与HttpActionDescriptor

    HttpControllerDescriptor封装了某个HttpController类型的元数据,我们可以将它视为某个HttpController类型的描述对象。HttpActionDescriptor也类似。上一篇中说到AbpApiControlerAction信息分别封装于DynamicApiControllerInfoDynamicApiActionInfoAbpHttpControllerDescriptorHttpActionDescriptor有新的实现DynamicHttpControllerDescriptorDyanamicHttpActionDescriptor

    Action的执行

    Action方法的执行最终实现在HttpActionDescriptorExecuteAsync方法中。DyanamicHttpActionDescriptor也重写了ExecuteAsync,并且将Action的返回值类型定义为AjaxResponse

            public override Type ReturnType
            {
                get
                {
                    return typeof(AjaxResponse);
                }
            }
    
            public override System.Threading.Tasks.Task<object> ExecuteAsync(HttpControllerContext controllerContext, System.Collections.Generic.IDictionary<string, object> arguments, System.Threading.CancellationToken cancellationToken)
            {
                return base
                    .ExecuteAsync(controllerContext, arguments, cancellationToken)
                    .ContinueWith(task =>
                    {
                        try
                        {
                            if (task.Result == null)
                            {
                                return new AjaxResponse();
                            }
    
                            if (task.Result is AjaxResponse)
                            {
                                return task.Result;
                            }
                            
                            return new AjaxResponse(task.Result);
                        }
                        catch (AggregateException ex)
                        {
                            ex.InnerException.ReThrow();
                            throw; // The previous line will throw, but we need this to makes compiler happy
                        }
                    });
            }
    View Code

     

    IHttpControllerSelector与IHttpActionSelector

    在上一篇的开头提到了动态的WebApi的核心之一就是对原有的WebApi服务进行了替换。其中就包括IHttpControllerSelectorIHttpActionSelector,这两个接口的主要功能就是对url进行解析生成相应的HttpControllerDescriptorHttpControllerDescriptor,并传给WebApi系统,再由WebApi系统去执行Action

    在上一篇中说到AbpApiControllerDynamicApiControllerInfo缓存于DynamicApiControllerManager中,在DynamicApiControllerManager中有一DynamicApiControllers的静态IDictionary属性。

    private static readonly IDictionary<string, DynamicApiControllerInfo> DynamicApiControllers;
    

      

    Abp系统的AbpHttpControllerSelector的中,根据url的解析出相应的服务名在DynamicApiControllerManager查找出DynamicApiControllerInfo.再生成DynamicHttpControllerDescriptor返回。

            public override HttpControllerDescriptor SelectController(HttpRequestMessage request)
            {
                if (request != null)
                {
                    var routeData = request.GetRouteData();
                    if (routeData != null)
                    {
                        string serviceNameWithAction;
                        if (routeData.Values.TryGetValue("serviceNameWithAction", out serviceNameWithAction) && DynamicApiServiceNameHelper.IsValidServiceNameWithAction(serviceNameWithAction))
                        {
                            var serviceName = DynamicApiServiceNameHelper.GetServiceNameInServiceNameWithAction(serviceNameWithAction);
                            var controllerInfo = DynamicApiControllerManager.FindOrNull(serviceName);
                            if (controllerInfo != null)
                            {
                                var controllerDescriptor = new DynamicHttpControllerDescriptor(_configuration, controllerInfo.ServiceName, controllerInfo.Type, controllerInfo.Filters);
                                controllerDescriptor.Properties["__AbpDynamicApiControllerInfo"] = controllerInfo;
                                return controllerDescriptor;
                            }
                        }
                    }
                }
    
                return base.SelectController(request);
            }
    View Code

     

    DynamicApiControllerInfo中有IDictionary<string, DynamicApiActionInfo> Actions字典所以获取Action也就十分方便。

    Abp的路由

    Abp定义了自己的路由格式

        public static class DynamicApiRouteConfig
        {
            /// <summary>
            /// Registers dynamic api controllers
            /// </summary>
            public static void Register()
            {
                //Dynamic Web APIs (with area name)
                GlobalConfiguration.Configuration.Routes.MapHttpRoute(
                    name: "AbpDynamicWebApi",
                    routeTemplate: "api/services/{*serviceNameWithAction}"
                    );
            }
        }
    View Code

     

    具体的解析就是:

    Api/services/{ServicePrefix}/{ServiceName}/{Action}

    SimpleTaskSystem中一访问所有Tasksurl

    http://localhost:6247/api/services/tasksystem/task/GetTasks

    ServicePrefix:服务前缀,由开发者自己定义

    SimpleTaskSystem

        [DependsOn(typeof(AbpWebApiModule))] //We declare depended modules explicitly
        public class SimpleTaskSystemWebApiModule : AbpModule
        {
            public override void Initialize()
            {
                //This code is used to register classes to dependency injection system for this assembly using conventions.
                IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
    
                //Creating dynamic Web Api Controllers for application services.
                //Thus, 'web api layer' is created automatically by ABP.
    
                DynamicApiControllerBuilder
                    .ForAll<IApplicationService>(Assembly.GetAssembly(typeof (SimpleTaskSystemApplicationModule)), "tasksystem")
                    .Build();
            }
        }
    

      

    ServiceName:服务名,由服务接口名解析而成。具体规则在BatchApiControllerBuilder. GetConventionalServiceName

            public static string GetConventionalServiceName(Type type)
            {
                var typeName = type.Name;
    
                if (typeName.EndsWith("ApplicationService"))
                {
                    typeName = typeName.Substring(0, typeName.Length - "ApplicationService".Length);
                }
                else if (typeName.EndsWith("AppService"))
                {
                    typeName = typeName.Substring(0, typeName.Length - "AppService".Length);
                }
                else if (typeName.EndsWith("Service"))
                {
                    typeName = typeName.Substring(0, typeName.Length - "Service".Length);
                }
    
                if (typeName.Length > 1 && typeName.StartsWith("I") && char.IsUpper(typeName, 1))
                {
                    typeName = typeName.Substring(1);
                }
    
                return typeName.ToCamelCase();
            }
    View Code

     

    Action:即为方法名

    HttpVerb

    Apb定义的四种Http访问方式

        [Flags]
        public enum HttpVerb
        {
            /// <summary>
            /// GET
            /// </summary>
            Get,
    
            /// <summary>
            /// POST
            /// </summary>
            Post,
    
            /// <summary>
            /// PUT
            /// </summary>
            Put,
    
            /// <summary>
            /// DELETE
            /// </summary>
            Delete,
        }
    View Code

    原本作者是定义了HttpVerb的处理方式,即对是通过方法名进行的分析。

        /// <summary>
        /// NOTE: This is not used (as all members are private)
        /// </summary>
        internal static class DynamicApiVerbHelper
        {
            private static HttpVerb GetConventionalVerbForMethodName(string methodName)
            {
                if (methodName.StartsWith("Get"))
                {
                    return HttpVerb.Get;
                }
    
                if (methodName.StartsWith("Update") || methodName.StartsWith("Put"))
                {
                    return HttpVerb.Put;
                }
    
                if (methodName.StartsWith("Delete") || methodName.StartsWith("Remove"))
                {
                    return HttpVerb.Delete;
                }
    
                if (methodName.StartsWith("Create") || methodName.StartsWith("Post"))
                {
                    return HttpVerb.Post;
                }
    
                return GetDefaultHttpVerb();
            }
    
            private static HttpVerb GetDefaultHttpVerb()
            {
                return HttpVerb.Post;
            }
        }
    View Code

     

    但作者好像并不打算这么做,在源代码中我也没有找到别的处理方式。

  • 相关阅读:
    虚拟机搭建Hadoop集群
    多线程编程之保护性暂挂模式
    Java多线程编程之不可变对象模式
    多线程编程之两阶段终止模式
    Spring自定义标签解析与实现
    Spring Bean注册解析(二)
    苹果ios开发
    java
    layui 单选项 点击显示与隐藏
    PHP -- 七牛云 在线视频 获取某一帧作为封面图
  • 原文地址:https://www.cnblogs.com/gangtianci/p/4694628.html
Copyright © 2020-2023  润新知