基於 abp vNext 和 .NET Core 開發部落格專案 - 部落格介面實戰篇(四)

阿星Plus發表於2020-06-06

系列文章

  1. 基於 abp vNext 和 .NET Core 開發部落格專案 - 使用 abp cli 搭建專案
  2. 基於 abp vNext 和 .NET Core 開發部落格專案 - 給專案瘦身,讓它跑起來
  3. 基於 abp vNext 和 .NET Core 開發部落格專案 - 完善與美化,Swagger登場
  4. 基於 abp vNext 和 .NET Core 開發部落格專案 - 資料訪問和程式碼優先
  5. 基於 abp vNext 和 .NET Core 開發部落格專案 - 自定義倉儲之增刪改查
  6. 基於 abp vNext 和 .NET Core 開發部落格專案 - 統一規範API,包裝返回模型
  7. 基於 abp vNext 和 .NET Core 開發部落格專案 - 再說Swagger,分組、描述、小綠鎖
  8. 基於 abp vNext 和 .NET Core 開發部落格專案 - 接入GitHub,用JWT保護你的API
  9. 基於 abp vNext 和 .NET Core 開發部落格專案 - 異常處理和日誌記錄
  10. 基於 abp vNext 和 .NET Core 開發部落格專案 - 使用Redis快取資料
  11. 基於 abp vNext 和 .NET Core 開發部落格專案 - 整合Hangfire實現定時任務處理
  12. 基於 abp vNext 和 .NET Core 開發部落格專案 - 用AutoMapper搞定物件對映
  13. 基於 abp vNext 和 .NET Core 開發部落格專案 - 定時任務最佳實戰(一)
  14. 基於 abp vNext 和 .NET Core 開發部落格專案 - 定時任務最佳實戰(二)
  15. 基於 abp vNext 和 .NET Core 開發部落格專案 - 定時任務最佳實戰(三)
  16. 基於 abp vNext 和 .NET Core 開發部落格專案 - 部落格介面實戰篇(一)
  17. 基於 abp vNext 和 .NET Core 開發部落格專案 - 部落格介面實戰篇(二)
  18. 基於 abp vNext 和 .NET Core 開發部落格專案 - 部落格介面實戰篇(三)

上篇文章完成了文章增刪改的介面和友情連結列表的介面,本篇繼續。

善於思考的同學肯定發現,在執行增刪改操作後,Redis快取中的資料還是存在的,也就意味著查詢介面返回的資料還是舊的,所以在寫介面之前,先完成一下清快取的操作。

移除快取

移除快取我這裡找了一個新的包:Caching.CSRedis,選他是因為微軟的包Microsoft.Extensions.Caching.StackExchangeRedis沒有給我們實現批量刪除的功能。

Caching.CSRedis開源地址,https://github.com/2881099/csredis 在這不做過多介紹,感興趣的自己去看。

.Application.Caching層新增包Caching.CSRedisInstall-Package Caching.CSRedis,然後在模組類MeowvBlogApplicationCachingModule中進行配置。

//MeowvBlogApplicationCachingModule.cs
...
public override void ConfigureServices(ServiceConfigurationContext context)
{
    ...

    var csredis = new CSRedis.CSRedisClient(AppSettings.Caching.RedisConnectionString);
    RedisHelper.Initialization(csredis);

    context.Services.AddSingleton<IDistributedCache>(new CSRedisCache(RedisHelper.Instance));
}
...

直接新建一個移除快取的介面:ICacheRemoveService,新增移除快取的方法RemoveAsync()。程式碼較少,可以直接寫在快取基類CachingServiceBase中。

public interface ICacheRemoveService
{
    /// <summary>
    /// 移除快取
    /// </summary>
    /// <param name="key"></param>
    /// <param name="cursor"></param>
    /// <returns></returns>
    Task RemoveAsync(string key, int cursor = 0);
}

然後可以在基類中實現這個介面。

public async Task RemoveAsync(string key, int cursor = 0)
{
    var scan = await RedisHelper.ScanAsync(cursor);
    var keys = scan.Items;

    if (keys.Any() && key.IsNotNullOrEmpty())
    {
        keys = keys.Where(x => x.StartsWith(key)).ToArray();

        await RedisHelper.DelAsync(keys);
    }
}

簡單說一下這個操作過程,使用ScanAsync()獲取到所有的Redis key值,返回的是一個string陣列,然後根據引數找到符合此字首的所有key,最後呼叫DelAsync(keys)刪除快取。

