dotnetcore+vue+elementUI 前后端分离架 二(后端篇)

前言

最近几年前后端分离架构大行其道,而且各种框架也是层出不穷。本文通过dotnetcore +vue 来介绍 前后端分离架构实战。

涉及的技术栈

服务端技术

  • mysql

    本项目使用mysql 作为持久化层
    本项目采用了 mysql 的示例 employees 数据库, 需要的朋友可以自行下载 。

http://www3.ntu.edu.sg/home/ehchua/programming/sql/SampleDatabases.html

  • orm

    dapper 短小精悍,被称为orm中的瑞士军刀。作者之前使用EF 比较多,总感觉 EF 对一些复杂查询需要原生sql支持的不是那么好,EF 生成sql 不好控制,涉及对性能要求比较高的地方,优化起来不够理想。作者在最近的几个项目中接触到dapper,它对原生sql查询支持的相当给力,使用起来也比较简便,感觉真是爱不释手,嘿嘿。。。
    https://github.com/StackExchange/Dapper

  • 架构

    服务端整体架构采用仓储模式
    Repository是一个独立的层,介于领域层与数据映射层(数据访问层)之间。它的存在让领域层感觉不到数据访问层的存在,它提供一个类似集合的接口提供给领域层进行领域对象的访问。Repository是仓库管理员,领域层需要什么东西只需告诉仓库管理员,由仓库管理员把东西拿给它,并不需要知道东西实际放在哪。
    此处照搬了dudu同学对仓储模式的理解。
    仓储模式的好处:领域依赖接口与DB进行交互,解除了二者之间的耦合,如果更换orm,DB层,采用这种模式,更换的代价最低。

前端技术

整体上SPA 结构

  • Vue:

    渐进式 JavaScript 框架.
    三大特点:易用,灵活, 高效。
    详细信息见 https://cn.vuejs.org/

  • VueRouter

    vue-router是Vue.js官方的路由插件,它和vue.js是深度集成的,适合用于构建单页面应用。vue的单页面应用是基于路由和组件的,路由用于设定访问路径,并将路径和组件映射起来。传统的页面应用,是用一些超链接来实现页面切换和跳转的。在vue-router单页面应用中,则是路径之间的切换,也就是组件的切换。

  • axios

    axios 开始崛起, 是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端。

  • ElementUI

    网站快速成型工具
    Element,一套为开发者、设计师和产品经理准备的基于 Vue 2.0 的桌面端组件库
    详细信息见 http://element-cn.eleme.io/#/zh-CN

服务端项目结构

服务端代码地址:https://github.com/hbb0b0/Hbb0b0.CMS/tree/master/Hbb0b0.CMS.WebAPI

摘取部分类予以说明。

CMS.Common

通用工具的封装

  • 配置工具类

DB配置

Cors配置

WebApi配置

  • DB工具类

DapperContext

IRespository

ResponsitoryBase

包含获取列表,获取分页列表,增删改的通用操作的封装

SimpleCRUD

github上对Dapper的进一步分装

  • 消息

  • 数据转换

entity --> Dto

DTObase

PageList

CMS.DTO

返回给前端的数据对象,隔离DB model变化直接映射前端对象,使View与Model解耦。

CMS.Model

DB 中的表映射到 Model

CMS.IResponsity

DB 操作接口

CMS.Responsity

DB 操作接口的实现

CMS.IService

Serive接口,可以供给第三方调用,也是第三方调用的规范,同时也约束着服务实现。
目前提供给API层调用。

CMS.Service

Serive接口的实现

CMS.API

以WebAPI 形式提供给前台调用,并不是严格按照 WebApi 规范 post,get,put,delete 调用.使用了 core中的 mvc 方式。

  • CMS.API 调用 IService 接口

  • CMS.Service 调用 IResponsitory接口

  • 各接口与实现之间通过Core中的构造函数注入方式联接

服务端代码说明:

  • 配置

{

  "Logging": {

    "IncludeScopes": false,

    "Debug": {

      "LogLevel": {

        "Default": "Information"

      }

    },

    "Console": {

      "LogLevel": {

        "Default": "Information"

      }

    }


  },

  "WebAPI": {

    "DB": {

      "ConnectionString": "server=localhost;database=employees;uid=root;pwd=sqlsa;charset='utf8';persistsecurityinfo=True;SslMode=none;Allow User Variables=True;",

      "ReadingConnectionString": "server=localhost;database=employees;uid=root;pwd=sqlsa;charset='utf8';persistsecurityinfo=True;SslMode=none;Allow User Variables=True;",

      "WritingConnectionString": "server=localhost;database=employees;uid=root;pwd=sqlsa;charset='utf8';persistsecurityinfo=True;SslMode=none;Allow User Variables=True;"


    },

    "Cors": {

      "Name": "CMSCorsConfig",

      "Original": "http://localhost:8080"

    }


  }

}

