1.4 防牛客社区--开发社区首页

开发社区首页

一次请求流程

在这里插入图片描述

Dao层

1、先写entity中的实体类

  • 依据数据库中表的字段建立相应的属性,并且生成其get和set方法,以及toString方法;

2、编写对应的Mapper接口,规定需要实现的方法

  • selectDiscussPosts查询帖子,参数userid,offset-起始页,limit-每一页显示的数据
  • userid==0表示首页查询,==其他值表示查询个人主页的帖子
  • countDiscussPosts–表示查询一共有多少帖子,去除被拉黑的帖子,为了下一步的分页
@Mapper
public interface DiscussPostMapper {
    //查询从offset开始每页limit条数据的帖子信息
    List<DiscussPost> selectDiscussPosts(int userId,int offset,int limit);
    //查询一共有多少条帖子
    //@Param给参数取一个别名  当只有一个参数并且需要在<if>中使用就必须要加注解
    int countDiscussPosts(@Param("userId")  int userId);
    
}

3、编写Mapper对应的xml文件,编写sql语句

  • 判断标签,如果test中值为false就不会拼接到sql中,否则拼接
<?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.js.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="countDiscussPosts" resultType="int">
        select count(id)
        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>
    
</mapper>

Service层

4、编写与Mapper对应的Service层,实现相应的方法

@Service
public class DiscussPostService {
    @Autowired(required = false)
    private DiscussPostMapper discussPostMapper;

    //查询从offset开始每页limit条数据的帖子信息
    public List<DiscussPost> findDiscussPosts(int userId, int offset, int limit)
    {
        return discussPostMapper.selectDiscussPosts(userId,offset,limit);
    }
    //查询一共有多少条帖子
    //@Param给参数取一个别名  当只有一个参数并且需要在<if>中使用就必须要加注解
    public int countDiscussPosts(@Param("userId")  int userId)
    {
        return discussPostMapper.countDiscussPosts(userId);
    }
}
  • 为了把用户表和帖子表相关联,通过userid查询到username 可以有两种办法
  • 1、在写sql查询的时候通过语句把查询到username返回;
  • 2、在查询到帖子后通过userService层的方法查询到user,在返回其User对象,从而获得其它详细信息;一般使用这种方法,代码比较直观,使用redis缓存数据会更加方便
@Service
public class UserService {
    @Autowired(required = false)
    private UserMapper userMapper;
    
    public User queryUserById(int userId)
    {
        return userMapper.queryById(userId);
    }
    
}

导入前端资源

css,img,js等放在static下 网页放在templates下

在这里插入图片描述

Controller层

  • 编写对应的Controller,调用Service层中的方法;
  • 调用discussPostService找到帖子的前十条数据,并把其放到List集合中;
  • 创建一个新的集合,遍历查询每一条帖子,通过userid找到对应的详细User信息,并且把它们放到map中,最后加入新集合中
  • 把新集合加入到model模型中
  • 返回主页面
@Controller
public class DiscussPostController {
    @Autowired
    private DiscussPostService discussPostService;
    @Autowired
    private UserService userService;

    @RequestMapping(value = "/index",method = RequestMethod.GET)
    public String getIndexPage(Model model)
    {
        //获取帖子数据
        List<DiscussPost> list = discussPostService.findDiscussPosts(0, 0, 10);
        //创建新集合
        List<Map<String,Object>> discussPosts=new ArrayList<>();
        //遍历list
        if(list!=null)
        {
            for(DiscussPost post:list)
            {
                Map<String,Object> map=new HashMap<>();
                map.put("post",post);
                User user = userService.queryUserById(post.getUserId());
                map.put("user",user);
                discussPosts.add(map);
            }
        }
        model.addAttribute("discussPosts",discussPosts);
        return "/index";


    }
}

Thymeleaf

  • 声明Thymeleaf

  • 绝对路径不需要修改,相对路径需要修改防止找不到资源 方法是,把相对路径用@{}包起来,这样就会寻找static下的路径

  • <link rel="stylesheet" th:href="@{/css/global.css}" />
    

在这里插入图片描述

  • 使用utext会把转义字符进行相应的转义,text则不会

  • 对li标签进行each循环

  • <li class="media pb-3 pt-3 mb-3 border-bottom" th:each="map:${discussPosts}">
    
<li class="media pb-3 pt-3 mb-3 border-bottom" th:each="map:${discussPosts}">
   <a href="site/profile.html">
      <img th:src="${map.user.headerUrl}" class="mr-4 rounded-circle" alt="用户头像" style="width:50px;height:50px;">
   </a>
   <div class="media-body">
      <h6 class="mt-0 mb-3">
         <a href="site/discuss-detail.html" th:utext="${map.post.title}"></a>
         <span class="badge badge-secondary bg-primary" th:if="${map.post.type==1}" >置顶</span>
         <span class="badge badge-secondary bg-danger" th:if="${map.post.status==1}">精华</span>

      </h6>
      <div class="text-muted font-size-12">
         <u class="mr-3" th:utext="${map.user.username}"></u> 发布于 <b th:text="${#dates.format(map.user.createTime,'yyyy-mm-dd HH:mm:ss')}"></b>
         <ul class="d-inline float-right">
            <li class="d-inline ml-2">赞 11</li>
            <li class="d-inline ml-2">|</li>
            <li class="d-inline ml-2">回帖 7</li>
         </ul>
        </div>
   </div>
