封装数据的总结

108 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第9天,点击查看活动详情

1.问题引入

今天在学习尚硅谷的一个项目的时候,有一个接口需要封装数据,再返回给前端同学,过程个人觉得有点复杂,在此记录下自己的思考,欢迎各位同学批评指教。

这个接口的要求是查询课程的大纲,即需要查找课程的章节以及每个章节的每个小节的信息。

需要封装的数据是这样的。第一层大括号封装的是章节信息,第一层大括号里面的大括号封装的是每个章节的每个小节信息。

[
    {
        id:"1",
        title:"",
        children:[
            {
                id:"11",
                title:"第一节"
            },
            {}
        ]
    },
    {}
    
]

从上面的数据组织形式,我们发现最外面是[]。看到这个中括号,意味着我们在controller层返回的应该是一个List集合,这个list集合的元素应该是封装着章节信息的类。我们现在把目光转移到第一层括号里面,我们发现里面有个属性children,这个children属性后面带的也是一个数组,这意味着章节信息应该封装着小节信息,因为一个章节可能有多个小节,所以每个封装着章节信息的类里面应该有一个集合,这个集合的元素应该是封装着小节信息的类

用代码的形式展现如下:

小节信息的类

@ApiModel("课时信息")
@Data
public class VideoVo {
    @ApiModelProperty(value = "课时ID")
    private Long id;
    @ApiModelProperty(value = "课时标题")
    private String title;
    @ApiModelProperty(value = "是否可以试听")
    private Integer isFree;
    @ApiModelProperty(value = "排序")
    private Integer sort;
    @ApiModelProperty(value = "阿里云视频ID")
    private String videoSourceId;
}

章节信息的类

@ApiModel("课程章节对象")
@Data
public class ChapterVo {

    @ApiModelProperty(value = "章节ID")
    private Long id;
    @ApiModelProperty(value = "章节标题")
    private String title;
    @ApiModelProperty(value = "排序")
    private Integer sort;
    @ApiModelProperty(value = "章节下的课时列表")
    private List<VideoVo> children = new ArrayList<>();
}

2.解决问题的相关代码

在看代码之前,我们先来看下我们的数据库表。

章节表

这张图希望大家能注意到里面的course_id字段,这个字段记录了当前章节属于那个课程。 image.png 小节表

这张表希望大家能注意到两个字段course_id和chapter_id。course_id字段记录了当前小节属于那个课程,chapter_id字段记录当前小节属于那个章节。

image.png

具体代码(持久层框架是mybatisplus,所以我这里没写mapper):

controller

//1 大纲列表(章节和小节列表)
@ApiOperation("大纲列表")
@GetMapping("getNestedTreeList/{courseId}")
public Result getNestedTreeList(@PathVariable Long courseId) {
    List<ChapterVo> list = chapterService.getTreeList(courseId);
    return Result.ok(list);
}

service接口和service接口实现类

public interface ChapterService extends IService<Chapter> {

    List<ChapterVo> getTreeList(Long courseId);
}

service接口实现类代码讲解:

  1. 通过课程id在章节表里面查询出属于这个课程的章节。
  2. 通过课程id在小节表里面查询出属于这个课程的小节。
  3. 因为我们是用自己写的实体类来封装信息,并返回给前端同学的,所以我们这里需要将查询到的数据进行封装。我们查询到的数据是保存在Chapter(章节)和Video(小节),我们要将他们封装到ChapterVo和VideoVo。
  4. 封装章节的思路很简单,通过一个for循环遍历刚刚查找到的章节集合,并信息封装到我们自己写的ChapterVo类(这个类可以看上面)。
  5. 封装章节的for循环里面,可以顺便封装小节信息。如何判断这个小节属于哪个章节的判断标准就是,小节的chapter_id是否和封装章节信息的类取得的id相同。如果相同,意味着这个小节属于当前章节,并将这个小节保存到List集合,然后将这个集合添加到ChapterVo类,并最终将ChapterVo保存到List集合。
  6. 返回List集合。
@Service
public class ChapterServiceImpl extends ServiceImpl<ChapterMapper, Chapter> implements ChapterService {

    @Autowired
    private VideoService videoService;

    //1 大纲列表(章节和小节列表)
    @Override
    public List<ChapterVo> getTreeList(Long courseId) {
        //定义最终数据list集合
        List<ChapterVo> finalChapterList = new ArrayList<>();

        //根据courseId获取课程里面所有章节
        QueryWrapper<Chapter> wrapperChapter = new QueryWrapper<>();
        wrapperChapter.eq("course_id",courseId);
        List<Chapter> chapterList = baseMapper.selectList(wrapperChapter);

        //根据courseId获取课程里面所有小节
        LambdaQueryWrapper<Video> wrapperVideo = new LambdaQueryWrapper<>();
        wrapperVideo.eq(Video::getCourseId,courseId);
        List<Video> videoList = videoService.list(wrapperVideo);

        //封装章节
        for (int i = 0; i < chapterList.size();i++){
            //得到课程每个章节
            Chapter chapter = chapterList.get(i);
            // Chapter转换成ChapterVo
            ChapterVo chapterVo = new ChapterVo();
            BeanUtils.copyProperties(chapter,chapterVo);


            //封装章节里面的小节
            //创建list集合用于封装章节里面所有小节
            List<VideoVo> videoVoList = new ArrayList<>();
            //遍历小节list
            for (Video video : videoList){
                //判断小节是哪个章节下面
                //章节id和小节的chapter_id
                if (chapter.getId().equals(video.getChapterId())){
                    //video转换成VideoVo
                    VideoVo videoVo = new VideoVo();
                    BeanUtils.copyProperties(video,videoVo);
                    //放到videoList
                    videoVoList.add(videoVo);
                }
            }
            //把章节里面所有小节集合放到每个章节里面
            chapterVo.setChildren(videoVoList);
            //得到每个章节对象放到finalChapterList集合
            finalChapterList.add(chapterVo);
        }
        return finalChapterList;
    }
}

3.实验结果

image.png