使用docker搭建Swagger

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用docker搭建Swagger相关的知识,希望对你有一定的参考价值。

参考技术A json文件挂在到容器中

-p:宿主机端口:容器端口,将容器端口暴露给宿主机端口
-d:后台启动
-e:执行容器中/foo/swagger.json
-v:将宿主机中/home/service/swagger/swagger.json挂载到容器 /foo中执行

输入:http://主机IP:端口

NetCore 3.1 项目搭建反射依赖注入,Swagger结合Jwt,sqlSugar+EfCore异常中间件+Log4Net+MongoDb,Redis+Docker,丰富的公共类库,代码示例 下

十年河东,十年河西,莫欺少年穷

学无止境,精益求精

1、通过反射自动注入接口及服务类,项目数据访问层和业务逻辑层分离

2、数据库操作使用EFCore

3、sqlSugar 实现数据库复杂查询

4、实例代码丰富

5、丰富的公共类库

6、支持swagger + jwt + 异常中间件 + mongoDb + redis + docker 

下载地址:https://download.csdn.net/download/bbwolong/81748937

 简单介绍如下:

 

 

示例代码:

扩展方法:JwtExtension

 public static class JwtExtension
    
        public static void AddJwt(this IServiceCollection services)
        
            services.AddAuthentication(x =>
            
                x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            ).AddJwtBearer(x =>
            
                x.RequireHttpsMetadata = false;
                x.SaveToken = true;
                x.TokenValidationParameters = new TokenValidationParameters
                
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(TokenManagementModel.Secret)),
                    ValidIssuer = TokenManagementModel.Issuer,
                    ValidAudience = TokenManagementModel.Audience,
                    ValidateIssuer = false,
                    ValidateAudience = false
                ;
            );
        
    

扩展方法Swagger

 public static class SwaggerExtension
    
        public static void AddSwagger(this IServiceCollection services, string apiName, string title = "", string version="V1")
        
            services.AddSwaggerGen(c =>
            
                // 添加文档信息
                c.SwaggerDoc(version, new OpenApiInfo
                
                    Version = version,
                    Title = title
                );
                AddSwagger(apiName, c);
            );
        


        public static void AddSwagger(this IServiceCollection services, string apiName, params OpenApiInfo[] infos)
        
            services.AddSwaggerGen(c =>
            
                // 添加文档信息
                foreach (var item in infos)
                
                    c.SwaggerDoc(item.Version, item);
                
                AddSwagger(apiName, c);
            );
        

        private static void AddSwagger(string apiName, SwaggerGenOptions c)
        
            c.DocumentFilter<HiddenApiFilter>();
            c.DocumentFilter<SwaggerEnumFilter>();
            c.SchemaFilter<HiddenFieldFilter>();
            c.DocInclusionPredicate((docName, apiDesc) => apiDesc.GroupName == docName.ToUpper());
            var basePath = Path.GetDirectoryName(AppContext.BaseDirectory);
            c.IncludeXmlComments(Path.Combine(basePath, $"apiName.xml"), true);
            c.IncludeXmlComments(Path.Combine(basePath, Constants.ModelDllXml), true);

            #region Jwt
            c.OperationFilter<AddResponseHeadersFilter>();
            c.OperationFilter<AppendAuthorizeToSummaryOperationFilter>();
            c.OperationFilter<SecurityRequirementsOperationFilter>();
            c.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
            
                Description = "JWT授权(数据将在请求头中进行传递)直接在下面框中输入Bearer token(注意两者之间是一个空格) \\"",
                Name = "Authorization",//jwt默认的参数名称
                In = ParameterLocation.Header,//jwt默认存放Authorization信息的位置(请求头中)
                Type = SecuritySchemeType.ApiKey
            );
            #endregion
        

        public static void UseSwag(this IApplicationBuilder app, string version = "V1")
         
            // 启用Swagger中间件
            app.UseSwagger(c => c.RouteTemplate = "/swagger/documentName/swagger.json");
            // 配置SwaggerUI
            app.UseSwaggerUI(c =>
            
                c.SwaggerEndpoint($"Constants.VirtualPath/swagger/version/swagger.json", version);
            );
        

        public static void UseSwag(this IApplicationBuilder app, params string[] versions)
        
            // 启用Swagger中间件
            app.UseSwagger(c => c.RouteTemplate = "/swagger/documentName/swagger.json");
            // 配置SwaggerUI
            foreach (var version in versions)
            
                app.UseSwaggerUI(c =>
                
                    c.SwaggerEndpoint($"Constants.VirtualPath/swagger/version/swagger.json", version);
                );
            
        
    