APIStartup

  • 配置读取与接口实现配置

using System;

using System.Collections.Generic;

using System.Linq;

using System.Threading.Tasks;

using CMS.Common;

using CMS.Common.Config;

using CMS.Common.DB;

using CMS.IRepository;

using CMS.IService;

using CMS.Repository;

using CMS.Service;

using Microsoft.AspNetCore.Builder;

using Microsoft.AspNetCore.Hosting;

using Microsoft.Extensions.Configuration;

using Microsoft.Extensions.DependencyInjection;

using Microsoft.Extensions.Logging;

using Microsoft.Extensions.Options;

using Newtonsoft.Json;

using Newtonsoft.Json.Serialization;


namespace CMS.WebApi

{

    public class Startup

    {

        public Startup(IConfiguration configuration)

        {

            Configuration = configuration;

        }


        public IConfiguration Configuration { get; }


        // This method gets called by the runtime. Use this method to add services to the container.

        public void ConfigureServices(IServiceCollection services)

        {

            services.AddMvc()

            //序列化设置

            .AddJsonOptions(options =>

             {

                 //忽略循环引用

                 options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;

                 //不使用驼峰样式的key

                 //options.SerializerSettings.ContractResolver = new DefaultContractResolver();

                 //设置时间格式

                 options.SerializerSettings.DateFormatString = "yyyy-MM-dd hh:mm:ss"; 

             }

        );


            services.AddOptions();


            //读取配置

            services.Configure<WebApiOption>(Configuration.GetSection("WebAPI"));


            IServiceProvider serviceProvider = services.BuildServiceProvider();

            //获取配置

            WebApiOption config = serviceProvider.GetService<IOptions<WebApiOption>>().Value;

            //Cors配置

            AddCorsService(services,config);

            //DB Service

            AddDBService(services,config);

        


        }


        /// <summary>

        /// AddDBService

        /// </summary>

        /// <param name="services"></param>

        /// <param name="config"></param>

        private void AddDBService(IServiceCollection services,WebApiOption config)

        {

           

            //设置全局配置

            services.AddSingleton<IDapperContext>(_ => new DapperContext(

               config

               ));


            services.AddScoped<IDepartmentRep, DepartmentRep>();

            services.AddScoped<IDepartmentService, DepartmentService>();


            services.AddScoped<IEmployeeRep, EmployeeRep>();

            services.AddScoped<IEmployeeService, EmployeeService>();


            services.AddScoped<ITitleRep, TitleRep>();

            services.AddScoped<ISalaryRep, SalaryRep>();



        }



        /// <summary>

        /// AddCorsService

        /// </summary>

        /// <param name="services"></param>

        /// <param name="config"></param>

        private void AddCorsService(IServiceCollection services, WebApiOption config)

        {

          

            //添加cors 服务

            services.AddCors(options =>

                                     options.AddPolicy(WebApiOption.CORS_POLICY_NAME, p => p.WithOrigins(config.Cors.Original)

             .AllowAnyMethod().AllowAnyHeader()));

        }


        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)

        {

            if (env.IsDevelopment())

            {

                app.UseDeveloperExceptionPage();

            }


            app.UseMvc();



            app.UseMvc(routes =>

            {


                routes.MapRoute(

                    name: "default",

                    template: "{controller}/{action}/{no?}",

                    defaults: new { controller = "Home", action = "Index" });

            });

           

            //配置Cors

            app.UseCors(WebApiOption.CORS_POLICY_NAME);



        }

    }

}

  • ControllerBase

using CMS.Common.Config;

using Microsoft.AspNetCore.Cors;

using Microsoft.AspNetCore.Mvc;

using Microsoft.Extensions.Logging;

using System;

using System.Collections.Generic;

using System.Linq;

using System.Threading.Tasks;


namespace CMS.WebApi.Common

{

    [Route("api/[controller]")]

    [EnableCors(WebApiOption.CORS_POLICY_NAME)]

