diff --git a/Domain/AggregateModel/LinkAggregate/Link.cs b/Domain/AggregateModel/LinkAggregate/Link.cs index d96533f..f261dd4 100644 --- a/Domain/AggregateModel/LinkAggregate/Link.cs +++ b/Domain/AggregateModel/LinkAggregate/Link.cs @@ -33,15 +33,14 @@ namespace Domain.AggregateModel.LinkAggregate /// /// /// 分配的应用id - public Link(string baseUrl,string suffixUrl,int appId) + public Link(string baseUrl,string suffixUrl,string fullUrl,int appId,string shortCode) { BaseUrl = baseUrl; SuffixUrl = suffixUrl; - FullUrl = new Uri(new Uri(baseUrl),suffixUrl).ToString(); + FullUrl = fullUrl; + ShortCode = shortCode; AppId = appId; Time = DateTime.Now; - CalculateShortCode(); - AddDomainEvent(new LinkCreatedDomainEvent(this)); } /// diff --git a/QRCodeService/Application/Commands/CreateLinkCommandHandler.cs b/QRCodeService/Application/Commands/CreateLinkCommandHandler.cs index 1a8da27..2cdde0f 100644 --- a/QRCodeService/Application/Commands/CreateLinkCommandHandler.cs +++ b/QRCodeService/Application/Commands/CreateLinkCommandHandler.cs @@ -3,6 +3,7 @@ using Domain.AggregateModel.LinkAggregate; using Domain.Exceptions; using MediatR; using Microsoft.Extensions.Logging; +using QRCodeService.Services; using System; using System.Collections.Generic; using System.Linq; @@ -17,10 +18,12 @@ namespace QRCodeService.Application.Commands readonly ILogger logger; readonly IAppRepository appRepository; + private readonly IShortCodeService shortCodeService; readonly ILinkRepository linkRepository; - public CreateLinkCommandHandler(ILinkRepository linkRepository, IAppRepository appRepository, ILogger logger) + public CreateLinkCommandHandler(IShortCodeService shortCodeService,ILinkRepository linkRepository, IAppRepository appRepository, ILogger logger) { + this.shortCodeService = shortCodeService; this.linkRepository = linkRepository; this.appRepository = appRepository; this.logger = logger; @@ -33,13 +36,15 @@ namespace QRCodeService.Application.Commands { throw new DomainException("app not found"); } - var link = new Link(app.BaseUrl, request.SuffixUrl, request.AppId); - var dbLink = await linkRepository.GetAsync(link.ShortCode); + var fullUrl = new Uri(new Uri(app.BaseUrl), request.SuffixUrl).ToString(); + var shortCode = await shortCodeService.GenShortCode(fullUrl); + var dbLink = await linkRepository.GetAsync(shortCode); if (dbLink != null) { logger.LogDebug("use exist link"); return dbLink; } + var link = new Link(app.BaseUrl, request.SuffixUrl,fullUrl, request.AppId, shortCode); link = linkRepository.Add(link); await linkRepository.UnitOfWork.SaveEntitiesAsync(); return link; diff --git a/QRCodeService/QRCodeService.csproj b/QRCodeService/QRCodeService.csproj index 30f3b49..d9d359b 100644 --- a/QRCodeService/QRCodeService.csproj +++ b/QRCodeService/QRCodeService.csproj @@ -51,10 +51,6 @@ - - - - diff --git a/QRCodeService/Services/IShortCodeService.cs b/QRCodeService/Services/IShortCodeService.cs new file mode 100644 index 0000000..3386377 --- /dev/null +++ b/QRCodeService/Services/IShortCodeService.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace QRCodeService.Services +{ + public interface IShortCodeService + { + Task GenShortCode(string url); + } +} diff --git a/QRCodeService/Services/ShortCodeService.cs b/QRCodeService/Services/ShortCodeService.cs new file mode 100644 index 0000000..61cbee4 --- /dev/null +++ b/QRCodeService/Services/ShortCodeService.cs @@ -0,0 +1,76 @@ +using Base62; +using Domain.AggregateModel.LinkAggregate; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using System.Threading.Tasks; + +namespace QRCodeService.Services +{ + public class ShortCodeService : IShortCodeService + { + private readonly ILinkRepository linkRepository; + + public ShortCodeService(ILinkRepository linkRepository) + { + this.linkRepository = linkRepository; + } + + public async Task GenShortCode(string url) + { + var full = 16; + var length = 4; + var idx = 0; + + while (true) + { + var code = CalculateShortCode(url, length, idx); + var link = await linkRepository.GetAsync(code); + if (link == null || link.FullUrl == url) + { + return code; + } + idx++; + if (idx * length == full) + { + idx = 0; + length = 2 * length; + } + } + + } + /// + /// 计算短链接 + /// + /// + /// 4(四分之一) 8(半) 16(全长) + /// + /// + private string CalculateShortCode(string url,int length,int index) + { + using (var md5 = MD5.Create()) + { + var result = md5.ComputeHash(Encoding.UTF8.GetBytes(url)); + if (length == 4) + { + return BitConverter.ToInt32(result, 4 * index).ToBase62(); + } + if(length == 8) + { + return BitConverter.ToInt32(result, 8 * index).ToBase62(); + } + if(length == 16) + { + return BitConverter.ToInt64(result, 0).ToBase62() + BitConverter.ToInt64(result, 8).ToBase62(); + } + if(length > 16) + { + return BitConverter.ToInt64(result, 0).ToBase62() + BitConverter.ToInt64(result, 8).ToBase62() + length.ToBase62(); + } + throw (new ArgumentOutOfRangeException()); + } + } + } +} diff --git a/QRCodeService/Startup.cs b/QRCodeService/Startup.cs index 650615e..d403f3a 100644 --- a/QRCodeService/Startup.cs +++ b/QRCodeService/Startup.cs @@ -24,6 +24,7 @@ using QRCodeService.Application.Queries; using QRCodeService.Application.Validations; using QRCodeService.Infrastructure.Middlewares; using QRCodeService.Options; +using QRCodeService.Services; using System; using System.Collections.Generic; using System.Linq; @@ -90,6 +91,8 @@ namespace QRCodeService options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto; }); + + services.AddTransient(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.