豆宝社区项目实战教程简介
本项目实战教程配有免费视频教程,配套代码完全开源。手把手从零开始搭建一个目前应用最广泛的Springboot+Vue前后端分离多用户社区项目。本项目难度适中,为便于大家学习,每一集视频教程对应在Github上的每一次提交。
项目首页截图
代码开源地址
视频教程地址
前端技术栈
Vue Vuex Vue Router Axios Bulma Buefy Element Vditor DarkReader
后端技术栈
Spring Boot Mysql Mybatis MyBatis-Plus Spring Security JWT Lombok
帖子列表后端实现
实体类
BmsPost
import com.baomidou.mybatisplus.annotation.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
import java.util.Date;
@Data
@Builder
@TableName("bms_post")
@AllArgsConstructor
@NoArgsConstructor
public class BmsPost implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private String id;
/**
* 标题
*/
@NotBlank(message = "标题不可以为空")
@TableField(value = "title")
private String title;
/**
* markdown
*/
@NotBlank(message = "内容不可以为空")
@TableField("`content`")
private String content;
/**
* 作者ID
*/
@TableField("user_id")
private String userId;
/**
* 评论数
*/
@TableField("comments")
@Builder.Default
private Integer comments = 0;
/**
* 收藏数
*/
@TableField("collects")
@Builder.Default
private Integer collects = 0;
/**
* 浏览数
*/
@TableField("view")
@Builder.Default
private Integer view = 0;
/**
* 专栏ID,默认不分栏
*/
@TableField("section_id")
@Builder.Default
private Integer sectionId = 0;
/**
* 置顶
*/
@TableField("top")
@Builder.Default
private Boolean top = false;
/**
* 加精
*/
@TableField("essence")
@Builder.Default
private Boolean essence = false;
/**
* 创建时间
*/
@TableField(value = "create_time", fill = FieldFill.INSERT)
private Date createTime;
/**
* 修改时间
*/
@TableField(value = "modify_time", fill = FieldFill.UPDATE)
private Date modifyTime;
/**
* 描述
*/
@TableField("summary")
private String summary;
}
BmsPostTag
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
@Data
@TableName("bms_post_tag")
@Accessors(chain = true)
public class BmsPostTag implements Serializable {
private static final long serialVersionUID = -5028599844989220715L;
@TableId(type = IdType.AUTO)
private Integer id;
@TableField("tag_id")
private String tagId;
@TableField("post_id")
private String postId;
}
BmsTag
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Builder;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
@Data
@Builder
@TableName("bms_tag")
@Accessors(chain = true)
public class BmsTag implements Serializable {
private static final long serialVersionUID = 3257790983905872243L;
@TableId(type = IdType.ASSIGN_ID)
private String id;
@TableField("name")
private String name;
/**
* 当前标签下的话题个数
*/
@TableField("post_count")
@Builder.Default
private Integer postCount = 1;
}
Vo
package com.notepad.blog.domain.vo;
import com.notepad.blog.domain.BmsTag;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PostVO implements Serializable {
private static final long serialVersionUID = -261082150965211545L;
/**
* 文章ID
*/
private String id;
/**
* 用户ID
*/
private String userId;
/**
* 头像
*/
private String avatar;
/**
* 用户昵称
*/
private String alias;
/**
* 账号
*/
private String username;
/**
* 标题
*/
private String title;
/**
* 评论统计
*/
private Integer comments;
/**
* 置顶
*/
private Boolean top;
/**
* 加精
*/
private Boolean essence;
/**
* 收藏次數
*/
private Integer collects;
/**
* 话题关联标签
*/
private List<BmsTag> tags;
/**
* 浏览量
*/
private Integer view;
/**
* 创建时间
*/
private Date createTime;
/**
* 修改时间
*/
private Date modifyTime;
/**
* 文章描述
*/
private String summary;
}
mapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.notepad.blog.mapper.BmsPostMapper">
<resultMap id="postVo" type="com.notepad.blog.domain.vo.PostVO">
<id column="id" property="id"/>
<result column="title" property="title"/>
<result column="user_id" property="userId"/>
<result column="comments" property="comments"/>
<result column="view" property="view"/>
<result column="collects" property="collects"/>
<result column="top" property="top"/>
<result column="essence" property="essence"/>
<result column="create_time" property="createTime"/>
<result column="modify_time" property="modifyTime"/>
<result column="username" property="username"/>
<result column="alias" property="alias"/>
<result column="avatar" property="avatar"/>
<result column="summary" property="summary"/>
<collection property="tags" ofType="com.notepad.blog.domain.BmsTag">
<result column="tag_id" property="id"/>
<result column="name" property="name"/>
<result column="post_count" property="postCount"/>
</collection>
</resultMap>
<select id="selectListAndPage" resultMap="postVo">
SELECT
p.id,
p.title,
<!-- p.user_id, -->
p.comments,
p.VIEW,
p.collects,
p.top,
p.essence,
p.create_time,
p.modify_time,
u.username,
u.alias,
u.avatar,
pt.tag_id,
t.`name`,
t.post_count
FROM
bms_post p
LEFT JOIN ums_user u ON p.user_id = u.id
LEFT JOIN bms_post_tag pt ON p.id = pt.post_id
LEFT JOIN bms_tag t ON t.id = pt.tag_id
<if test="tab == 'hot'">
<where>
date(p.create_time) <= date_add(curdate(), interval 1 day)
and date(p.create_time) >= date_sub(curdate(), interval 7 day)
</where>
order by p.view desc, p.create_time desc
</if>
<if test="tab == 'atest'">
order by p.create_time desc
</if>
<if test="tab == 'update'">
<where>
p.modify_time is NOT null
</where>
order by p.modify_time desc
</if>
</select>
</mapper>
mapper层
public interface BmsPostMapper extends BaseMapper<BmsPost> {
Page<PostVO> selectListAndPage(@Param("page") Page<PostVO> page, @Param("tab") String tab);
}java
controller
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.notepad.blog.common.api.ApiResult;
import com.notepad.blog.domain.vo.PostVO;
import com.notepad.blog.service.BmsPostService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/post")
public class BmsPostController {
@Autowired
private BmsPostService postService;
@GetMapping("/list")
public ApiResult<Page<PostVO>> list(@RequestParam(value = "tab", defaultValue = "latest") String tab,
@RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(value = "size", defaultValue = "10") Integer pageSize) {
Page<PostVO> list = postService.getList(pageNo,pageSize, tab);
return ApiResult.success(list);
}
}
service
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.notepad.blog.domain.BmsPost;
import com.notepad.blog.domain.BmsPostTag;
import com.notepad.blog.domain.BmsTag;
import com.notepad.blog.domain.vo.PostVO;
import com.notepad.blog.mapper.BmsPostMapper;
import com.notepad.blog.mapper.BmsPostTagMapper;
import com.notepad.blog.mapper.BmsTagMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class BmsPostService extends ServiceImpl<BmsPostMapper, BmsPost> {
@Autowired
private BmsPostMapper postMapper;
public Page<PostVO> getList(Integer pageNo, Integer pageSize, String tab) {
Page<PostVO> page = new Page(pageNo, pageSize);
// 查询文章
Page<PostVO> iPage = postMapper.selectListAndPage(page, tab);
return iPage;
}
}