    public abstract class BaseController: Controller

    {

        protected readonly ILogger m_Logger;


        public BaseController(ILogger<BaseController> logger)

        {

            m_Logger = logger;

        }

    }

}

  • EmployeeController

using System;

using System.Collections.Generic;

using System.Linq;

using System.Threading.Tasks;

using CMS.Common;

using CMS.Common.Config;

using CMS.Common.Message;

using CMS.DTO;

using CMS.Entity;

using CMS.IService;

using CMS.WebApi.Common;

using Microsoft.AspNetCore.Cors;

using Microsoft.AspNetCore.Mvc;

using Microsoft.Extensions.Logging;

using Microsoft.Extensions.Options;

using Newtonsoft.Json;


namespace CMS.WebApi.Controllers

{



    public class EmployeeController : BaseController

    {


        private DBOption m_CmsOptions;

        private IEmployeeService m_Service;


        public EmployeeController(IOptions<DBOption> option, IEmployeeService employeeService, ILogger<EmployeeController> logger) : base(logger)

        {

            this.m_CmsOptions = option.Value;

            m_Service = employeeService;

        }



        [Route("[action]/{pageNumber}/{rowsPerPage}")]

        [HttpGet]

        public ReponseMessage<PagedList<EmployeeDTO>> GetPagedList(int pageNumber, int rowsPerPage)

        {

            var result = m_Service.GetPagedList(pageNumber, rowsPerPage);


            return m_Service.GetPagedList(pageNumber, rowsPerPage);

        }


        [Route("[action]")]

        [HttpPost]

        public ReponseMessage<PagedList<EmployeeDTO>> Query([FromBody]QueryCondition<EmployeeQuery> condition)

        {

            var result = m_Service.Query(condition);

            m_Logger.LogInformation("GetPagedList:{0}", JsonConvert.SerializeObject(result));

            return result;

        }


        [Route("[action]/{no}")]

        [HttpGet]

        public ReponseMessage<EmployeeDetailDto> GetDetail(string no)

        {

            var result = m_Service.GetDetail(no);


            return result;

        }


        [Route("[action]")]

        [HttpPost]

        public ReponseMessage<int> Add([FromBody]EmployeeDTO dto)

        {

            var result = m_Service.Add(dto);


            return result;

        }


        [Route("[action]/{empNo}")]

        [HttpPost]

        public ReponseMessage<int> Delete(int empNo)

        {

            var result = m_Service.Delete(empNo);


            return result;

        }


        [Route("[action]/")]

        [HttpPost]

        public ReponseMessage<int> Update([FromBody]EmployeeDTO dto)

        {

            var result = m_Service.Update(dto);


            return result;

        }

    }

}

  • IService

using CMS.Common;

using CMS.Common.Message;

using CMS.DTO;

using CMS.Entity;

using CMS.Model;

using System;

using System.Collections.Generic;


namespace CMS.IService

{

    public interface IEmployeeService

    {


        ReponseMessage<PagedList<EmployeeDTO>> GetPagedList(int pageNumber, int rowsPerPage);


        ReponseMessage<PagedList<EmployeeDTO>> Query(QueryCondition<EmployeeQuery> condition);

        ReponseMessage<EmployeeDetailDto> GetDetail(string emp_no);


        ReponseMessage<int> Add(EmployeeDTO dto);


        ReponseMessage<int> Update(EmployeeDTO dto);


        ReponseMessage<int> Delete(int emp_No);

    }

}

  • Service 实现

using CMS.Common;

using CMS.Common.Message;

using CMS.DTO;

using CMS.Entity;

using CMS.IRepository;

using CMS.IService;

using CMS.Model;

using CMS.Utility;

using Dapper;

using System;

using System.Collections.Generic;

using System.Linq;

namespace CMS.Service

{

    public class EmployeeService : IEmployeeService

    {

        private IEmployeeRep m_Rep;

        private ITitleRep m_TitleRep;

        private ISalaryRep m_SalaryRep;

        public EmployeeService(IEmployeeRep rep,ITitleRep titleRep, ISalaryRep salaryRep)

        {

            m_Rep = rep;

            m_TitleRep = titleRep;

            m_SalaryRep = salaryRep;

        }


      

        public ReponseMessage<EmployeeDetailDto> GetDetail(string emp_no)

