牛客网社区项目——1.6开发社区首页

①在开发数据访问层DAO之前,先在eneity包下写一个实体类DisussPost,用来封装表里的数据。开发流程示意图

package com.nowcoder.community.entity;
import java.util.Date;
public class DiscussPost {
    private int id;
    private int userId;
    private String title;
    private String content;
    private int type;
    private int status;
    private Date createTime;
    private int commentCount;
    private double score;

②在DAO包下编写DiscussPostMapper接口,提供两个方法

@Mapper
public interface DicussPostMapper {
    List<DiscussPost> selectDiscussPosts(int userId, int offset, int limit);
    //@Param注解用于给参数取别名
    //如果只有一个参数,并且在<if>里使用,则必须加别名
    int selectDiscussPostRows(@Param("userId") int userId);
}

③在mapper文件夹下新建一个DiscussPostMapper的配置文件discusspost-mapper.xml,建立DiscussPostMapper与数据库之间的连接

<?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.nowcoder.community.dao.DicussPostMapper">
    <sql id="selectField">
        id,user_id,title,content,type,status,create_time,comment_count,score
    </sql>
    <select id="selectDiscussPosts" resultType="DiscussPost">
        select <include refid="selectField"></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>

配置好之后就可以在测试类中进行测试了

 @Test
    public void testSelectPosts(){
        List<DiscussPost> list=discussPostMapper.selectDiscussPosts(149,0,10);
        for(DiscussPost post:list){
            System.out.println(post);
        }
        int rows=discussPostMapper.selectDiscussPostRows(149);
        System.out.println(rows);
    }

到这里,数据访问层(DAO)的开发工作就完成了,接下来是业务层(service)的开发
③在service目录下新建一个DiscussPostService类,将DAO包下对应的Mapper注入,并定义业务层中用到的方法

@Service
public class DiscussPostService {
    @Autowired(required = false)
    private DicussPostMapper dicussPostMapper;
    public List<DiscussPost> findDiscussPosts(int userId, int offset, int limit ){
        return dicussPostMapper.selectDiscussPosts(userId, offset, limit);
    }
    public int findDiscussPostRows(int userId){
        return dicussPostMapper.selectDiscussPostRows(userId);
    }
}

findDiscussPosts()方法中返回的是帖子(DiscussPost)当中虽然包含了用户信息(userId),但我们希望返回的内容当中包含完整的用户信息(User类的对象),在service包下新建一个UserService类,提供根据userId获取User对象的服务

@Service
public class UserService {
    @Autowired(required = false)
    private UserMapper userMapper;
    public User findUserById(int id){
        return userMapper.selectById(id);
    }
}

视图层(controller)需要用到一些页面,以及页面所依赖的样式文件,将准备好的页面及静态文件拷贝进来
④在controller包下新建一个HomeController类,注入相关的service,并增加一个处理请求的方法(注意声明方法的访问路径)

@Controller
public class HomeController {
    @Autowired
    private DiscussPostService discussPostService;
    @Autowired
    private UserService userService;
    @RequestMapping(path = "/index",method = RequestMethod.GET )
    public String getIndexPage(Model model, Page page){
        //方法调用前,springMVC会自动实例化Model和Page,并将Page注入Model
        //所以在thymeleaf中可以直接访问Page对象中的数据
        page.setRows(discussPostService.findDiscussPostRows(0));
        page.setPath("/index");
        List<DiscussPost> list = discussPostService.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";
    }
}

⑤接下来配置controller中用到的网页模板**.html**文件,部分代码如下

<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
	<link rel="icon" href="https://static.nowcoder.com/images/logo_87_87.png"/>
	<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" crossorigin="anonymous">
	<link rel="stylesheet" th:href="@{/css/global.css}" />
	<title>牛客网-首页</title>
</head>

配置好之后的效果图如下
社区首页⑥在开发分页功能,在entity包下新建一个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(limit >= 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;
    }
    /**
     * 获取当前页的起始行
     */
    public int getOffset(){

        return (current-1)*limit;
    }
    /**
     * 获取总页数
     */
    public int getTotal(){
        if(rows % limit == 0){
            return rows/limit;
        }else{
            return rows/limit+1;
        }
    }
    /**
     * 获取起始页码
     */
    public int getFrom(){
        int from=current-2;
        return from<1 ? 1 : from;
    }
    /**
     * 获取结束页码
     */
    public int getTo(){
        int to=current+2;
        int total = getTotal();
        return to>total ? total : to;
    }
}

⑦最后回到HomeController中改造相关方法,使其能够支持分页功能,回到**.html**修改分页逻辑


版权声明:本文为zhangdaliya原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。