首页文章列表
- 前端项目构建完成之后,f12查看控制台,没有任何内容,可以看见,这里是项目已经完成,最初是爆红的。
- 那么接下来进行接口的开发。根据文档了解到接口的一个说明。 封装一个PageParams
- 因为是前后端分离的项目,所以需要制定统一状态码
@Data
@AllArgsConstructor
public class Result {
private boolean success;
private int code;
private String msg;
private Object data;
public static Result success(Object data){
return new Result(true,200,"success",data);
}
public static Result fail(int code, String msg){
return new Result(false,code,msg,null);
}
}
- 根据给的文档可以看出,在
/articles
接口下的数据返回格式,设计到了文章表、标签表、用户表(因为有author),分别创建这三个表的实体类,根据字段创建。
同时根据数据返回格式创建一个ArticleVo用来接收查询到的数据
@Data
public class ArticleVo {
private Long id;
private String title;
private String summary;
private int commentCounts;
private int viewCounts;
private int weight;
/**
* 创建时间
*/
private String createDate;
private String author;
private ArticleBodyVo body;
private List<TagVo> tags;
private List<CategoryVo> categorys;
}
controller
- 目前所有的流程都是controller->service->mapper
- 写一个
ArticleController
,专门用来处理和文章相关的
@RestController
@RequestMapping("articles")
public class ArticleController {
@Autowired
private ArticleService articleService;
//Result是统一结果返回
@PostMapping
public Result articles(@RequestBody PageParams pageParams) {
//ArticleVo 页面接收的数据
List<ArticleVo> articles = articleService.listArticlesPage(pageParams);
return Result.success(articles);
}
}
service
- 因为controller已经调用service,创建对应的
ArticleService
接口,实现类ArticleServiceImpl
ArticleService
public interface ArticleService {
List<ArticleVo> listArticlesPage(PageParams pageParams);
}
ArticleServiceImpl
@Service
public class ArticleServiceImpl implements ArticleService {
@Autowired
private ArticleMapper articleMapper;
@Autowired
private SysUserService sysUserService;
@Autowired
private TagsService tagsService;
public ArticleVo copy(Article article,boolean isAuthor,boolean isBody,boolean isTags){
ArticleVo articleVo = new ArticleVo();
BeanUtils.copyProperties(article, articleVo);
if (isAuthor) {
SysUser sysUser = sysUserService.findSysUserById(article.getAuthorId());
articleVo.setAuthor(sysUser.getNickname());
}
articleVo.setCreateDate(new DateTime(article.getCreateDate()).toString("yyyy-MM-dd HH:mm"));
if (isTags){
List<TagVo> tags = tagsService.findTagsByArticleId(article.getId());
articleVo.setTags(tags);
}
return articleVo;
}
private List<ArticleVo> copyList(List<Article> records,boolean isAuthor,boolean isBody,boolean isTags) {
List<ArticleVo> articleVoList = new ArrayList<>();
for (Article article : records) {
ArticleVo articleVo = copy(article,isAuthor,isBody,isTags);
articleVoList.add(articleVo);
}
return articleVoList;
}
@Override
public List<ArticleVo> listArticlesPage(PageParams pageParams) {
QueryWrapper<Article> queryWrapper = new QueryWrapper<>();
Page<Article> page = new Page<>(pageParams.getPage(),pageParams.getPageSize());
Page<Article> articlePage = articleMapper.selectPage(page, queryWrapper);
List<ArticleVo> articleVoList = copyList(articlePage.getRecords(),true,false,true);
return articleVoList;
}
}
- 解释一下:
- 因为ArticleServiceImpl只能调用ArticleMapper,但是又涉及到了其他的两个表,所以将其他两个表的service也注入。
- 创建wrapper和page之后,因为返回的是所有的,那么就会查询到所有的article的列表,但是要求的是返回一个ArticleVo对象列表,所以要将查出的所有Article转换为ArticleVo对象(需要文章作者名称,不需要具体内容,需要文章所属标签)
- 根据传入的Article可以获取到作者Id,以及文章自身的Id,因为在标签表中关联了tagId和文章Id。
- 将传入的article有的属性使用工具类
BeanUtils
封装,再根据是否需要作者以及是否需要标签,去两个表中进行查找。
UserService
public interface UserService {
SysUser findUserById(Long userId);
}
UserServiceImpl
@Service
public class UserServiceImpl implements UserService {
@Autowired
private SysUserMapper sysUserMapper;
@Override
public SysUser findUserById(Long userId) {
SysUser sysUser = sysUserMapper.selectById(userId);
if (sysUser == null) {
sysUser = new SysUser();
sysUser.setNickname("码神之路");
}
return sysUser;
}
}
TagsService
public interface TagsService {
List<TagVo> findTagsByArticleId(Long id);
}
TagsServiceImpl
@Service
public class TagsServiceImpl implements TagsService {
@Autowired
private TagMapper tagMapper;
public TagVo copy(Tag tag){
TagVo tagVo = new TagVo();
BeanUtils.copyProperties(tag,tagVo);
return tagVo;
}
public List<TagVo> copyList(List<Tag> tagList){
List<TagVo> tagVoList = new ArrayList<>();
for (Tag tag : tagList) {
tagVoList.add(copy(tag));
}
return tagVoList;
}
@Override
public List<TagVo> findTagsByArticleId(Long id) {
List<Tag> tags = tagMapper.findTagsByArticleId(id);
return copyList(tags);
}
}
- 解释:这里tagVo和Tag两个类的属性一样,但是分开可能是降耦合的目的,真实开发不确定是否会这样写
Dao
上面设计到的三个mapper
ArticleMapper
public interface ArticleMapper extends BaseMapper<Article> {
}
TagMapper
public interface TagMapper extends BaseMapper<Tag> {
List<Tag> findTagsByArticleId(Long articleId);
}
sql
因为mp不支持多表联合查询,在数据库文章标签表中,文章和标签进行了一个关联,而又有一个单独的标签表。所以需要进行一个sql书写
<mapper namespace="com.mszlu.blog.dao.TagMapper">
<select id="findTagsByArticleId" parameterType="long" resultType="com.lbj.blog.dao.pojo.Tag">
select id,avatar,tag_name as tagName from ms_tag
where id in
(select tag_id from ms_article_tag where article_id=#{articleId})
</select>
</mapper>
SysUserMapper
public interface SysUserMapper extends BaseMapper<SysUser> {
}
- 到这里就完成了文章列表的创建了
说一下自己的小感悟吧:
1. 在看视频的时候很慌,慌张的原因在于没有研究过数据库表的结构,所以挺视频的时候一头雾水,这里为什么要这样,那里为什么要那样。其实只要好好看看数据库表的结构,就可以理解。
2. 现在的小问题,在明白了逻辑的构成之后,代码不一定能够写的通畅,这是自己的问题所在,这个也是自己代码写的少,加紧训练就好。