Anno微服务引擎与传统应用相融合
1、Anno是什么?
Anno是一个微服务引擎。在此之前我们通过 Viper项目对Anno有一个基本的认识,并且Viper也受到的很多朋友的喜欢,截止发稿前Viper在GitHub收获了300多个星。并且Anno也在昨天(2020年11月24日)开源。今天我们就聊一聊Anno如何与传统的项目相结合。
github :https://github.com/duyanming/Anno.Core
gitee :https://gitee.com/duyanming/anno.core
体验地址:http://140.143.207.244/Home/Login
2、Anno和传统项目相结合
我们新建一个asp.net framework WebApi 项目。然后我们通过客户端代理(Install-Package Anno.Rpc.Client.DynamicProxy)生成服务接口代理类,并注入到Autofac容器中去。服务提供方可以是.netcore服务、.netframework服务、java服务以及其他语言提供的服务(期待大佬的加入扩展出更多)。
Demo地址:https://github.com/duyanming/Viper/tree/master/Samples
以下Demo我们用.netcore提供服务。
创建一个传统的ASP.NET WEB API项目,结构如下:
第一步 引入Nuget包 :
Install-Package Anno.Rpc.Client.DynamicProxy -Version 1.0.2.8
Install-Package Autofac.WebApi2 -Version 4.3.1
第二步:
新增文件:IocManager.cs
1 public static class IocManager 2 { 3 public static IContainer IoContainer; 4 private static readonly ContainerBuilder Builder = new ContainerBuilder(); 5 6 public static ContainerBuilder GetContainerBuilder() 7 { 8 return Builder; 9 } 10 11 public static void Build(params Assembly[] assemblies) 12 { 13 if (assemblies != null) 14 { 15 assemblies.ToList().ForEach(assembly => 16 { 17 assembly.GetTypes().Where(x => x.GetTypeInfo().IsClass && !x.GetTypeInfo().IsAbstract && !x.GetTypeInfo().IsInterface).ToList().ForEach( 18 t => 19 { 20 var interfaces = t.GetInterfaces(); 21 if (interfaces.Length <= 0) 22 { 23 Builder.RegisterType(t); 24 } 25 else 26 { 27 Builder.RegisterType(t).As(t.GetInterfaces()); 28 } 29 }); 30 }); 31 32 } 33 IoContainer = Builder.Build(); 34 } 35 }
新增文件:AutoFacConfig.cs
1 public class AutoFacConfig 2 { 3 public static void Register() 4 { 5 var builder = IocManager.GetContainerBuilder(); 6 var config = GlobalConfiguration.Configuration; 7 8 builder.RegisterApiControllers(Assembly.GetCallingAssembly()) 9 .PropertiesAutowired(); 10 builder.RegisterWebApiFilterProvider(config); 11 builder.RegisterWebApiModelBinderProvider(); 12 /* 13 * Anno服务接口通过代理注册到IOC容器中去 14 */ 15 builder.RegisterInstance<IHelloWorldViperService>(AnnoProxyBuilder.GetService<IHelloWorldViperService>()); 16 17 IocManager.Build(typeof(IocManager).Assembly); 18 config.DependencyResolver = new AutofacWebApiDependencyResolver(IocManager.IoContainer); 19 20 21 } 22 }
修改文件:WebApiConfig.cs
1 public static class WebApiConfig 2 { 3 public static void Register(HttpConfiguration config) 4 { 5 //1、将默认的xml格式化程序清除 6 GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear(); 7 8 // Web API 配置和服务 9 10 // Web API 路由 11 config.MapHttpAttributeRoutes(); 12 13 config.Routes.MapHttpRoute( 14 name: "DefaultApi", 15 routeTemplate: "api/{controller}/{id}", 16 defaults: new { id = RouteParameter.Optional } 17 ); 18 config.Formatters.JsonFormatter.SerializerSettings.DateFormatString = "MM/dd/yyy HH:mm:ss"; 19 } 20 }
修改文件:Global.asax
1 using Anno.Rpc.Client; 2 public class WebApiApplication : System.Web.HttpApplication 3 { 4 protected void Application_Start() 5 { 6 /* 7 * 配置注册中心地址 8 * 客户端名称:MvcCallAnno 9 * 注册中心IP:127.0.0.1 10 * 注册中心端口:7010 11 * 调用链追踪:false(true开启,false关闭) 12 */ 13 DefaultConfigManager.SetDefaultConfiguration("MvcCallAnno", "127.0.0.1", 7010, true); 14 /* 15 * Autofac Ioc 初始化 16 */ 17 AutoFacConfig.Register(); 18 GlobalConfiguration.Configure(WebApiConfig.Register); 19 } 20 }
增加服务接口:IHelloWorldViperService.cs
1 namespace MvcCallAnno.Service 2 { 3 using Anno.Rpc.Client.DynamicProxy; 4 5 /// <summary> 6 /// 对应Anno.Plugs.HelloWorldService 插件的 HelloWorldViperModule 模块 7 /// 接口名称和接口方法和 AnnoService端的 名称不一样的时候使用AnnoProxy 指定别名 8 /// </summary> 9 [AnnoProxy(Channel = "Anno.Plugs.HelloWorld", Router = "HelloWorldViper")] 10 public interface IHelloWorldViperService 11 { 12 /// <summary> 13 /// 名称不一致 14 /// </summary> 15 /// <param name="name"></param> 16 /// <param name="age"></param> 17 /// <returns></returns> 18 [AnnoProxy(Method = "SayHello")] 19 dynamic SayHello(string name, int age); 20 /// <summary> 21 /// 名称一致 22 /// </summary> 23 /// <param name="x"></param> 24 /// <param name="y"></param> 25 /// <returns></returns> 26 int Subtraction(int x, int y); 27 28 ProductDto BuyProduct(string productName, int number); 29 } 30 31 32 public class ProductDto 33 { 34 public string Name { get; set; } 35 public int Number { get; set; } 36 public double Price { get; set; } 37 public double Amount { get { return Price * Number; } } 38 public string CountryOfOrigin { get; set; } 39 } 40 }
增加控制器:ValuesController.cs
1 public class ValuesController : ApiController 2 { 3 private readonly IHelloWorldViperService helloWorldViperService; 4 public ValuesController(IHelloWorldViperService helloWorldViperService) { 5 this.helloWorldViperService = helloWorldViperService; 6 } 7 [HttpGet] 8 public dynamic SayHello(string name, int age) { 9 var rlt= helloWorldViperService.SayHello(name,age); 10 return Json(rlt); 11 } 12 [HttpGet] 13 public int Subtraction(int x, int y) { 14 return helloWorldViperService.Subtraction(x,y); 15 } 16 [HttpGet] 17 public dynamic BuyProduct(string productName, int number) { 18 return helloWorldViperService.BuyProduct(productName, number); 19 }
主要步骤:
安装Nuget包---》初始化Anno注册中心配置----》代理注入AutoFac容器---》控制器通过构造函数注入服务接口
2.1、开始演示
1、启动注册中心
2、启动HelloWorldService服务
再来看下注册中心输出的信息
注册中心已经收到HelloWorldService服务的注册
3、启动我们的Asp.net Web API
调用控制器接口:SayHello
[HttpGet] public dynamic SayHello(string name, int age) { var rlt= helloWorldViperService.SayHello(name,age); return Json(rlt); }
看到了输出结果,第一个接口调用成功。
第二个接口:Subtraction
1 [HttpGet] 2 public int Subtraction(int x, int y) { 3 return helloWorldViperService.Subtraction(x,y); 4 }
看到了输出结果75,也是我们预期的结果。调用成功。
第三个接口:BuyProduct
1 [HttpGet] 2 public dynamic BuyProduct(string productName, int number) { 3 return helloWorldViperService.BuyProduct(productName, number); 4 }
也是我们预期的结果。调用成功。
学习交流 QQ群:478399354 ,到这里我们互为师长相互学习。
Anno核心源码:https://github.com/duyanming/Anno.Core
Viper示例项目:https://github.com/duyanming/Viper
体验地址:http://140.143.207.244/Home/Login
文档地址:https://duyanming.github.io/
关于Anno的更多内容,随后更新。敬请关注。开源不易,感谢Star。