扩展方法:JsonExtension

    public static class JsonExtension
    
        public static void AddJson(this IServiceCollection services,bool resolver = true)
        
            services.AddControllersWithViews().AddNewtonsoftJson(options =>
            
                if (resolver)
                
                    options.SerializerSettings.ContractResolver = new DefaultContractResolver();
                
                options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc;  // 设置时区为 UTC)
                options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
            );
        
    

过滤器:HiddenApiFilter

    public class HiddenApiFilter : IDocumentFilter
    
        public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
        
            foreach (var item in context.ApiDescriptions)
            
                if (item.TryGetMethodInfo(out MethodInfo methodInfo))
                
                    if (methodInfo.ReflectedType.CustomAttributes.Any(t => t.AttributeType == typeof(HiddenAttribute))
                    || methodInfo.CustomAttributes.Any(t => t.AttributeType == typeof(HiddenAttribute)))
                    
                        var key = "/" + item.RelativePath.TrimEnd(\'/\');
                        if (key.Contains("?"))
                        
                            int idx = key.IndexOf("?", StringComparison.Ordinal);
                            key = key.Substring(0, idx);
                        
                        if (swaggerDoc.Paths.ContainsKey(key))
                        
                            swaggerDoc.Paths.Remove(key);
                        
                    
                
            
        
    


    public class HiddenFieldFilter : ISchemaFilter
    
        public void Apply(OpenApiSchema schema, SchemaFilterContext context)
        
            if (schema?.Properties == null)
            
                return;
            
            var name = context.Type.FullName;
            var excludedProperties = context.Type.GetProperties();
            foreach (var property in excludedProperties)
            
                var attribute = property.GetCustomAttribute<HiddenFieldAttribute>();
                if (attribute != null
                    && schema.Properties.ContainsKey(property.Name.ToLowerStart()))
                
                    schema.Properties.Remove(property.Name.ToLowerStart());
                
            ;
        
    

通过反射依赖注入

public static class DIRegister
    
        public static void RegisterDI(this IServiceCollection services)
        
            var rootPath = Path.GetDirectoryName(typeof(DIExtension).Assembly.Location);
            var rootDir = new DirectoryInfo(rootPath);
            var basePath = rootDir.FullName;
            //注册业务访问层    接口 与 实现类 注册为 AddScoped
            RegisterDll(services, basePath, Constants.ServiceDllFullName, Constants.ServiceSuffix );
            //注册数据访问层  接口 与 实现类 注册为 AddScoped
            RegisterDll(services, basePath, Constants.RepositoryDllFullName, Constants.RepositorySuffix );
        

        private static void RegisterDll(IServiceCollection services, string basePath, string dllName, params string[] endsWith)
        
            ///D:\\525gitProject\\netcore\\WuAnManager\\WuAnChangeApi\\bin\\Debug\\netcoreapp3.1\\WuAnService.dll
            string assemblyPath = Path.Combine(basePath, dllName);
            var assembly = Assembly.LoadFrom(assemblyPath);
            services.RegisterAssemblyEndsWith(assembly, endsWith);
        

        public static void DIListPage(this IApplicationBuilder app, IServiceCollection _services)
        
            app.Map($"/api/allservices", builder => builder.Run(async context =>
            
                var sb = new StringBuilder();
                sb.Append("<h1>All Services</h1>");
                sb.Append("<table><thead>");
                sb.Append("<tr><th>Type</th><th>Lifetime</th><th>Instance</th></tr>");
                sb.Append("</thead><tbody>");
                foreach (var svc in _services)
                
                    sb.Append("<tr>");
                    sb.Append($"<td>svc.ServiceType.FullName</td>");
                    sb.Append($"<td>svc.Lifetime</td>");
                    sb.Append($"<td>svc.ImplementationType?.FullName</td>");
                    sb.Append("</tr>");
                
                sb.Append("</tbody></table>");
                await context.Response.WriteAsync(sb.ToString());
            ));
        
    

异常处理中间件

    public class ExceptionMiddlewares
    
        private ILog log;
        private readonly RequestDelegate next;
        private IHostingEnvironment environment;

        public ExceptionMiddlewares(RequestDelegate next, IHostingEnvironment environment)
        
            this.log = LogManager.GetLogger(Startup.repository.Name, typeof(ExceptionMiddlewares));
            this.next = next;
            this.environment = environment;
        

        public async Task Invoke(HttpContext context)
        
            try
            
                await next.Invoke(context);
                var features = context.Features;
            
            catch(AssertException ex)
            
                if (context.Response.HasStarted)
                
                    throw;
                
                await Response(context, ex.HttpStatusCode, ex.Message);
            
            catch (Exception e)
            
                Log.Inst.Error($"wuanapi系统异常:e.ToString()");
                await HandleException(context, e);
            
        

        private async Task HandleException(HttpContext context, Exception e)
        
            context.Response.StatusCode = 500;
            context.Response.ContentType = "text/json;charset=utf-8;";
            string error = "";

            var json = new  message = e.Message ;
            log.Error(json);
            error = JsonConvert.SerializeObject(json);


            await context.Response.WriteAsync(error);
        

        private async Task Response(HttpContext httpContext, int statusCode, string message)
        
            httpContext.Response.StatusCode = statusCode;
            httpContext.Response.ContentType = "application/json; charset=utf-8";
            var result = CommonBaseResponse.SetResponse(false, message);
            await httpContext.Response.WriteAsync(result.ToJson());
        
    

SqlSugar 帮助类

 public class DataRepository
    
        public static string NewGuid()
        
            return Guid.NewGuid().ToString("N");
        
        /// <summary>
        /// 获取返回的列表
        /// </summary>
        /// <typeparam name="U"></typeparam>
        /// <param name="sql"></param>
        /// <param name="orderby"></param>
        /// <returns></returns>
        public static List<U> GetListBySql<U>(string sql, string orderby = "")
            where U : class, new()
        
            SugarContext sugar = new SugarContext();
            List<U> result = null;
            using (var db = sugar.Db)
            
                if (string.IsNullOrEmpty(orderby))
                
                    result = db.SqlQueryable<U>(sql).ToList();
                
                else
                
                    result = db.SqlQueryable<U>(sql).OrderBy(orderby).ToList();
                
            
            return result;
        
        /// <summary>
        /// 获取返回的列表-参数化
        /// </summary>
        /// <typeparam name="U"></typeparam>
        /// <param name="sql"></param>
        /// <param name="where"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public static List<U> GetListBySql<U>(string sql, string where, object parameters)
            where U : class, new()
        
            SugarContext sugar = new SugarContext();
            List<U> result = null;
            using (var db = sugar.Db)
            
                result = db.SqlQueryable<U>(sql).Where(where, parameters).ToList();
            
            return result;
        

        /// <summary>
        /// 获取DbSet 第一行
        /// </summary>
        /// <typeparam name="U"></typeparam>
        /// <param name="sql"></param>
        /// <returns></returns>
        public static U GetOneBySql<U>(string sql)
            where U : class, new()
        
            SugarContext sugar = new SugarContext();
            U result = null;
            using (var db = sugar.Db)
            
                result = db.SqlQueryable<U>(sql).First();
            
            return result;
        
        /// <summary>
        /// 获取第一行第一列的值 并转化为Int
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        public static int GetInt(string sql)
        
            SugarContext sugar = new SugarContext();
            using (var db = sugar.Db)
            
                return db.Ado.GetInt(sql);
            
        
        /// <summary>
        /// 获取第一行第一列的值 并转化为Double
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        public static double GetDouble(string sql)
        
            SugarContext sugar = new SugarContext();
            using (var db = sugar.Db)
            
                return db.Ado.GetDouble(sql);
            
        
        /// <summary>
        /// 执行Sql 查询单个实体
        /// </summary>
        /// <typeparam name="E"></typeparam>
        /// <typeparam name="U"></typeparam>
        /// <param name="sql"></param>
        /// <param name="OrderBy"></param>
        /// <param name="u"></param>
        /// <returns></returns>
        public static E PageOne<E>(string sql)
            where E : class, new()
        
            SugarContext sugar = new SugarContext();
            var db = sugar.Db;
            var one = db.SqlQueryable<E>(sql).ToList().FirstOrDefault();
            return one;
        

        /// <summary>
        /// 查询结果List的第一条记录
        /// </summary>
        /// <typeparam name="E"></typeparam>
        /// <param name="sql"></param>
        /// <param name="where"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public static E PageOne<E>(string sql, string where, object parameters)
           where E : class, new()
        
            SugarContext sugar = new SugarContext();
            if (parameters == null)
            
                return PageOne<E>(sql);
            

            var db = sugar.Db;
            var one = db.SqlQueryable<E>(sql).Where(where, parameters).ToList().FirstOrDefault();
            return one;
        

        public static PaginationListModel<E> PageQuery<E, U>(string sql, string OrderBy, U u)
          where U : PaginationModel
          where E : class, new()
        
            SugarContext sugar = new SugarContext();
            var db = sugar.Db;
            int total = 0;
            List<E> list = null;
            if (OrderBy.IsNullOrWhiteSpace())
            
                list = db.SqlQueryable<E>(sql).ToPageList(u.pageNumber, u.pageSize, ref total);
            
            else
            
                list = db.SqlQueryable<E>(sql).OrderBy(OrderBy).ToPageList(u.pageNumber, u.pageSize, ref total);
            
            return new PaginationListModel<E>()
            
                data = list,
                pagination = new BasePaginationModel()
                
                    pageNumber = u.pageNumber,
                    pageSize = u.pageSize,
                    total = total
                
            ;
        


        /// <summary>
        /// 第一行第一列
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public static object ExecuteScalar(string sql, object parameters = null)
        
            SugarContext sugar = new SugarContext();
            using (var db = sugar.Db)
            
                return db.Ado.GetScalar(sql, parameters);
            
        

        /// <summary>
        /// 执行Update insert 等操作
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public static int ExecuteCommand(string sql, object parameters = null)
        
            SugarContext sugar = new SugarContext();
            using (var db = sugar.Db)
            
                return db.Ado.ExecuteCommand(sql, parameters);
            
        

        /// <summary>
        /// 第一行第一列
        /// </summary>
        public static object ExecuteScalar(string sql)
        
            SugarContext sugar = new SugarContext();
            using (var db = sugar.Db)
            
                return db.Ado.GetScalar(sql);
            
        
        /// <summary>
        /// 第一行第一列    -    异步
        /// </summary>
        public static async Task<object> ExecuteScalarAsync(string sql, object parameters = null)
        
            SugarContext sugar = new SugarContext();
            using (var db = sugar.Db)
            
                return await db.Ado.GetScalarAsync(sql, parameters);
            
        
        /// <summary>
        /// 第一行第一列    -    异步
        /// </summary>
        public static async Task<object> ExecuteScalarAsync(string sql)
        
            SugarContext sugar = new SugarContext();
            using (var db = sugar.Db)
            
                return await db.Ado.GetScalarAsync(sql);
            
        

        public static E GetOneBySql<E>(string sql, object parameters = null)
            where E : class
        
            SugarContext sugar = new SugarContext();
            using (var db = sugar.Db)
            
                return db.Ado.SqlQuerySingle<E>(sql, parameters);
            

        
        /// <summary>
        /// 第一行第一列    -    异步
        /// </summary>
        public static async Task<E> GetOneBySqlAsync<E>(string sql, object parameters = null)
          where E : class
        
            SugarContext sugar = new SugarContext();
            using (var db = sugar.Db)
            
                return await db.Ado.SqlQuerySingleAsync<E>(sql, parameters);
            

        

        public static List<E> GetBySql<E>(string sql, object parameters = null)
            where E : class
        
            SugarContext sugar = new SugarContext();
            using (var db = sugar.Db)
            
                return db.Ado.SqlQuery<E>(sql, parameters);
            

        

        public static async Task<List<E>> GetBySqlAsync<E>(string sql, object parameters = null)
            where E : class
        
            SugarContext sugar = new SugarContext();
            using (var db = sugar.Db)
            
                return await db.Ado.SqlQueryAsync<E>(sql, parameters);
            
        

        /// <summary>
        /// 执行事务
        /// </summary>
        /// <param name="sqls"></param>
        public static void ExecTransaction(List<string> sqls)
        
            SugarContext sugar = new SugarContext();
            using (var db = sugar.Db)
            
                try
                
                    db.Ado.BeginTran();
                    foreach (var item in sqls)
                    
                        db.Ado.ExecuteCommand(item);
                    
                    db.Ado.CommitTran();

                
                catch (Exception ex)
                
                    db.Ado.RollbackTran();
                    throw ex;
                
            
        

    

    public class DataRepository<T> where T   : class, new()
    

        public static PaginationListModel<T>  PageQuery<U>(string sql, U u, string where = "")
          where U : OrderByPaginationModel 
        
            SugarContext sugar = new SugarContext();
            var db = sugar.Db;
            var query = db.SqlQueryable<T>(sql);
            if (where.NotNullOrWhiteSpace())
            
                query = query.Where(where, u.ToSqlParam());
            
            if (u.OrderBy.NotNullOrWhiteSpace())
            
                query = query.OrderBy(u.OrderBy);
            
            int total = 0;
            var list = query.ToPageList(u.pageNumber, u.pageSize, ref total);
            return new PaginationListModel<T>()
            
                data = list,
                pagination = new BasePaginationModel()
                
                    pageNumber = u.pageNumber,
                    pageSize = u.pageSize,
                    total = total
                
            ;
        

    

    internal static class SqlExtend
    
        public static string Equal(this string source, string field)
        
            return $"source = field";
        

        public static string Like(this string source)
        
            return $"%source%";
        

        public static Dictionary<string, object> ToSqlParam<T>(this T t)
            where T : class
        
            var fields = typeof(T).GetProperties();
            var fieldDict = new Dictionary<string, object>();
            foreach (var item in fields)
            
                fieldDict.Add(item.Name, item.GetValue(t));
            
            return fieldDict;
        

        public static List<Dictionary<string, object>> ToSqlParam<T>(this List<T> tList)
          where T : class
        
            var result = new List<Dictionary<string, object>>();
            foreach (var item in tList)
            
                result.Add(ToSqlParam(item));
            
            return result;
        

        public static string Top(this string source, int topCount)
        
            return source.Replace("select", $"select top topCount");
        

        public static string Where(this string source, params string[] conditions)
        
            var where = new StringBuilder(" where 1 = 1 ");
            foreach (var item in conditions)
            
                where.Append($" and item ");
            
            return $"source where";
        


    

sqlSugarDbContxt上下文

    public class SugarContext
    
        /// 获取连接字符串        
        private static string Connection = ConfigCommon.Get("WuAnFundDbContext");
        public SugarContext(string connection = "")
        
            Db = new SqlSugarClient(new ConnectionConfig()
            
                ConnectionString = connection.IsNullOrWhiteSpace() ? Connection : connection,
                DbType = DbType.SqlServer,
                InitKeyType = InitKeyType.Attribute,//从特性读取主键和自增列信息
                IsAutoCloseConnection = true,//开启自动释放模式和EF原理一样我就不多解释了

            );
            //调式代码 用来打印SQL 
            Db.Aop.OnLogExecuting = (sql, pars) =>
            
                Console.WriteLine(sql + "\\r\\n" +
                    Db.Utilities.SerializeObject(pars.ToDictionary(it => it.ParameterName, it => it.Value)));
                Console.WriteLine();
            ;

        
        //注意:不能写成静态的
        public SqlSugarClient Db;//用来处理事务多表查询和复杂的操作
    

数据访问层代码示例1

    /// <summary>
    /// 数据库访问层 
    /// </summary>

    public class StudentRepository: IStudentRepository
    
        public List<StudentModel> GetStudents()
        
            string sql = "select * from Student where StudentAge<100 order by StudentAge";
            return DataRepository.GetBySql<StudentModel>(sql);
        

        public List<StudentModel> GetStudentsByName(SearchStudentByNameModel searchParam)
        
            string sql = "select * from Student where 1=1 ";
            if (!string.IsNullOrEmpty(searchParam.StudentName))
            
                sql += " and StudentName=@StudentName";
            
            var parm = new  StudentName = searchParam.StudentName ;
            return DataRepository.GetBySql<StudentModel>(sql, parm);
        

        public PaginationListModel<StudentModel> GetPaginationStudents(SearchStudentModel searchParam)
           
            string sql = string.Format(@"SELECT * FROM [dbo].[Student] ");
            string where = " 1=1 and StudentName<>@StudentName";
            searchParam.OrderBy = "createTime desc";
            return DataRepository<StudentModel>.PageQuery <SearchStudentModel>(sql, searchParam, where);
        


        public PaginationListModel<StudentModel> GetPageStudents(SearchStudentModel_2 searchParam)
        
            string sql = string.Format(@"SELECT * FROM [dbo].[Student] where 1=1  ");
             sql+= " and StudentName<>\'"+ searchParam .StudentName+ "\'";

            return DataRepository.PageQuery<StudentModel, SearchStudentModel_2>(sql, "CreateTime desc", searchParam);
        
    

等等吧,中小企业项目用这个框架完全没问题

@天才卧龙的博客

以上是关于使用docker搭建Swagger的主要内容,如果未能解决你的问题,请参考以下文章

使用docker搭建flink集群

使用rancher 搭建docker集群

Docker搭建与使用

Mac 使用docker搭建PHP环境

使用docker搭建STUN/TURN服务器

使用docker搭建redis集群