SpringBoot学习项目-博客系统-part2

首页文章列表

  1. 前端项目构建完成之后,f12查看控制台,没有任何内容,可以看见SpringBoot学习项目-博客系统-part2,这里是项目已经完成,最初是爆红的。
  2. 那么接下来进行接口的开发。根据文档了解到接口的一个说明。 封装一个PageParams
  3. 因为是前后端分离的项目,所以需要制定统一状态码
@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);
    }
}

  1. 根据给的文档可以看出,在/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

  1. 目前所有的流程都是controller->service->mapper
  2. 写一个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

  1. 因为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;
    }


}

  • 解释一下:
  1. 因为ArticleServiceImpl只能调用ArticleMapper,但是又涉及到了其他的两个表,所以将其他两个表的service也注入。
  2. 创建wrapper和page之后,因为返回的是所有的,那么就会查询到所有的article的列表,但是要求的是返回一个ArticleVo对象列表,所以要将查出的所有Article转换为ArticleVo对象(需要文章作者名称,不需要具体内容,需要文章所属标签)
  3. 根据传入的Article可以获取到作者Id,以及文章自身的Id,因为在标签表中关联了tagId和文章Id。
  4. 将传入的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. 现在的小问题,在明白了逻辑的构成之后,代码不一定能够写的通畅,这是自己的问题所在,这个也是自己代码写的少,加紧训练就好。
上一篇:【Python+Django】一个博客网站的设计和代码实现


下一篇:手把手教Linux驱动9-等待队列waitq