        {

            ReponseMessage<EmployeeDetailDto> result = new ReponseMessage<EmployeeDetailDto>();

            EmployeeDetailDto data = new EmployeeDetailDto();

            var emp = m_Rep.Get(emp_no);

            data.Info = emp.JTransformTo<EmployeeDTO>();

            var titleList = m_TitleRep.GetList(string.Format($"where emp_no = {emp_no}"));

            var salaryList = m_SalaryRep.GetList(string.Format($"where emp_no = {emp_no} order by from_date "));

            result.Data = data;

            result.IsSuccess = true;

            if (titleList != null)

            {

                result.Data.TitleList = titleList.JTransformTo<TitleDto>();

            }


            if (salaryList!=null)

            {

                result.Data.SalaryList = salaryList.JTransformTo<SalaryDto>();

            }

            return result;


        }


        public ReponseMessage<PagedList<EmployeeDTO>> GetPagedList(int pageNumber, int rowsPerPage)

        {

            int total = 0;

            ReponseMessage<PagedList<EmployeeDTO>> result = new ReponseMessage<PagedList<EmployeeDTO>>();

            result.Data = new PagedList<EmployeeDTO>();

            var modelResult= m_Rep.GetPagedList(pageNumber, rowsPerPage, null, null, out total);

            result.Data.TotalCount = total;

            result.Data.Items=modelResult.Items.JTransformTo<EmployeeDTO>();

            result.IsSuccess = true;


            return result;

        }

        public ReponseMessage<PagedList<EmployeeDTO>> Query(QueryCondition<EmployeeQuery> condition)

        {

            ReponseMessage<PagedList<EmployeeDTO>> result = new ReponseMessage<PagedList<EmployeeDTO>>();

            result.Data = new PagedList<EmployeeDTO>();

            var modelResult = m_Rep.Query(condition);

            result.Data.TotalCount = modelResult.TotalCount;

            if (modelResult.TotalCount > 0)

            {

                result.Data.Items = modelResult.TotalCount>0 ? modelResult.Items.JTransformTo<EmployeeDTO>():new List<EmployeeDTO>();

            }

            result.IsSuccess = true;


            return result;

        }


        public ReponseMessage<int> Add(EmployeeDTO dto)

        {

            ReponseMessage<int> result = new ReponseMessage<int>();

            if (dto==null )

            {

                result.IsSuccess = false;

                result.MessageInfo = new MessageInfo() { ErrorCode = -1, Message ="无效的参数" };

            }


            EmployeeModel entitity = dto.JTransformTo<EmployeeModel>();


            int? opResult =  m_Rep.CustomerAdd(entitity);


            if(opResult.HasValue && opResult>0)

            {

                result.IsSuccess = true;

                result.Data = opResult.Value;

            }

            

            return result;

        }


        public ReponseMessage<int> Update(EmployeeDTO dto)

        {

            ReponseMessage<int> result = new ReponseMessage<int>();

            if (dto == null)

            {

                result.IsSuccess = false;

                result.MessageInfo = new MessageInfo() { ErrorCode = -1, Message = "无效的参数" };

            }


            EmployeeModel entitity = dto.JTransformTo<EmployeeModel>();


            int? opResult = m_Rep.Update(entitity);


            if (opResult.HasValue && opResult > 0)

            {

                result.IsSuccess = true;

                result.Data = opResult.Value;

            }


            return result;

        }


        public ReponseMessage<int> Delete(int empNo)

        {

            ReponseMessage<int> result = new ReponseMessage<int>();


            int? opResult = m_Rep.Delete(empNo);


            if (opResult.HasValue && opResult ==1)

            {

                result.IsSuccess = true;

                result.Data = opResult.Value;

            }


            return result;

        }

    }

}

  • IResponsitory

using CMS.Common;

using CMS.Common.DB;

using CMS.DTO;

using CMS.Entity;

using CMS.Model;

using System;

using System.Collections.Generic;

using System.Text;


namespace CMS.IRepository

{

    public interface IEmployeeRep: IRepository<EmployeeModel>

    {

        PagedList<EmployeeDTO> Query(QueryCondition<EmployeeQuery> query);


        int? Add(EmployeeModel entity);


        int? CustomerAdd(EmployeeModel entity);


        int? Delete(int  empNo);


        int? Update(EmployeeModel entity);


    }

}

-Responsitory 实现


using CMS.Common;

using CMS.Common.DB;

using CMS.DTO;

using CMS.IRepository;

using CMS.Model;

using System;

using System.Collections.Generic;

