Echo/docs/10-开发社区首页.md
2021-01-17 11:14:50 +08:00

9.7 KiB
Raw Blame History

开发社区首页


DiscussPost 讨论帖

Entity

DAO

  • Mapper 接口 DiscussPostMapper
  • 对应的 xml 配置文件 discusspost-mapper.xml

@Param 注解用于给参数起别名,如果只有一个参数,并且需要在 <if> 里使用,则必须加别名

@Mapper
public interface DiscussPostMapper {

    /**
     * 分页查询讨论贴信息
     *
     * @param userId 当传入的 userId = 0 时查找所有用户的帖子
     *               当传入的 userId != 0 时,查找该指定用户的帖子
     * @param offset 每页的起始索引
     * @param limit  每页显示多少条数据
     * @return
     */
    List<DiscussPost> selectDiscussPosts(int userId, int offset, int limit);

    /**
     * 查询讨论贴的个数
     * @param userId 当传入的 userId = 0 时计算所有用户的帖子总数
     *               当传入的 userId = 0 时计算该指定用户的帖子总数
     * @return
     */
    int selectDiscussPostRows(@Param("userId") int userId);
}

对应的 Mapper

<?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.greate.community.dao.DiscussPostMapper">

    <sql id = "selectFields">
        id, user_id, title, content, type, status, create_time, comment_count, score
    </sql>

    <!--分页查询讨论贴信息-->
    <!--不显示拉黑的帖子, 按照是否置顶和创建时间排序-->
    <select id = "selectDiscussPosts" resultType="DiscussPost">
        select <include refid="selectFields"></include>
        from discuss_post
        where status != 2
        <if test = "userId!=0">
            and user_id = #{userId}
        </if>
        order by type desc, create_time desc
        limit #{offset}, #{limit}
    </select>

    <!--查询讨论贴的个数-->
    <select id = "selectDiscussPostRows" resultType="int">
        select count(id)
        from discuss_post
        where status != 2
        <if test = "userId != 0">
            and user_id = #{userId}
        </if>
    </select>

</mapper>

Service

关于自动注入 Mapper 报错问题:可参考 关于IDEA中@Autowired 注解报错~图文

@Service
public class DiscussPostSerivce {

    @Autowired
    private DiscussPostMapper discussPostMapper;


    /**
     * 分页查询讨论帖信息
     *
     * @param userId 当传入的 userId = 0 时查找所有用户的帖子
     *               当传入的 userId != 0 时,查找该指定用户的帖子
     * @param offset 每页的起始索引
     * @param limit  每页显示多少条数据
     * @return
     */
    public List<DiscussPost> findDiscussPosts (int userId, int offset, int limit) {
        return discussPostMapper.selectDiscussPosts(userId, offset, limit);
    }

    /**
     * 查询讨论贴的个数
     * @param userId 当传入的 userId = 0 时计算所有用户的帖子总数
     *               当传入的 userId = 0 时计算该指定用户的帖子总数
     * @return
     */
    public int findDiscussPostRows (int userId) {
        return discussPostMapper.selectDiscussPostRows(userId);
    }

}

User

Entity

DAO

@Mapper
public interface UserMapper {

    /**
     * 根据 id 查询用户
     * @param id
     * @return
     */
    User selectById (int id);

    /**
     * 根据 username 查询用户
     * @param username
     * @return
     */
    User selectByName(String username);

    /**
     * 根据 email 查询用户
     * @param email
     * @return
     */
    User selectByEmail(String email);

    /**
     * 插入用户(注册)
     * @param user
     * @return
     */
    int insertUser(User user);

    /**
     * 修改用户状态
     * @param id
     * @param status 0未激活1已激活
     * @return
     */
    int updateStatus(int id, int status);

    /**
     * 修改头像
     * @param id
     * @param headerUrl
     * @return
     */
    int updateHeader(int id, String headerUrl);

    /**
     * 修改密码
     * @param id
     * @param password
     * @return
     */
    int updatePassword(int id, String password);

}

