基于 abp vNext 和 .NET Core 开发博客项目 - 博客接口实战篇(二)
系列文章
- 基于 abp vNext 和 .NET Core 开发博客项目 - 使用 abp cli 搭建项目
- 基于 abp vNext 和 .NET Core 开发博客项目 - 给项目瘦身,让它跑起来
- 基于 abp vNext 和 .NET Core 开发博客项目 - 完善与美化,Swagger登场
- 基于 abp vNext 和 .NET Core 开发博客项目 - 数据访问和代码优先
- 基于 abp vNext 和 .NET Core 开发博客项目 - 自定义仓储之增删改查
- 基于 abp vNext 和 .NET Core 开发博客项目 - 统一规范API,包装返回模型
- 基于 abp vNext 和 .NET Core 开发博客项目 - 再说Swagger,分组、描述、小绿锁
- 基于 abp vNext 和 .NET Core 开发博客项目 - 接入GitHub,用JWT保护你的API
- 基于 abp vNext 和 .NET Core 开发博客项目 - 异常处理和日志记录
- 基于 abp vNext 和 .NET Core 开发博客项目 - 使用Redis缓存数据
- 基于 abp vNext 和 .NET Core 开发博客项目 - 集成Hangfire实现定时任务处理
- 基于 abp vNext 和 .NET Core 开发博客项目 - 用AutoMapper搞定对象映射
- 基于 abp vNext 和 .NET Core 开发博客项目 - 定时任务最佳实战(一)
- 基于 abp vNext 和 .NET Core 开发博客项目 - 定时任务最佳实战(二)
- 基于 abp vNext 和 .NET Core 开发博客项目 - 定时任务最佳实战(三)
- 基于 abp vNext 和 .NET Core 开发博客项目 - 博客接口实战篇(一)
上篇文章完成了两个接口:文章列表页、文章详情页,本篇继续。
分类列表

分析:这里多了一个统计文章数量的字段,可以直接新建一个模型QueryCategoryDto.cs继承CategoryDto。
//QueryCategoryDto.cs
namespace Meowv.Blog.Application.Contracts.Blog
{
public class QueryCategoryDto : CategoryDto
{
/// <summary>
/// 总数
/// </summary>
public int Count { get; set; }
}
}
添加查询分类列表接口和缓存接口。
//IBlogService.Category.cs
using Meowv.Blog.Application.Contracts.Blog;
using Meowv.Blog.ToolKits.Base;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Meowv.Blog.Application.Blog
{
public partial interface IBlogService
{
/// <summary>
/// 查询分类列表
/// </summary>
/// <returns></returns>
Task<ServiceResult<IEnumerable<QueryCategoryDto>>> QueryCategoriesAsync();
}
}
//IBlogCacheService.Category.cs
using Meowv.Blog.Application.Contracts.Blog;
using Meowv.Blog.ToolKits.Base;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Meowv.Blog.Application.Caching.Blog
{
public partial interface IBlogCacheService
{
/// <summary>
/// 查询分类列表
/// </summary>
/// <param name="factory"></param>
/// <returns></returns>
Task<ServiceResult<IEnumerable<QueryCategoryDto>>> QueryCategoriesAsync(Func<Task<ServiceResult<IEnumerable<QueryCategoryDto>>>> factory);
}
}
分别实现这两个接口。
//BlogCacheService.Category.cs
using Meowv.Blog.Application.Contracts.Blog;
using Meowv.Blog.ToolKits.Base;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using static Meowv.Blog.Domain.Shared.MeowvBlogConsts;
namespace Meowv.Blog.Application.Caching.Blog.Impl
{
public partial class BlogCacheService
{
private const string KEY_QueryCategories = "Blog:Category:QueryCategories";
/// <summary>
/// 查询分类列表
/// </summary>
/// <param name="factory"></param>
/// <returns></returns>
public async Task<ServiceResult<IEnumerable<QueryCategoryDto>>> QueryCategoriesAsync(Func<Task<ServiceResult<IEnumerable<QueryCategoryDto>>>> factory)
{
return await Cache.GetOrAddAsync(KEY_QueryCategories, factory, CacheStrategy.ONE_DAY);
}
}
}
//BlogService.Category.cs
using Meowv.Blog.Application.Contracts.Blog;
using Meowv.Blog.ToolKits.Base;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Meowv.Blog.Application.Blog.Impl
{
public partial class BlogService
{
/// <summary>
/// 查询分类列表
/// </summary>
/// <returns></returns>
public async Task<ServiceResult<IEnumerable<QueryCategoryDto>>> QueryCategoriesAsync()
{
return await _blogCacheService.QueryCategoriesAsync(async () =>
{
var result = new ServiceResult<IEnumerable<QueryCategoryDto>>();
var list = from category in await _categoryRepository.GetListAsync()
join posts in await _postRepository.GetListAsync()
on category.Id equals posts.CategoryId
group category by new
{
category.CategoryName,
category.DisplayName
} into g
select new QueryCategoryDto
{
CategoryName = g.Key.CategoryName,
DisplayName = g.Key.DisplayName,
Count = g.Count()
};
result.IsSuccess(list);
return result;
});
}
}
}
缓存就不说了,查询分类列表,联合查询文章和分类两张表,关联字段为CategoryId,然后分组,计算出对应的数量,在BlogController中添加API。
/// <summary>
/// 查询分类列表
/// </summary>
/// <returns></returns>
[HttpGet]
[Route("categories")]
public async Task<ServiceResult<IEnumerable<QueryCategoryDto>>> QueryCategoriesAsync()
{
return await _blogService.QueryCategoriesAsync();
}