using System.Text;

using Dapper;


namespace CMS.Repository

{

  public class EmployeeRep : ReponsitoryBase, IEmployeeRep

  {

    private static object m_sync_Object = new object();


    public EmployeeRep(IDapperContext dapper) : base(dapper)

   {

    }


    public int? Add(EmployeeModel entity)

    {

        return this.Insert(entity);

    }

    new public int? Update(EmployeeModel entity)

    {

        return base.Update(entity);

    }

    public int? CustomerAdd(EmployeeModel entity)

    {

        int cmdResult = -1;

        using (var connection = this.GetWritingConnection())

        {

            var sql = new StringBuilder(" set @maxNo=(select max(emp_no)+1 from employees) ;");

            sql.AppendLine("insert into employees(emp_no,first_name,last_name,gender,birth_date,hire_date) values(@maxNo,@first_name,@last_name,@gender,@birth_date,@hire_date); ");

            sql.AppendLine("select @maxNo;");

            cmdResult = connection.ExecuteScalar<int>(sql.ToString(), entity);

        }


        return cmdResult;

    }


    public int? Delete(int empNo)

    {

        int cmdResult = -1;

        using (var connection = this.GetWritingConnection())

        {

            cmdResult = connection.Execute("delete from employees where emp_no = @emp_no ;", new { emp_no = empNo });

        }


        return cmdResult;

    }


    public PagedList<EmployeeDTO> Query(QueryCondition<EmployeeQuery> query)

    {



        PagedList<EmployeeDTO> pagedList = new PagedList<EmployeeDTO>();

        #region sql


        var sql = new StringBuilder("SELECT SQL_CALC_FOUND_ROWS * from employees ");


        #endregion


        sql.AppendLine(" Where 1=1");



        if (!string.IsNullOrEmpty(query.Param.First_Name))

        {

            sql.AppendLine(string.Format(" and First_Name like '{0}'", query.GetLikeValue(query.Param.First_Name)));

        }


        if (!string.IsNullOrEmpty(query.Param.Last_Name))

        {

            sql.AppendLine(string.Format(" and last_Name like '{0}'", query.GetLikeValue(query.Param.Last_Name)));

        }


        if (!string.IsNullOrEmpty(query.Param.Emp_No))

        {

            sql.AppendLine(string.Format(" and emp_no = @Emp_No"));

        }


        if (!string.IsNullOrEmpty(query.Param.Gender))

        {

            sql.AppendLine(string.Format(" and gender = @Gender"));

        }


        DateTime? hire_date_start = null;

        DateTime? hire_date_end = null;

        if (query.Param.Hire_Date_Range != null)

        {

            if (query.Param.Hire_Date_Range[0].HasValue)

            {

                hire_date_start = query.Param.Hire_Date_Range[0];

                sql.AppendLine(string.Format(" and hire_date >= @Hire_Date_Range_Start"));

            }

            if (query.Param.Hire_Date_Range[1].HasValue)

            {

                hire_date_end = query.Param.Hire_Date_Range[1];

                sql.AppendLine(string.Format(" and hire_date <= @Hire_Date_Range_End"));

            }

        }


        DateTime? birth_date_start = null;

        DateTime? birth_date_end = null;

        if (query.Param.Birth_Date_Range != null)

        {

            if (query.Param.Birth_Date_Range[0].HasValue)

            {

                birth_date_start = query.Param.Birth_Date_Range[0];

                sql.AppendLine(string.Format(" and birth_date >= @Birth_Date_Range_Start"));

            }

            if (query.Param.Birth_Date_Range[1].HasValue)

            {

                birth_date_end = query.Param.Birth_Date_Range[1];

                sql.AppendLine(string.Format(" and birth_date <= @Birth_Date_Range_End"));

            }

        }


        sql.AppendLine(" order by emp_no desc");

        sql.AppendLine($" LIMIT {(query.pageInfo.PageIndex - 1) * query.pageInfo.PageSize},{query.pageInfo.PageSize}");

        sql.Append(";");

        using (var connection = this.GetReadingConnection())

        {

            var result = connection.Query<EmployeeDTO>(sql.ToString(),

                new

                {

                    Emp_No = query.Param.Emp_No,

                    Hire_Date_Range_Start = hire_date_start,

                    Hire_Date_Range_End = hire_date_end,

                    Birth_Date_Range_Start = birth_date_start,

                    Birth_Date_Range_End = birth_date_end,

                    Gender = query.Param.Gender


                }).AsList();

            pagedList.Items = result;

            pagedList.TotalCount = connection.ExecuteScalar<int>("SELECT FOUND_ROWS();");

        }

        return pagedList;

    }


}

目前测试 empoyee 30万条分页数据大致在400ms左右

相关文章:

  • 浅谈开发模式及架构发展

  • dotnet core webapi +vue 搭建前后端完全分离web架构(一)

原文地址:http://www.cnblogs.com/hbb0b0/p/8391598.html


.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/322147.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringCloud Gateway配置自定义路由404坑

一、场景复现 微服务自定义路由&#xff0c;返回404页面。 ①如图&#xff1a; &#xff08;1&#xff09;springcloud-gateway的路由设置 Configuration public class RouteConfig {Beanpublic RouteLocator customRouteLocator(RouteLocatorBuilder builder) {return buil…

Actor-ES框架:Ray-Handler之ToReadHandler编写

如图右上角所示&#xff0c;Ray中有两类Handler&#xff08;SubHandler和PartSubHandler&#xff09;,在使用中&#xff0c;SubHandler派生Actor的CoreHandler&#xff0c;PartSubHandler派生SQLToReadHandler&#xff0c;SQLToReadHandler派生Actor的ToReadHandler&#xff0c…

SpringCloud Zuul(十)之配置路由prefix坑

一、场景复现 配置prefixapi访问/api/micro-service/test接口404 &#xff08;1&#xff09;zuul配置 zuul:strip-prefix: true #转发路径截断匹配前缀prefix: "api"add-proxy-headers: falseset-content-length: truesemaphore:max-semaphores: 600 &#xff08;…

在Firefox 58中,WebAssembly组件性能提升了10倍

Mozilla在Firefox 58中为WebAssembly&#xff08;WASM&#xff09;组件推出了一套双层编译系统&#xff0c;号称解析和编译WASM代码的速度达到30-60MB/s&#xff0c;足够在有线网络中实现实时编译。基准测试表明&#xff0c;新版的性能比旧版提高了10倍&#xff0c;比Chrome快1…

SpringCloud Zuul(九)之路由自动刷新原理

一、现象 发布新服务&#xff0c;然后在数据库配置了路由&#xff0c;使用服务路径访问404。然后重新发布新的服务&#xff0c;就可以继续访问得到 &#xff08;1&#xff09;配置了路由第一次访问 &#xff08;2&#xff09;重新发布后访问 二、分析 &#xff08;1&#xf…

dotnetcore+vue+elementUI 前后端分离 三(前端篇)

说明&#xff1a;本项目使用了 mysql employees数据库&#xff0c;使用了vue axois element UI 2.0 ,演示了 单页程序 架构 ,vue router 的使用&#xff0c;axois 使用&#xff0c;以及 element UI 控件的使用。通过这几种技术的组合&#xff0c;实现了对 employee 的增&…

SpringCloud Greenwich(一)注册中心之nacos、Zuul和 gateway网关配置

本项目是搭建基于nacos注册中心的springcloud&#xff0c;使用zuul网关和gateway网关。 一、框架搭建 &#xff08;1&#xff09;项目结构 micro-service 服务提供者 zuul-gateway zuul网关 springcloud-gateway gateway网关 &#xff08;2&#xff09;环境 nacos 1.4.1…

欢乐ssl暑假赛【2019.8.6】

前言 莫得前言 成绩 JJJ表示初中&#xff0c;HHH表示高中后面加的是几年级&#xff0c;只放前10 RankRankRankPersonPersonPersonScoreScoreScoreAAABBBCCCDDDEEE111(J−3)WYC(J-3)WYC(J−3)WYC500500500100100100100100100100100100100100100100100100222(H−1)QYH(H-1)QYH(H…

Actor-ES框架:Ray-Handler-消息订阅器编写

消息订阅器&#xff1a;Ray是基于Event Sourcing设计的ES/Actor框架&#xff0c;消息发布后需要订阅处理&#xff0c;订阅器主要有以下两类&#xff1a;CoreHandler消息订阅器RabbitSubSubHandlerToReadHandler消息订阅器RabbitSubSQLToReadHandler&#xff08;ToReadHandler的…

Actor-ES框架:Actor编写-ESGrain与ESRepGrain

ESGrain生命周期Ray中ESGrain继承自Grain扩展了Grain的生命周期。Grain的生命周期参加文档附录&#xff1a;1-Grain生命周期-译注.mdESGrain重写了Grain的OnActivateAsync方法。ESGrain的初始化过程如下&#xff1a;初始化ESGrain中的State调用ReadSnapshotAsync()读快照。如果…

DotNetAnywhere:可供选择的 .NET 运行时

我最近在收听一个名为DotNetRock 的优质播客&#xff0c;其中有以Knockout.js而闻名的Steven Sanderson 正在讨论 " WebAssembly And Blazor "。也许你还没听过&#xff0c;Blazor 正试图凭借WebAssembly的魔力将 .NET 带入到浏览器中。如果您想了解更多信息&#xf…

SpringCloud Greenwich(二)注册中心之consul、Zuul和 gateway网关配置

本项目是搭建基于consul注册中心的springcloud&#xff0c;使用zuul网关和gateway网关 一、框架搭建 &#xff08;1&#xff09;项目结构 micro-service 服务提供者 zuul-gateway zuul网关 springcloud-gateway gateway网关 &#xff08;2&#xff09;环境 consul 1.9.0…

Actor-ES框架:消息发布器与消息存储器

消息发布器&#xff1a;Ray是基于Event Sourcing设计的ES/Actor框架&#xff0c;ESGrain状态&#xff08;State&#xff09;的修改、ESGrain之间的通信默认使用RabbitMQ通信。消息的发布器主要是RabbitPubESGrain。RabbitPub特性RabbitPub特性是RabbitMQ消息发布器。RabbitSub特…

consul的安装搭建

一、下载consul consul官网下载地址&#xff1a;https://www.consul.io/downloads 旧版本下载 consul 1.9.3直接下载地址&#xff1a; consul_1.9.3_windows_amd64.zip consul_1.9.3_linux_amd64.zip 二、安装 将consul_1.9.3_xxx.zip解压的xxx/consul目录 &#xff08;1&…

使用xUnit为.net core程序进行单元测试

一. 导读为什么要编写自动化测试程序&#xff08;Automated Tests&#xff09;&#xff1f;可以频繁的进行测试可以在任何时间进行测试&#xff0c;也可以按计划定时进行&#xff0c;例如&#xff1a;可以在半夜进行自动测试。肯定比人工测试要快。可以更快速的发现错误。基本上…

jzoj6276-[Noip提高组模拟1]树【线段树,扫描线,倍增】

正题 题目大意 一棵树&#xff0c;若干个点对&#xff0c;求不包括任何一个点对的路径数量。 解题思路 我们考虑将不合法的方案在坐标系上表示。 我们先只考虑一个点对(x,y)(x,y)(x,y)&#xff0c;若xxx和yyy没有祖先关系&#xff0c;则不合法的路径一个点在xxx的子树中&…

SpringCloud Greenwich(三)注册中心之zookeeper、Zuul和 gateway网关配置

本项目是搭建基于zookeeper注册中心的springcloud&#xff0c;使用zuul网关和gateway网关 一、框架搭建 &#xff08;1&#xff09;项目结构 micro-service 服务提供者 zuul-gateway zuul网关 springcloud-gateway gateway网关 &#xff08;2&#xff09;环境 zookeeper…

Metrics, tracing 和 logging 的关系

译者注Peter Bourgon原作&#xff1a; Metrics, tracing, and logging译者&#xff1a;吴晟原作发表时间&#xff1a; 2017年2月21日这是在OpenTracing和分布式追踪领域内广受欢迎的一篇博客文章。在构建监控系统时&#xff0c;大家往往在这几个名词和方式之间纠结。 通过这篇文…

快速序列化组件MessagePack介绍

简介MessagePack for C&#xff03;&#xff08;MessagePack-CSharp&#xff09;是用于C&#xff03;的极速MessagePack序列化程序&#xff0c;比MsgPack-Cli快10倍&#xff0c;与其他所有C&#xff03;序列化程序相比&#xff0c;具有最好的性能。 MessagePack for C&#xff…

SpringCloud Greenwich(四)注册中心之eureka、Zuul和 gateway网关配置

本项目是搭建基于eureka注册中心的springcloud&#xff0c;使用zuul网关和gateway网关 一、框架搭建 &#xff08;1&#xff09;项目结构 eureka-server eureka注册中心 micro-service 服务提供者 zuul-gateway zuul网关 springcloud-gateway gateway网关 &#xff08;…