</li>
  • Thymeleaf的日期格式化工具,dates.format
<u class="mr-3" th:utext="${map.user.username}"></u> 发布于 <b th:text="${#dates.format(map.user.createTime,'yyyy-mm-dd HH:mm:ss')}"></b>

分页组件开发

实现分页的思路:

浏览器和服务器之间:

  1. 从浏览器传回的参数得知当前页码和显示上限,即每一页最多显示几条数据;
  2. 要有查询路径,即点击分页跳转的页面路径;

跟数据库相关的操作

  1. 告诉数据库查询的offset起始行数,和limit
  2. offset通过当前页的页码计算得出 公式 offset=(current-1)*limit

页面显示

  1. 要计算总页数,需要先查询一共有多少的帖子数量,再把帖子数量/limit 就能够得到一共有多少页,如果%取余!=0,总页数等于结果加1;
  2. 显示从多少页到多少页

操作

1、建立page实体类

  • 编写对应属性和方法
  • 增加条件判断
public class Page {
    //当前页码
    private int current=1;
    //每页显示数量,默认为10
    private int limit=10;
    //帖子总数量
    private int rows;
    //跳转路径
    private String path;
    }

2、增加其他方法

//数据库中offset起始行数计算
public int getOffset()
{
    return (current-1)*limit;
}

//计算一共有多少页
public int pageCount()
{
    if(rows%limit==0) {
        return rows / limit;
    }else {
        return rows/limit+1;
    }
}

//获取起始页码
public int fromPage()
{
    //如果cur比1大返回cur否则返回1
    int cur=current-2;
    return cur>1?cur:1;
}

//获取结束页码
public int endPage()
{
    int cur=current+2;
    int totalPage=pageCount();
    return cur>totalPage?totalPage:cur;
}

3、修改controller

  • 增加page对象
  • 设置rows和path 修改offset和limit使其为动态
  • 不需要向model中添加page对象 因为方法调用前,SpringMvc会自动实例化Model和Page,并将Page注入Model 所以,在Thymeleaf中可以直接访问Page对象中的数据
@RequestMapping(value = "/index",method = RequestMethod.GET)
public String getIndexPage(Model model, Page page)
{
    //不需要向model中添加page对象  因为方法调用前,SpringMvc会自动实例化Model和Page,并将Page注入Model
    // 所以,在Thymeleaf中可以直接访问Page对象中的数据
    //获取总行数
    page.setRows(discussPostService.countDiscussPosts(0));
    page.setPath("/index");

    //获取帖子数据
    List<DiscussPost> list = discussPostService.findDiscussPosts(0, page.getOffset(), page.getLimit());
    //创建新集合
    List<Map<String,Object>> discussPosts=new ArrayList<>();
    //遍历list
    if(list!=null)
    {
        for(DiscussPost post:list)
        {
            Map<String,Object> map=new HashMap<>();
            map.put("post",post);
            User user = userService.queryUserById(post.getUserId());
            map.put("user",user);
            discussPosts.add(map);
        }
    }
    model.addAttribute("discussPosts",discussPosts);
    return "/index";


}

4、修改分页

  • 首先判断rows即帖子数量是否大于0,小于则不显示分页
  • 修改首页末页 修改current的值
  • 修改上一页下一页,使current的值减一加一
  • 循环每一页,使用Thymeleaf的numbers工具,生成一组连续的数字,遍历
  • 当页数为第一页和最后一页的时候,把上一页和下一页的按钮变成灰色
  • 判断当前页数,修改active点亮当前页面
<!-- 分页 -->
<nav class="mt-5"  th:if="${page.rows>0}">
   <ul class="pagination justify-content-center">
      <li class="page-item">
         <a class="page-link" th:href="@{${page.path}(current=1)}">首页</a>
      </li>
      <li th:class="|page-item ${page.current==1?'disabled':''}|">
         <a class="page-link" th:href="@{${page.path}(current=${page.current-1})}">上一页</a>
      </li>
      <li th:class="|page-item ${page.current==i?'active':''}|"  th:each="i:${#numbers.sequence(page.fromPage(),page.endPage())}">
         <a class="page-link" th:href="@{${page.path}(current=${i})}"  th:text="${i}">1</a>
      </li>
      <li th:class="|page-item ${page.current==page.pageCount()?'disabled':''}|">
         <a class="page-link" th:href="@{${page.path}(current=${page.current+1})}">下一页</a>
      </li>
      <li class="page-item">
         <a class="page-link" th:href="@{${page.path}(current=${page.pageCount()})}">末页</a>
      </li>
   </ul>
</nav>

debug:

1、org.apache.ibatis.binding.BindingException: Parameter not found,使用@Param注解与不使用@Param注解

因为在Mapper的xml的Sql语句中写了多余的参数limit #{offset},#{limit}

2、别忘记修改标签属性加上th:

th:class="|page-item ${page.current==1?'disabled':''}|"

tem">
末页

```

debug:

1、org.apache.ibatis.binding.BindingException: Parameter not found,使用@Param注解与不使用@Param注解

因为在Mapper的xml的Sql语句中写了多余的参数limit #{offset},#{limit}

2、别忘记修改标签属性加上th:

th:class="|page-item ${page.current==1?'disabled':''}|"
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值