在需要有移除快取功能的介面上繼承ICacheRemoveService,這裡就是IBlogCacheService

//IBlogCacheService.cs
namespace Meowv.Blog.Application.Caching.Blog
{
    public partial interface IBlogCacheService : ICacheRemoveService
    {
    }
}

在基類中已經實現了這個介面,所以現在所有基層基類的快取實現類都可以呼叫移除快取方法了。

MeowvBlogConsts中新增快取字首的常量。

//MeowvBlogConsts.cs
/// <summary>
/// 快取字首
/// </summary>
public static class CachePrefix
{
    public const string Authorize = "Authorize";

    public const string Blog = "Blog";

    public const string Blog_Post = Blog + ":Post";

    public const string Blog_Tag = Blog + ":Tag";

    public const string Blog_Category = Blog + ":Category";

    public const string Blog_FriendLink = Blog + ":FriendLink";
}

然後在BlogService.Admin.cs服務執行增刪改後呼叫移除快取的方法。

//BlogService.Admin.cs

// 執行清除快取操作
await _blogCacheService.RemoveAsync(CachePrefix.Blog_Post);

因為是小專案,採用這種策略直接刪除快取,這樣就搞定了當在執行增刪改操作後,前臺介面可以實時查詢出最後的結果。

文章詳情

1

當我們修改文章資料的時候,是需要把當前資料庫中的資料帶出來顯示在介面上的,因為有可能只是個別地方需要修改,所以這還需要一個查詢文章詳情的介面,當然這裡的詳情和前端的是不一樣的,這裡是需要根據Id主鍵去查詢。

新增模型類PostForAdminDto.cs,直接繼承PostDto,然後新增一個Tags列表就行,==,好像和上一篇文章中的EditPostInput欄位是一模一樣的。順手將EditPostInput改一下吧,具體程式碼如下:

//PostForAdminDto.cs
using System.Collections.Generic;

namespace Meowv.Blog.Application.Contracts.Blog
{
    public class PostForAdminDto : PostDto
    {
        /// <summary>
        /// 標籤列表
        /// </summary>
        public IEnumerable<string> Tags { get; set; }
    }
}

//EditPostInput.cs
namespace Meowv.Blog.Application.Contracts.Blog.Params
{
    public class EditPostInput : PostForAdminDto
    {
    }
}

IBlogService.Admin.cs中新增介面。

/// <summary>
/// 獲取文章詳情
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
Task<ServiceResult<PostForAdminDto>> GetPostForAdminAsync(int id);

實現這個介面。

/// <summary>
/// 獲取文章詳情
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public async Task<ServiceResult<PostForAdminDto>> GetPostForAdminAsync(int id)
{
    var result = new ServiceResult<PostForAdminDto>();

    var post = await _postRepository.GetAsync(id);

    var tags = from post_tags in await _postTagRepository.GetListAsync()
               join tag in await _tagRepository.GetListAsync()
               on post_tags.TagId equals tag.Id
               where post_tags.PostId.Equals(post.Id)
               select tag.TagName;

    var detail = ObjectMapper.Map<Post, PostForAdminDto>(post);
    detail.Tags = tags;
    detail.Url = post.Url.Split("/").Where(x => !string.IsNullOrEmpty(x)).Last();

    result.IsSuccess(detail);
    return result;
}

先根據Id查出文章資料,再通過聯合查詢找出標籤資料。

CreateMap<Post, PostForAdminDto>().ForMember(x => x.Tags, opt => opt.Ignore());

新建一條AutoMapper配置,將Post轉換成PostForAdminDto,忽略Tags。

然後將查出來的標籤、Url賦值給DTO,輸出即可。在BlogController.Admin中新增API。

/// <summary>
/// 獲取文章詳情
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[HttpGet]
[Authorize]
[Route("admin/post")]
[ApiExplorerSettings(GroupName = Grouping.GroupName_v2)]
public async Task<ServiceResult<PostForAdminDto>> GetPostForAdminAsync([Required] int id)
{
    return await _blogService.GetPostForAdminAsync(id);
}

2

至此,完成了關於文章的所有介面。

接下來按照以上方式依次完成分類、標籤、友鏈的增刪改查介面,我覺得如果你有跟著我一起做,剩下的可以自己完成。

開源地址:https://github.com/Meowv/Blog/tree/blog_tutorial


搭配下方課程學習更佳 ↓ ↓ ↓

http://gk.link/a/10iQ7

3

相關文章