标签列表

分析:和分类列表差不多,新建模型QueryTagDto.cs继承TagDto。
//QueryTagDto.cs
namespace Meowv.Blog.Application.Contracts.Blog
{
public class QueryTagDto : TagDto
{
/// <summary>
/// 总数
/// </summary>
public int Count { get; set; }
}
}
添加查询标签列表接口和缓存接口。
//IBlogCacheService.Tag.cs
using Meowv.Blog.Application.Contracts.Blog;
using Meowv.Blog.ToolKits.Base;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Meowv.Blog.Application.Caching.Blog
{
public partial interface IBlogCacheService
{
/// <summary>
/// 查询标签列表
/// </summary>
/// <param name="factory"></param>
/// <returns></returns>
Task<ServiceResult<IEnumerable<QueryTagDto>>> QueryTagsAsync(Func<Task<ServiceResult<IEnumerable<QueryTagDto>>>> factory);
}
}
//IBlogService.Tag.cs
using Meowv.Blog.Application.Contracts.Blog;
using Meowv.Blog.ToolKits.Base;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Meowv.Blog.Application.Blog
{
public partial interface IBlogService
{
/// <summary>
/// 查询标签列表
/// </summary>
/// <returns></returns>
Task<ServiceResult<IEnumerable<QueryTagDto>>> QueryTagsAsync();
}
}
分别实现这两个接口。
//BlogCacheService.Tag.cs
using Meowv.Blog.Application.Contracts.Blog;
using Meowv.Blog.ToolKits.Base;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using static Meowv.Blog.Domain.Shared.MeowvBlogConsts;
namespace Meowv.Blog.Application.Caching.Blog.Impl
{
public partial class BlogCacheService
{
private const string KEY_QueryTags = "Blog:Tag:QueryTags";
/// <summary>
/// 查询标签列表
/// </summary>
/// <param name="factory"></param>
/// <returns></returns>
public async Task<ServiceResult<IEnumerable<QueryTagDto>>> QueryTagsAsync(Func<Task<ServiceResult<IEnumerable<QueryTagDto>>>> factory)
{
return await Cache.GetOrAddAsync(KEY_QueryTags, factory, CacheStrategy.ONE_DAY);
}
}
}
//BlogService.Tag.cs
using Meowv.Blog.Application.Contracts.Blog;
using Meowv.Blog.ToolKits.Base;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Meowv.Blog.Application.Blog.Impl
{
public partial class BlogService
{
/// <summary>
/// 查询标签列表
/// </summary>
/// <returns></returns>
public async Task<ServiceResult<IEnumerable<QueryTagDto>>> QueryTagsAsync()
{
return await _blogCacheService.QueryTagsAsync(async () =>
{
var result = new ServiceResult<IEnumerable<QueryTagDto>>();
var list = from tags in await _tagRepository.GetListAsync()
join post_tags in await _postTagRepository.GetListAsync()
on tags.Id equals post_tags.TagId
group tags by new
{
tags.TagName,
tags.DisplayName
} into g
select new QueryTagDto
{
TagName = g.Key.TagName,
DisplayName = g.Key.DisplayName,
Count = g.Count()
};
result.IsSuccess(list);
return result;
});
}
}
}
查询标签列表需要联合查询tags和post_tags,根据TagId进行关联,然后分组从而获取标签下文章的总数,在BlogController中添加API。
/// <summary>
/// 查询标签列表
/// </summary>
/// <returns></returns>
[HttpGet]
[Route("tags")]
public async Task<ServiceResult<IEnumerable<QueryTagDto>>> QueryTagsAsync()
{
return await _blogService.QueryTagsAsync();
}