对应的 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.greate.community.dao.UserMapper">

    <sql id = "insertFields">
        username, password, salt, email, type, status, activation_code, header_url, create_time
    </sql>

    <sql id = "selectFields">
        id, username, password, salt, email, type, status, activation_code, header_url, create_time
    </sql>

    <!--根据 Id 查询用户信息-->
    <select id = "selectById" resultType = "User">
        select <include refid="selectFields"></include>
        from user
        where id = #{id}
    </select>

    <!--根据 Username 查询用户信息-->
    <select id="selectByName" resultType="User">
        select <include refid="selectFields"></include>
        from user
        where username = #{username}
    </select>

    <!--根据 email 查询用户信息-->
    <select id="selectByEmail" resultType="User">
        select <include refid="selectFields"></include>
        from user
        where email = #{email}
    </select>

    <!--插入用户信息(注册)-->
    <insert id="insertUser" parameterType="User" keyProperty="id">
        insert into user (<include refid="insertFields"></include>)
        values(#{username}, #{password}, #{salt}, #{email}, #{type}, #{status}, #{activationCode}, #{headerUrl}, #{createTime})
    </insert>

    <!--修改用户状态-->
    <update id="updateStatus">
        update user set status = #{status} where id = #{id}
    </update>

    <!--修改用户头像-->
    <update id="updateHeader">
        update user set header_url = #{headerUrl} where id = #{id}
    </update>

    <!--修改密码-->
    <update id="updatePassword">
        update user set password = #{password} where id = #{id}
    </update>

</mapper>

Service

@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    public User findUserById (int id) {
        return userMapper.selectById(id);
    }

}

Page 分页

/**
 * 封装分页相关的信息
 */
public class Page {

    // 当前的页码
    private int current = 1;
    // 单页显示的帖子数量上限
    private int limit = 10;
    // 帖子总数(用于计算总页数)
    private int rows;
    // 查询路径(用于复用分页链接, 因为我们不只在首页中有分页,其他界面也会有分页)
    private String path;

    public int getCurrent() {
        return current;
    }

    public void setCurrent(int current) {
        if (current >= 1) {
            this.current = current;
        }
    }

    public int getLimit() {
        return limit;
    }

    public void setLimit(int limit) {
        if (current >= 1 && limit <= 100) {
            this.limit = limit;
        }
    }

    public int getRows() {
        return rows;
    }

    public void setRows(int rows) {
        if (rows >= 0) {
            this.rows = rows;
        }
    }

    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }

    /**
     * 获取当前页的起始索引 offset
     * @return
     */
    public int getOffset() {
        return current * limit - limit;
    }

    /**
     * 获取总页数
     * @return
     */
    public int getTotal() {
        if (rows % limit == 0) {
            return rows / limit;
        }
        else {
            return rows / limit + 1;
        }
    }

    /**
     * 获取分页栏起始页码
     * 分页栏显示当前页码及其前后两页
     * @return
     */
    public int getFrom() {
        int from = current - 2;
        return from < 1 ? 1 : from;
    }

    /**
     * 获取分页栏结束页码
     * @return
     */
    public int getTo() {
        int to = current + 2;
        int total = getTotal();
        return to > total ? total : to;
    }
}

Controller

@Controller
public class HomeController {

    @Autowired
    private DiscussPostSerivce discussPostSerivce;

    @Autowired
    private UserService userService;

    @GetMapping("/index")
    public String getIndexPage(Model model, Page page) {
        // 获取总页数
        page.setRows(discussPostSerivce.findDiscussPostRows(0));
        page.setPath("/index");

        // 分页查询
        List<DiscussPost> list = discussPostSerivce.findDiscussPosts(0, page.getOffset(), page.getLimit());
        // 封装帖子和该帖子对应的用户信息
        List<Map<String, Object>> discussPosts = new ArrayList<>();
        if (list != null) {
            for (DiscussPost post : list) {
                Map<String, Object> map = new HashMap<>();
                map.put("post", post);
                User user = userService.findUserById(post.getUserId());
                map.put("user", user);
                discussPosts.add(map);
            }
        }
        model.addAttribute("discussPosts", discussPosts);
        return "index";
    }

}

🚩 小 Tip这里不用把 Page 放入 modelmodel.addAttribute("page", page);

因为在方法调用之前Spring MVC 会自动实例化 Model 和 Page并将 Page 注入 Model所以在 Thymeleaf 中可以直接访问 Page 对象中的数据

前端界面 index.html

th:each="map:${discussPosts}"

表示将每次遍历 discussPosts 取出的变量称为 map