From f12b337fd0a9273cb982cbc09e3be43a4e078ffc Mon Sep 17 00:00:00 2001 From: zhengyiming <540361168@qq.com> Date: 星期五, 22 八月 2025 14:16:48 +0800 Subject: [PATCH] fix: s --- FlexJobApi.Core/Utils/ResourceUtils/ResourceUtils.cs | 208 +++++++++++++++++++++++---------------------------- 1 files changed, 93 insertions(+), 115 deletions(-) diff --git a/FlexJobApi.Core/Utils/ResourceUtils/ResourceUtils.cs b/FlexJobApi.Core/Utils/ResourceUtils/ResourceUtils.cs index 0bf57e6..1ec943a 100644 --- a/FlexJobApi.Core/Utils/ResourceUtils/ResourceUtils.cs +++ b/FlexJobApi.Core/Utils/ResourceUtils/ResourceUtils.cs @@ -6,6 +6,8 @@ using Furion.DynamicApiController; using Furion.FriendlyException; using Furion.HttpRemote; +using Furion.Logging; +using Furion.Logging.Extensions; using Mapster; using MediatR; using Microsoft.AspNetCore.Mvc; @@ -13,6 +15,7 @@ using Microsoft.AspNetCore.Mvc.Controllers; using Microsoft.AspNetCore.Routing; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.DependencyInjection; using System; using System.Collections.Generic; @@ -36,87 +39,6 @@ /// </summary> public static class ResourceUtils { - /// <summary> - /// 鍙戦�丠TTP璇锋眰 - /// </summary> - /// <typeparam name="TRequest"></typeparam> - /// <typeparam name="TResponse"></typeparam> - /// <param name="request"></param> - /// <returns></returns> - public static async Task<TResponse> SendHttpAsync<TRequest, TResponse>(TRequest request) - where TRequest : class, new() - { - var requestTypeFullName = typeof(TRequest).FullName; - var resource = await Db.GetRepository<Resource>().AsQueryable().AsNoTracking() - .Where(it => !it.IsExpired && it.RequestTypeFullName == requestTypeFullName) - .FirstOrDefaultAsync(); - var domain = await GetHealthyServiceDomain(resource); - var httpRemoteService = App.GetRequiredService<IHttpRemoteService>(); - var token = App.HttpContext.Request.Headers["Authorization"].ToString(); - var refreshToken = App.HttpContext.Request.Headers["X-Authorization"].ToString(); - TResponse response; - switch (resource.Method) - { - case EnumResourceMethod.Get: - response = await httpRemoteService.GetAsAsync<TResponse>( - $"{domain}{resource.Route}", - it => - it.WithQueryParameters(request) - .AddAuthentication(new AuthenticationHeaderValue("Authorization", token)) - .AddAuthentication(new AuthenticationHeaderValue("X-Authorization", refreshToken))); - break; - case EnumResourceMethod.Post: - response = await httpRemoteService.PostAsAsync<TResponse>( - $"{domain}{resource.Route}", - it => - it.SetJsonContent(request) - .WithHeader("Authorization", token) - .WithHeader("X-Authorization", refreshToken)); - break; - case EnumResourceMethod.Put: - response = await httpRemoteService.PutAsAsync<TResponse>( - $"{domain}{resource.Route}", - it => - it.SetJsonContent(request) - .AddAuthentication(new AuthenticationHeaderValue("Authorization", token)) - .AddAuthentication(new AuthenticationHeaderValue("X-Authorization", refreshToken))); - break; - case EnumResourceMethod.Delete: - response = await httpRemoteService.DeleteAsAsync<TResponse>( - $"{domain}{resource.Route}", - it => - it.SetJsonContent(request) - .AddAuthentication(new AuthenticationHeaderValue("Authorization", token)) - .AddAuthentication(new AuthenticationHeaderValue("X-Authorization", refreshToken))); - break; - default: - throw Oops.Oh(EnumErrorCodeType.s400, $"涓嶆敮鎸佽姹傛柟寮弡resource.Method}"); - } - return response; - } - - /// <summary> - /// 鑾峰彇鍋ュ悍鏈嶅姟鍩熷悕 - /// </summary> - /// <param name="resource"></param> - /// <returns></returns> - public static async Task<string> GetHealthyServiceDomain(Resource resource) - { - var client = App.GetRequiredService<IConsulClient>(); - var queryResult = await client.Health.Service(resource.ServiceName, null, true); - if (queryResult.StatusCode != System.Net.HttpStatusCode.OK) - throw Oops.Oh(EnumErrorCodeType.s404, $"寰湇鍔resource.Service}"); - - var domains = queryResult.Response - .Select(s => $"http://{s.Service.Address}:{s.Service.Port}") - .ToList(); - if (domains.IsNull()) - throw Oops.Oh(EnumErrorCodeType.s404, $"寰湇鍔resource.Service}"); - // 杞閫夋嫨瀹炰緥 - int randomIndex = new Random().Next(domains.Count); - return domains[randomIndex]; - } - /// <summary> /// 鐢熸垚鍔ㄦ�佹帶鍒跺櫒 /// </summary> @@ -149,16 +71,17 @@ var model = new ResourceModel(); model.TraceId = traceId; model.ApplicationName = resourceService.ApplicationName; - model.Controller = controller; + model.ControllerName = resourceController.ControllerName; model.ControllerSummary = resourceControllers.GetDescription(controller); model.ActionName = Regex.Replace(request.Name, @"(Command|Query)$", "", RegexOptions.None); model.ActionSummary = requestXmlDoc?.Summary; - model.Service = resourceController.Service; model.ServiceName = resourceService.ServiceName; model.RouteArea = resourceService.RouteArea; - model.Route = $"/api/{resourceService.RouteArea ?? "main"}/{controller}/{model.ActionName}"; + model.Route = $"/api/{resourceService.RouteArea ?? "main"}/{model.ControllerName}/{model.ActionName}"; model.Method = - request.BaseType?.IsGenericType == true && request.BaseType.GetGenericTypeDefinition() == typeof(PagedListQuery<,>) + resourceAttribute.Method != EnumResourceMethod.None + ? resourceAttribute.Method + : request.BaseType?.IsGenericType == true && request.BaseType.GetGenericTypeDefinition() == typeof(PagedListQuery<,>) ? EnumResourceMethod.Post : new List<string> { "Post", "Add", "Create", "Insert", "Submit" }.Any(it => request.Name.StartsWith(it, StringComparison.OrdinalIgnoreCase)) ? EnumResourceMethod.Post @@ -169,6 +92,7 @@ : new List<string> { "Delete", "Remove ", "Clear" }.Any(it => request.Name.StartsWith(it, StringComparison.OrdinalIgnoreCase)) ? EnumResourceMethod.Delete : EnumResourceMethod.Post; + model.FileUpload = resourceAttribute.FileUpload; model.Code = requestXmlDoc?.Name; model.Name = $"{model.ControllerSummary}-{model.ActionSummary}"; model.AllowAnonymous = resourceAttribute.AllowAnonymous; @@ -181,13 +105,13 @@ model.ResponseTypeName = responseType.GetCSharpFriendlyName(); model.ResponseTypeFullName = responseType.FullName; } - - models.Add(model); + + await App.GetRequiredService<IDistributedCache>().SetStringAsync($"ResourceModel|{model.RequestTypeFullName}", model.ToJson()); } } - var resources = await SaveResourcesAsync(models, traceId, rep); + var resources = await SaveResourcesAsync(models, rep); DynamicControllersHotPlug(resources, provider); @@ -201,7 +125,7 @@ /// <param name="traceId"></param> /// <param name="rep"></param> /// <returns></returns> - private static async Task<List<Resource>> SaveResourcesAsync(List<ResourceModel> models, string traceId, IRepository<Resource> rep = null) + private static async Task<List<Resource>> SaveResourcesAsync(List<ResourceModel> models, IRepository<Resource> rep = null) { rep = rep ?? Db.GetRepository<Resource>(); var resources = await rep.AsQueryable() @@ -213,22 +137,32 @@ if (resource == null) { resource = new Resource(); + resource.Id = IDGen.NextID(); + resource.CreatedTime = DateTimeOffset.Now; model.Adapt(resource); await rep.InsertAsync(resource); resources.Add(resource); } else { - model.Adapt(resource); - await rep.UpdateAsync(resource); + var resourceBakModel = new ResourceModel(); + resource.Adapt(resourceBakModel); + resourceBakModel.TraceId = model.TraceId; + resourceBakModel.DynamicAssemblyName = model.DynamicAssemblyName; + if (resourceBakModel.ToJson() != model.ToJson()) + { + model.Adapt(resource); + resource.UpdatedTime = DateTimeOffset.Now; + await rep.UpdateAsync(resource); + } } } - var expiredResources = resources.Where(it => it.TraceId != traceId).ToList(); + var expiredResources = resources.Where(it => !models.Any(m => m.Route == it.Route && m.Method == it.Method)).ToList(); foreach (var expiredResource in expiredResources) { - expiredResource.IsExpired = true; - await rep.UpdateAsync(expiredResource); + resources.Remove(expiredResource); + await rep.DeleteAsync(expiredResource); } return resources.Where(it => !it.IsExpired).ToList(); @@ -242,7 +176,21 @@ public static void DynamicControllersHotPlug(List<Resource> resources, IDynamicApiRuntimeChangeProvider provider = null) { provider = provider ?? App.GetRequiredService<IDynamicApiRuntimeChangeProvider>(); - foreach (var resource in resources) + var controllers = resources + .GroupBy(it => new + { + it.ApplicationName, + it.ControllerName, + it.ControllerSummary, + it.RouteArea + }) + .Select(it => new + { + it.Key, + Actions = it.ToList() + }) + .ToList(); + foreach (var controller in controllers) { var code = $@" using FlexJobApi.Core; @@ -256,40 +204,70 @@ using System.Collections.Generic; using System.ComponentModel; -namespace {resource.ApplicationName}.{resource.Controller}.{resource.ActionName}Request + +namespace {controller.Key.ApplicationName}.{controller.Key.ControllerName} {{ /// <summary> - /// {resource.ControllerSummary} + /// {controller.Key.ControllerSummary} /// </summary> - [Route(""api/{resource.RouteArea}/[controller]"")] - public class {resource.Controller}AppService(IMediator mediator) : IDynamicApiController + [Route(""api/{controller.Key.RouteArea}/[controller]"")] + public class {controller.Key.ControllerName}AppService(IMediator mediator) : IDynamicApiController {{ - private readonly IMediator mediator = mediator; + private readonly IMediator mediator = mediator;"; + + foreach (var action in controller.Actions) + { + var result = action.ResponseTypeName.IsNull() ? "Task" : $"Task<{action.ResponseTypeName}>"; + code += @$" /// <summary> - /// {resource.ActionSummary} + /// {action.ActionSummary} /// </summary> /// <param name=""request""></param> /// <returns></returns>"; - if (resource.AllowAnonymous) - { - code += $@" + if (action.AllowAnonymous) + { + code += $@" [AllowAnonymous]"; - } - code += $@" - [Http{resource.Method}] - public Task<{resource.ResponseTypeName}> {resource.ActionName}({resource.RequestTypeName} request) + } + code += $@" + [Http{action.Method}]"; + if (action.FileUpload) + { + code += @" + [Consumes(""multipart/form-data"")]"; + } + code += @$" + public {result} {action.ActionName}("; + if (action.FileUpload) + { + code += "[FromForm] "; + } + code += $@"{action.RequestTypeName} request) {{ return mediator.Send(request); - }} + }}"; + } - }} -}} + code += @" + } +} "; - var dynamicAssembly = App.CompileCSharpClassCode(code); - provider.AddAssembliesWithNotifyChanges(dynamicAssembly); - var dynamicAssemblyName = dynamicAssembly.GetName().Name; - resource.DynamicAssemblyName = dynamicAssemblyName; + try + { + var dynamicAssembly = App.CompileCSharpClassCode(code); + provider.AddAssembliesWithNotifyChanges(dynamicAssembly); + var dynamicAssemblyName = dynamicAssembly.GetName().Name; + foreach (var action in controller.Actions) + { + action.DynamicAssemblyName = dynamicAssemblyName; + } + } + catch (Exception ex) + { + code.LogError(ex); + throw; + } } } -- Gitblit v1.9.1