网站中转页,手机触屏版网站管理系统,爱站工具包的主要功能,怎样建设商城网站系列文章使用 abp cli 搭建项目给项目瘦身#xff0c;让它跑起来完善与美化#xff0c;Swagger登场数据访问和代码优先自定义仓储之增删改查统一规范API#xff0c;包装返回模型再说Swagger#xff0c;分组、描述、小绿锁接入GitHub#xff0c;用JWT保护你的API异常处理和… 系列文章使用 abp cli 搭建项目给项目瘦身让它跑起来完善与美化Swagger登场数据访问和代码优先自定义仓储之增删改查统一规范API包装返回模型再说Swagger分组、描述、小绿锁接入GitHub用JWT保护你的API异常处理和日志记录使用Redis缓存数据集成Hangfire实现定时任务处理用AutoMapper搞定对象映射定时任务最佳实战一定时任务最佳实战二定时任务最佳实战三准备工作现在博客数据库中的数据是比较混乱的为了看起来像那么回事显得正式一点我先手动搞点数据进去。搞定了种子数据就可以去愉快的写接口了我这里将根据我现在的博客页面去分析所需要接口感兴趣的去点点。为了让接口看起来清晰一目了然删掉之前在IBlogService中添加的所有接口将5个自定义仓储全部添加至BlogService中然后用partial修饰。//IBlogService.cs
public partial interface IBlogService
{
}//BlogService.cs
using Meowv.Blog.Application.Caching.Blog;
using Meowv.Blog.Domain.Blog.Repositories;namespace Meowv.Blog.Application.Blog.Impl
{public partial class BlogService : ServiceBase, IBlogService{private readonly IBlogCacheService _blogCacheService;private readonly IPostRepository _postRepository;private readonly ICategoryRepository _categoryRepository;private readonly ITagRepository _tagRepository;private readonly IPostTagRepository _postTagRepository;private readonly IFriendLinkRepository _friendLinksRepository;public BlogService(IBlogCacheService blogCacheService,IPostRepository postRepository,ICategoryRepository categoryRepository,ITagRepository tagRepository,IPostTagRepository postTagRepository,IFriendLinkRepository friendLinksRepository){_blogCacheService blogCacheService;_postRepository postRepository;_categoryRepository categoryRepository;_tagRepository tagRepository;_postTagRepository postTagRepository;_friendLinksRepository friendLinksRepository;}}
}
在Blog文件夹下依次添加接口IBlogService.Post.cs、IBlogService.Category.cs、IBlogService.Tag.cs、IBlogService.FriendLink.cs、IBlogService.Admin.cs。在Blog/Impl文件夹下添加实现类IBlogService.Post.cs、BlogService.Category.cs、BlogService.Tag.cs、BlogService.FriendLink.cs、BlogService.Admin.cs。同上.Application.Caching层也按照这个样子添加。注意都需要添加partial修饰为局部的接口和实现类所有文章相关的接口放在IBlogService.Post.cs中分类放在IBlogService.Category.cs标签放在IBlogService.Tag.cs友链放在IBlogService.FriendLink.cs后台增删改所有接口放在IBlogService.Admin.cs最终效果图如下文章列表页分析列表带分页以文章发表的年份分组所需字段标题、链接、时间、年份。在.Application.Contracts层Blog文件夹下添加返回的模型QueryPostDto.cs。//QueryPostDto.cs
using System.Collections.Generic;namespace Meowv.Blog.Application.Contracts.Blog
{public class QueryPostDto{/// summary/// 年份/// /summarypublic int Year { get; set; }/// summary/// Posts/// /summarypublic IEnumerablePostBriefDto Posts { get; set; }}
}
模型为一个年份和一个文章列表文章列表模型PostBriefDto.cs。//PostBriefDto.cs
namespace Meowv.Blog.Application.Contracts.Blog
{public class PostBriefDto{/// summary/// 标题/// /summarypublic string Title { get; set; }/// summary/// 链接/// /summarypublic string Url { get; set; }/// summary/// 年份/// /summarypublic int Year { get; set; }/// summary/// 创建时间/// /summarypublic string CreationTime { get; set; }}
}
搞定因为返回时间为英文格式所以CreationTime给了字符串类型。在IBlogService.Post.cs中添加接口分页查询文章列表QueryPostsAsync肯定需要接受俩参数分页页码和分页数量。还是去添加一个公共模型PagingInput吧在.Application.Contracts下面。//PagingInput.cs
using System.ComponentModel.DataAnnotations;namespace Meowv.Blog.Application.Contracts
{/// summary/// 分页输入参数/// /summarypublic class PagingInput{/// summary/// 页码/// /summary[Range(1, int.MaxValue)]public int Page { get; set; } 1;/// summary/// 限制条数/// /summary[Range(10, 30)]public int Limit { get; set; } 10;}
}
Page设置默认值为1Limit设置默认值为10Range Attribute设置参数可输入大小限制于是这个分页查询文章列表的接口就是这个样子的。//IBlogService.Post.cs
public partial interface IBlogService
{/// summary/// 分页查询文章列表/// /summary/// param nameinput/param/// returns/returnsTaskServiceResultPagedListQueryPostDto QueryPostsAsync(PagingInput input);
}
ServiceResult和PagedList是之前添加的统一返回模型紧接着就去添加一个分页查询文章列表缓存接口和上面是对应的。//IBlogCacheService.Post.cs
using Meowv.Blog.Application.Contracts;
using Meowv.Blog.Application.Contracts.Blog;
using Meowv.Blog.ToolKits.Base;
using System;
using System.Threading.Tasks;namespace Meowv.Blog.Application.Caching.Blog
{public partial interface IBlogCacheService{/// summary/// 分页查询文章列表/// /summary/// param nameinput/param/// param namefactory/param/// returns/returnsTaskServiceResultPagedListQueryPostDto QueryPostsAsync(PagingInput input, FuncTaskServiceResultPagedListQueryPostDto factory);}
}
分别实现这两个接口。//BlogCacheService.Post.cs
public partial class BlogCacheService
{private const string KEY_QueryPosts Blog:Post:QueryPosts-{0}-{1};/// summary/// 分页查询文章列表/// /summary/// param nameinput/param/// param namefactory/param/// returns/returnspublic async TaskServiceResultPagedListQueryPostDto QueryPostsAsync(PagingInput input, FuncTaskServiceResultPagedListQueryPostDto factory){return await Cache.GetOrAddAsync(KEY_QueryPosts.FormatWith(input.Page, input.Limit), factory, CacheStrategy.ONE_DAY);}
}
//BlogService.Post.cs
/// summary
/// 分页查询文章列表
/// /summary
/// param nameinput/param
/// returns/returns
public async TaskServiceResultPagedListQueryPostDto QueryPostsAsync(PagingInput input)
{return await _blogCacheService.QueryPostsAsync(input, async () {var result new ServiceResultPagedListQueryPostDto();var count await _postRepository.GetCountAsync();var list _postRepository.OrderByDescending(x x.CreationTime).PageByIndex(input.Page, input.Limit).Select(x new PostBriefDto{Title x.Title,Url x.Url,Year x.CreationTime.Year,CreationTime x.CreationTime.TryToDateTime()}).GroupBy(x x.Year).Select(x new QueryPostDto{Year x.Key,Posts x.ToList()}).ToList();result.IsSuccess(new PagedListQueryPostDto(count.TryToInt(), list));return result;});
}
PageByIndex(...)、TryToDateTime()是.ToolKits层添加的扩展方法先查询总数然后根据时间倒序分页筛选出所需字段根据年份分组输出结束。在BlogController中添加API。/// summary
/// 分页查询文章列表
/// /summary
/// param nameinput/param
/// returns/returns
[HttpGet]
[Route(posts)]
public async TaskServiceResultPagedListQueryPostDto QueryPostsAsync([FromQuery] PagingInput input)
{return await _blogService.QueryPostsAsync(input);
}
[FromQuery]设置input为从URL进行查询参数编译运行看效果。已经可以查询出数据并且缓存至Redis中。获取文章详情分析文章详情页文章的标题、作者、发布时间、所属分类、标签列表、文章内容(HTML和MarkDown)、链接、上下篇的标题和链接。创建返回模型PostDetailDto.cs//PostDetailDto.cs
using System.Collections.Generic;namespace Meowv.Blog.Application.Contracts.Blog
{public class PostDetailDto{/// summary/// 标题/// /summarypublic string Title { get; set; }/// summary/// 作者/// /summarypublic string Author { get; set; }/// summary/// 链接/// /summarypublic string Url { get; set; }/// summary/// HTML/// /summarypublic string Html { get; set; }/// summary/// Markdown/// /summarypublic string Markdown { get; set; }/// summary/// 创建时间/// /summarypublic string CreationTime { get; set; }/// summary/// 分类/// /summarypublic CategoryDto Category { get; set; }/// summary/// 标签列表/// /summarypublic IEnumerableTagDto Tags { get; set; }/// summary/// 上一篇/// /summarypublic PostForPagedDto Previous { get; set; }/// summary/// 下一篇/// /summarypublic PostForPagedDto Next { get; set; }}
}
同时添加CategoryDto、TagDto、PostForPagedDto。//CategoryDto.cs
namespace Meowv.Blog.Application.Contracts.Blog
{public class CategoryDto{/// summary/// 分类名称/// /summarypublic string CategoryName { get; set; }/// summary/// 展示名称/// /summarypublic string DisplayName { get; set; }}
}//TagDto.cs
namespace Meowv.Blog.Application.Contracts.Blog
{public class TagDto{/// summary/// 标签名称/// /summarypublic string TagName { get; set; }/// summary/// 展示名称/// /summarypublic string DisplayName { get; set; }}
}//PostForPagedDto.cs
namespace Meowv.Blog.Application.Contracts.Blog
{public class PostForPagedDto{/// summary/// 标题/// /summarypublic string Title { get; set; }/// summary/// 链接/// /summarypublic string Url { get; set; }}
}
添加获取文章详情接口和缓存的接口。//IBlogService.Post.cs
public partial interface IBlogService
{/// summary/// 根据URL获取文章详情/// /summary/// param nameurl/param/// returns/returnsTaskServiceResultPostDetailDto GetPostDetailAsync(string url);
}
//IBlogCacheService.Post.cs
public partial interface IBlogCacheService
{/// summary/// 根据URL获取文章详情/// /summary/// param nameurl/param/// returns/returnsTaskServiceResultPostDetailDto GetPostDetailAsync(string url, FuncTaskServiceResultPostDetailDto factory);
}
分别实现这两个接口。//BlogCacheService.Post.cs
public partial class BlogCacheService
{private const string KEY_GetPostDetail Blog:Post:GetPostDetail-{0};/// summary/// 根据URL获取文章详情/// /summary/// param nameurl/param/// param namefactory/param/// returns/returnspublic async TaskServiceResultPostDetailDto GetPostDetailAsync(string url, FuncTaskServiceResultPostDetailDto factory){return await Cache.GetOrAddAsync(KEY_GetPostDetail.FormatWith(url), factory, CacheStrategy.ONE_DAY);}
}
//BlogService.Post.cs
/// summary
/// 根据URL获取文章详情
/// /summary
/// param nameurl/param
/// returns/returns
public async TaskServiceResultPostDetailDto GetPostDetailAsync(string url)
{return await _blogCacheService.GetPostDetailAsync(url, async () {var result new ServiceResultPostDetailDto();var post await _postRepository.FindAsync(x x.Url.Equals(url));if (null post){result.IsFailed(ResponseText.WHAT_NOT_EXIST.FormatWith(URL, url));return result;}var category await _categoryRepository.GetAsync(post.CategoryId);var tags from post_tags in await _postTagRepository.GetListAsync()join tag in await _tagRepository.GetListAsync()on post_tags.TagId equals tag.Idwhere post_tags.PostId.Equals(post.Id)select new TagDto{TagName tag.TagName,DisplayName tag.DisplayName};var previous _postRepository.Where(x x.CreationTime post.CreationTime).Take(1).FirstOrDefault();var next _postRepository.Where(x x.CreationTime post.CreationTime).OrderByDescending(x x.CreationTime).Take(1).FirstOrDefault();var postDetail new PostDetailDto{Title post.Title,Author post.Author,Url post.Url,Html post.Html,Markdown post.Markdown,CreationTime post.CreationTime.TryToDateTime(),Category new CategoryDto{CategoryName category.CategoryName,DisplayName category.DisplayName},Tags tags,Previous previous null ? null : new PostForPagedDto{Title previous.Title,Url previous.Url},Next next null ? null : new PostForPagedDto{Title next.Title,Url next.Url}};result.IsSuccess(postDetail);return result;});
}
ResponseText.WHAT_NOT_EXIST是定义在MeowvBlogConsts.cs的常量。TryToDateTime()和列表查询中的扩展方法一样转换时间为想要的格式。简单说一下查询逻辑先根据参数url查询是否存在数据如果文章不存在则返回错误消息。然后根据 post.CategoryId 就可以查询到当前文章的分类名称。联合查询post_tags和tag两张表指定查询条件post.Id查询当前文章的所有标签。最后上下篇的逻辑也很简单上一篇取大于当前文章发布时间的第一篇下一篇取时间倒序排序并且小于当前文章发布时间的第一篇文章。最后将所有查询到的数据赋值给输出对象返回结束。在BlogController中添加API。 /// summary/// 根据URL获取文章详情/// /summary/// param nameurl/param/// returns/returns[HttpGet][Route(post)]public async TaskServiceResultPostDetailDto GetPostDetailAsync(string url){return await _blogService.GetPostDetailAsync(url);}
编译运行然后输入URL查询一条文章详情数据。成功输出预期内容缓存同时也是ok的。开源地址https://github.com/Meowv/Blog/tree/blog_tutorial