分类名称&文章列表

分析:此页面下包含两个接口,查询分类的名称和当前分类下的文章列表,和文章列表不同的是,它不带分页。分类包含两个字段,分类名称和展示名称,我们要把真正的名称查询出来展示在页面上。
分类名称
不需要给他添加返回模型,直接返回一个string类型即可,同时给一个查询参数name,添加获取分类名称接口和缓存接口。
//IBlogService.Category.cs
/// <summary>
/// 获取分类名称
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
Task<ServiceResult<string>> GetCategoryAsync(string name);
//IBlogCacheService.Category.cs
/// <summary>
/// 获取分类名称
/// </summary>
/// <param name="name"></param>
/// <param name="factory"></param>
/// <returns></returns>
Task<ServiceResult<string>> GetCategoryAsync(string name, Func<Task<ServiceResult<string>>> factory);
实现这两个接口。
//BlogCacheService.Category.cs
...
public partial class BlogCacheService
{
private const string KEY_GetCategory = "Blog:Category:GetCategory-{0}";
/// <summary>
/// 获取分类名称
/// </summary>
/// <param name="name"></param>
/// <param name="factory"></param>
/// <returns></returns>
public async Task<ServiceResult<string>> GetCategoryAsync(string name, Func<Task<ServiceResult<string>>> factory)
{
return await Cache.GetOrAddAsync(KEY_GetCategory.FormatWith(name), factory, CacheStrategy.ONE_DAY);
}
}
...
//BlogService.Category.cs
/// <summary>
/// 获取分类名称
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public async Task<ServiceResult<string>> GetCategoryAsync(string name)
{
return await _blogCacheService.GetCategoryAsync(name, async () =>
{
var result = new ServiceResult<string>();
var category = await _categoryRepository.FindAsync(x => x.DisplayName.Equals(name));
if (null == category)
{
result.IsFailed(ResponseText.WHAT_NOT_EXIST.FormatWith("分类", name));
return result;
}
result.IsSuccess(category.CategoryName);
return result;
});
}
FormatWith()是扩展方法,ResponseText.WHAT_NOT_EXIST是之前说过的常量,直接查询是否存在当前name的分类,如果不存在给出错误提示,存在的话,则只返回分类名称,在BlogController中添加API。
/// <summary>
/// 获取分类名称
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
[HttpGet]
[Route("category")]
public async Task<ServiceResult<string>> GetCategoryAsync(([Required] string name)
{
return await _blogService.GetCategoryAsync(name);
}
[Required]Attribute 指定参数name必填。


文章列表
通过分类名称查询文章列表和分页查询文章列表返回模型是一样的,只是不用分页,所以直接返回一个列表就可以了,添加通过分类名称查询文章列表和缓存的接口。
//IBlogService.Post.cs
/// <summary>
/// 通过分类名称查询文章列表
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
Task<ServiceResult<IEnumerable<QueryPostDto>>> QueryPostsByCategoryAsync(string name);
//IBlogCacheService.Post.cs
/// <summary>
/// 通过分类名称查询文章列表
/// </summary>
/// <param name="name"></param>
/// <param name="factory"></param>
/// <returns></returns>
Task<ServiceResult<IEnumerable<QueryPostDto>>> QueryPostsByCategoryAsync(string name, Func<Task<ServiceResult<IEnumerable<QueryPostDto>>>> factory);
分别实现这两个接口。
//BlogCacheService.Post.cs
...
public partial class BlogCacheService
{
private const string KEY_QueryPostsByCategory = "Blog:Post:QueryPostsByCategory-{0}";
/// <summary>
/// 通过分类名称查询文章列表
/// </summary>
/// <param name="name"></param>
/// <param name="factory"></param>
/// <returns></returns>
public async Task<ServiceResult<IEnumerable<QueryPostDto>>> QueryPostsByCategoryAsync(string name, Func<Task<ServiceResult<IEnumerable<QueryPostDto>>>> factory)
{
return await Cache.GetOrAddAsync(KEY_QueryPostsByCategory.FormatWith(name), factory, CacheStrategy.ONE_DAY);
}
}
...
//BlogService.Post.cs
/// <summary>
/// 通过分类名称查询文章列表
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public async Task<ServiceResult<IEnumerable<QueryPostDto>>> QueryPostsByCategoryAsync(string name)
{
return await _blogCacheService.QueryPostsByCategoryAsync(name, async () =>
{
var result = new ServiceResult<IEnumerable<QueryPostDto>>();
var list = (from posts in await _postRepository.GetListAsync()
join categories in await _categoryRepository.GetListAsync()
on posts.CategoryId equals categories.Id
where categories.DisplayName.Equals(name)
orderby posts.CreationTime descending
select new PostBriefDto
{
Title = posts.Title,
Url = posts.Url,
Year = posts.CreationTime.Year,
CreationTime = posts.CreationTime.TryToDateTime()
})
.GroupBy(x => x.Year)
.Select(x => new QueryPostDto
{
Year = x.Key,
Posts = x.ToList()
});
result.IsSuccess(list);
return result;
});
}
这个逻辑和分页查询文章列表是差不多的,联合查询文章表和分类表,关联字段为CategoryId,指定查询条件categories.DisplayName==name,以CreationTime倒序排序,年份分组,筛选出所需字段返回,在BlogController中添加API。
/// <summary>
/// 通过分类名称查询文章列表
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
[HttpGet]
[Route("posts/category")]
public async Task<ServiceResult<IEnumerable<QueryPostDto>>> QueryPostsByCategoryAsync([Required] string name)
{
return await _blogService.QueryPostsByCategoryAsync(name);
}

标签名称&文章列表

分析:此页面和分类页一样,包含两个接口,查询标签的名称和当前标签下的文章列表。
标签名称
添加获取标签名称接口和缓存接口,GetTagAsync()。
//IBlogService.Tag.cs
/// <summary>
/// 获取标签名称
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
Task<ServiceResult<string>> GetTagAsync(string name);
//IBlogCacheService.Tag.cs
/// <summary>
/// 获取标签名称
/// </summary>
/// <param name="name"></param>
/// <param name="factory"></param>
/// <returns></returns>
Task<ServiceResult<string>> GetTagAsync(string name, Func<Task<ServiceResult<string>>> factory);
实现这两个接口。
//BlogCacheService.Tag.cs
...
public partial class BlogCacheService
{
private const string KEY_GetTag = "Blog:Tag:GetTag-{0}";
/// <summary>
/// 获取标签名称
/// </summary>
/// <param name="name"></param>
/// <param name="factory"></param>
/// <returns></returns>
public async Task<ServiceResult<string>> GetTagAsync(string name, Func<Task<ServiceResult<string>>> factory)
{
return await Cache.GetOrAddAsync(KEY_GetTag.FormatWith(name), factory, CacheStrategy.ONE_DAY);
}
}
...
//BlogService.Tag.cs
/// <summary>
/// 获取标签名称
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public async Task<ServiceResult<string>> GetTagAsync(string name)
{
return await _blogCacheService.GetTagAsync(name, async () =>
{
var result = new ServiceResult<string>();
var tag = await _tagRepository.FindAsync(x => x.DisplayName.Equals(name));
if (null == tag)
{
result.IsFailed(ResponseText.WHAT_NOT_EXIST.FormatWith("标签", name));
return result;
}
result.IsSuccess(tag.TagName);
return result;
});
}
FormatWith()是扩展方法,ResponseText.WHAT_NOT_EXIST是之前说过的常量,直接查询是否存在当前name的分类,如果不存在给出错误提示,存在的话,则只返回分类名称,在BlogController中添加API。
/// <summary>
/// 获取标签名称
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
[HttpGet]
[Route("tag")]
public async Task<ServiceResult<string>> GetTagAsync(string name)
{
return await _blogService.GetTagAsync(name);
}
[Required]Attribute 指定参数name必填。


文章列表
和上面一模一样的,添加通过标签名称查询文章列表接口和缓存接口。
//IBlogService.Post.cs
/// <summary>
/// 通过标签名称查询文章列表
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
Task<ServiceResult<IEnumerable<QueryPostDto>>> QueryPostsByTagAsync(string name);
//IBlogCacheService.Post.cs
/// <summary>
/// 通过标签名称查询文章列表
/// </summary>
/// <param name="name"></param>
/// <param name="factory"></param>
/// <returns></returns>
Task<ServiceResult<IEnumerable<QueryPostDto>>> QueryPostsByTagAsync(string name, Func<Task<ServiceResult<IEnumerable<QueryPostDto>>>> factory);
分别实现这两个接口。
//BlogCacheService.Post.cs
...
public partial class BlogCacheService
{
private const string KEY_QueryPostsByTag = "Blog:Post:QueryPostsByTag-{0}";
/// <summary>
/// 通过标签名称查询文章列表
/// </summary>
/// <param name="name"></param>
/// <param name="factory"></param>
/// <returns></returns>
public async Task<ServiceResult<IEnumerable<QueryPostDto>>> QueryPostsByTagAsync(string name, Func<Task<ServiceResult<IEnumerable<QueryPostDto>>>> factory)
{
return await Cache.GetOrAddAsync(KEY_QueryPostsByTag.FormatWith(name), factory, CacheStrategy.ONE_DAY);
}
}
...
//BlogService.Post.cs
/// <summary>
/// 通过标签名称查询文章列表
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public async Task<ServiceResult<IEnumerable<QueryPostDto>>> QueryPostsByTagAsync(string name)
{
return await _blogCacheService.QueryPostsByTagAsync(name, async () =>
{
var result = new ServiceResult<IEnumerable<QueryPostDto>>();
var list = (from post_tags in await _postTagRepository.GetListAsync()
join tags in await _tagRepository.GetListAsync()
on post_tags.TagId equals tags.Id
join posts in await _postRepository.GetListAsync()
on post_tags.PostId equals posts.Id
where tags.DisplayName.Equals(name)
orderby posts.CreationTime descending
select new PostBriefDto
{
Title = posts.Title,
Url = posts.Url,
Year = posts.CreationTime.Year,
CreationTime = posts.CreationTime.TryToDateTime()
})
.GroupBy(x => x.Year)
.Select(x => new QueryPostDto
{
Year = x.Key,
Posts = x.ToList()
});
result.IsSuccess(list);
return result;
});
}
这个查询有点特殊,联合查询了3张表,先查post_tags和tags,关联字段TagId,再根据PostId查询posts,指定查询条件tags.DisplayName==name,以CreationTime倒序排序,年份分组,筛选出所需字段返回,在BlogController中添加API。
/// <summary>
/// 通过标签名称查询文章列表
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
[HttpGet]
[Route("posts/tag")]
public async Task<ServiceResult<IEnumerable<QueryPostDto>>> QueryPostsByTagAsync(string name)
{
return await _blogService.QueryPostsByTagAsync(name);
}

至此,基本上完成了博客前端所需的所有查询接口,就还剩下友链的查询,大家可以自己完成,后面如果需要什么新的接口再回头来写就好了。
开源地址:https://github.com/Meowv/Blog/tree/blog_tutorial
搭配下方课程学习更佳 ↓ ↓ ↓

基于 abp vNext 和 .NET Core 开发博客项目 - 博客接口实战篇(二)的更多相关文章
- 基于 abp vNext 和 .NET Core 开发博客项目 - 定时任务最佳实战(三)
上一篇(https://www.cnblogs.com/meowv/p/12974439.html)完成了全网各大平台的热点新闻数据的抓取,本篇继续围绕抓取完成后的操作做一个提醒.当每次抓取完数据后, ...
- 基于 abp vNext 和 .NET Core 开发博客项目 - 博客接口实战篇(一)
系列文章 基于 abp vNext 和 .NET Core 开发博客项目 - 使用 abp cli 搭建项目 基于 abp vNext 和 .NET Core 开发博客项目 - 给项目瘦身,让它跑起来 ...
- 基于 abp vNext 和 .NET Core 开发博客项目 - 博客接口实战篇(三)
系列文章 基于 abp vNext 和 .NET Core 开发博客项目 - 使用 abp cli 搭建项目 基于 abp vNext 和 .NET Core 开发博客项目 - 给项目瘦身,让它跑起来 ...
- 基于 abp vNext 和 .NET Core 开发博客项目 - 博客接口实战篇(四)
系列文章 基于 abp vNext 和 .NET Core 开发博客项目 - 使用 abp cli 搭建项目 基于 abp vNext 和 .NET Core 开发博客项目 - 给项目瘦身,让它跑起来 ...
- 基于 abp vNext 和 .NET Core 开发博客项目 - 博客接口实战篇(五)
系列文章 基于 abp vNext 和 .NET Core 开发博客项目 - 使用 abp cli 搭建项目 基于 abp vNext 和 .NET Core 开发博客项目 - 给项目瘦身,让它跑起来 ...
- 基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(一)
系列文章 基于 abp vNext 和 .NET Core 开发博客项目 - 使用 abp cli 搭建项目 基于 abp vNext 和 .NET Core 开发博客项目 - 给项目瘦身,让它跑起来 ...
- 基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(二)
系列文章 基于 abp vNext 和 .NET Core 开发博客项目 - 使用 abp cli 搭建项目 基于 abp vNext 和 .NET Core 开发博客项目 - 给项目瘦身,让它跑起来 ...
- 基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(三)
系列文章 基于 abp vNext 和 .NET Core 开发博客项目 - 使用 abp cli 搭建项目 基于 abp vNext 和 .NET Core 开发博客项目 - 给项目瘦身,让它跑起来 ...
- 基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(四)
系列文章 基于 abp vNext 和 .NET Core 开发博客项目 - 使用 abp cli 搭建项目 基于 abp vNext 和 .NET Core 开发博客项目 - 给项目瘦身,让它跑起来 ...
随机推荐
- iOS的内存管理和引用计数规则、Block的用法以及三种形式(stack、malloc、global)
学习内容 iOS的内存管理和引用计数规则 内存管理的思考方式 自己生成的对象自己持有 非自己生成的对象自己也能持有 自己持有的对象不需要时释放 非自己持有的对象不能释放 ARC有效时,id类型和对象类 ...
- GAN的前身——VAE模型原理
GAN的前身——VAE模型 今天跟大家说一说VAE模型相关的原理,首先我们从判别模型和生成模型定义开始说起: 判别式模型:已知观察变量X和隐含变量z,它对p(z|X)进行建模,它根据输入的观察变量X得 ...
- JUC之ReentrantLock源码分析
ReentrantLock:实现了Lock接口,是一个可重入锁,并且支持线程公平竞争和非公平竞争两种模式,默认情况下是非公平模式.ReentrantLock算是synchronized的补充和替代方案 ...
- [hdu3068 最长回文]Manacher算法,O(N)求最长回文子串
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3068 题意:求一个字符串的最长回文子串 思路: 枚举子串的两个端点,根据回文串的定义来判断其是否是回文 ...
- Mybatis 快速入门(XML方式)第一天
导读 架构原理图 说明 mybatis配置文件 SqlMapConfig.xml,此文件为mybatis的全局配置文件,配置了mybatis的运行环境等信息 XXXMapper.xml,此文件作为my ...
- Shiro+Mybatis实现登录认证、授权功能
Shiro+Mybatis实现登录认证.授权功能 一.实现登录认证功能 1.流程: 跟据用户提交表单的账号,经Mybatis框架在数据库中查出User对象: 如果User为空,则会抛出异常:Unkno ...
- 2018-06-17 js数组
数组的定义:① var arr=new Array(xx,xx,xx); ②var arr=[yy,yy,,yy]; 数组的查看:arr[x]; 数组的修改:arr[x]=xx; 数组的遍历:①for ...
- PAT 1010 Radix (25分) radix取值无限制,二分法提高效率
题目 Given a pair of positive integers, for example, 6 and 110, can this equation 6 = 110 be true? The ...
- delete old data in elasticsearch
delete old data in elasticsearch 0.正文. 其实很简单,就是用他的rest api 发一个delete 请求到 localhost:9200/[indices] [i ...
- nginx均衡负载
一直在担心session 问题,结果试了2个web 论坛,discuz 和phpbb ,前面用nginx 均衡负载,后端是apache httpd +php ,mysql 用同一个,修改一下confi ...