牛客网项目---1.1.开发首页

分步实现:

1、开发社区首页,显示前10个帖子;

2、开发分页组件,分页显示所有帖子。

一、加载社区首页/index

1、首页:最新/index?orderMode=0;最热:/index?orderMode=1,控制层获取orderMode参数的值,默认值设置为0:

2、分页机制Page page:传入Rows、Path

通过查询帖子总数设置Rows,通过offset、limit、userId、orderMode分页查询帖子列表,若userId等于0,则查询帖子的总数,否则根据userId查询相应自己的帖子。

3、本地缓存Caffeine:初始化热帖列表code=1

初始化帖子总数缓存,因为热帖不会总变,每5分钟计算一次帖子的分数,使用本地缓存存储热帖列表,避免每次都要去数据库进行查询,缓存帖子总数也是为了避免每次都要访问数据库。

用于减小对数据库的访问次数,频繁的访问数据库产生很大的开销,影响程序的执行效率!引入缓存,效率能几何倍递增。

4、数据结构:List>:将每个帖子/评论的post、userID,likeCount封装到map中,再加到list中,传给model,返回给index页面。

5、前端页面:

(1)使用thymeleaf模板引擎处理:xmlns:th:"http://www.thymeleaf.org"

生成动态的HTML,动态的引入css样式,js模板,将头部设置成模板:th:fragment="header",供其他页面复用;

(2)地址链接使用@{},从服务器端传来的参数引用使用${},显示帖子列表时,将传来的List集合进行遍历:

th:each="map:${discussPosts}"来遍历获取${map.user/headerUrl}等其他的用户信息,来显示在index页面上;

(3)分页:后端自动将page封装到mode中,前端直接获取page信息即可,利用总数,当前页,下一页,上一页等分页信息,来进行分页。使用th:fragment="pagination"标签,来让其他的页面复用。

6、热帖排行:从Redis中取出getPostScoreKey键对应的set集合,包含这段时间内变动的postID,通过取出每个postID,进而找到对应的帖子。根据是否精华、点赞数、评论数量计算帖子的权重;帖子分数上面加上一个距离一个固定日期的天数差,保证让新发的帖子尽可能地有争夺热帖的权利;

---------------------------------------------------------------------------------------------------------------------------------

配置数据库和Mybatis:

<!--mybatis-->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.1.3</version>
</dependency>
#数据库
spring:
  datasource:
    username: root
    password: gouhanchi521
    url: jdbc:mysql://localhost:3306/community?allowPublicKeyRetrieval=true&useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.zaxxer.hikari.HikariDataSource
    hikari:
      minimum-idle: 5
      maximum-pool-size: 15
      idle-timeout: 30000
#mybatis
mybatis:
  type-aliases-package: com.nowcoder.community.entity
  mapper-locations: classpath:mapper/*.xml
  configuration:
    use-generated-keys: true
    map-underscore-to-camel-case: true

1.编写Dao层

package com.nowcoder.community.mapper;

import com.nowcoder.community.entity.DiscussPost;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface DiscussPostMapper {
    List<DiscussPost> selectDiscussPosts(int userId,int offset,int limit);

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

2.编写Mapper.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.nowcoder.community.mapper.DiscussPostMapper">

    <select id="selectDiscussPosts" resultType="DiscussPost">
        select * 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>

3.编写业务层

package com.nowcoder.community.service;

import com.nowcoder.community.entity.DiscussPost;
import com.nowcoder.community.mapper.DiscussPostMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class DiscussPostServiceImpl implements DiscussPostService{
    @Autowired
    private DiscussPostMapper discussPostMapper;

    @Override
    public List<DiscussPost> selectDiscussPosts(int userId, int offset, int limit) {
        return discussPostMapper.selectDiscussPosts(userId, offset, limit);
    }

    @Override
    public int selectDiscussPostRows(int userId) {
        return discussPostMapper.selectDiscussPostRows(userId);
    }
}

4.编写Controller层

package com.nowcoder.community.controller;

import com.nowcoder.community.entity.DiscussPost;
import com.nowcoder.community.entity.Page;
import com.nowcoder.community.entity.User;
import com.nowcoder.community.service.DiscussPostServiceImpl;
import com.nowcoder.community.service.UserServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Controller
public class HomeController {
    @Autowired
    private DiscussPostServiceImpl discussPostService;
    @Autowired
    private UserServiceImpl userService;

    @GetMapping("/index")
    public String getIndexPage(Model model, Page page)
    {
        page.setRows(discussPostService.selectDiscussPostRows(0));
        page.setPath("/index");

        List<DiscussPost> list = discussPostService.selectDiscussPosts(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.selectById(post.getUserId());
                map.put("user",user);
                discussPosts.add(map);
            }
        }
        model.addAttribute("discussPosts",discussPosts);
        return "index";
    }
}

5.分页工具类:参数(当前页码、每页的行数、数据总量、查询路径)

package com.nowcoder.community.entity;

public class Page {
    //当前页码
    private int currentPage=1;
    //每页的数量
    private int limit=10;
    //数据总量
    private int rows;
    //查询路径
    private String path;

    public int getCurrentPage() {
        return currentPage;
    }

    public void setCurrentPage(int currentPage) {
        if (currentPage>=1){
            this.currentPage = currentPage;
        }
    }

    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 (currentPage-1)*limit;
    }

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

    //获取起始页
    public int getFromPage(){
        int from=currentPage-2;
        return from<1 ? 1:from;
    }

    //获取结束页
    public int getToPage(){
        int to=currentPage+2;
        int total=getTotalPage();
        return to>total ? total:to;
    }
}
				<!-- 分页 -->
				<nav class="mt-5" th:if="${page.rows>0}" th:fragment="pagination">
					<ul class="pagination justify-content-center">
						<li class="page-item">
							<a class="page-link" th:href="@{${page.path} (currentPage=1)}">首页</a>
						</li>
						<li th:class="|page-item ${page.currentPage==1?'disabled':''}|">
							<a class="page-link" th:href="@{${page.path} (currentPage=${page.currentPage-1})}">上一页</a>
						</li>
						<li th:class="|page-item ${i==page.currentPage?'active':''}|" th:each="i:${#numbers.sequence(page.fromPage,page.toPage)}">
							<a class="page-link" th:href="@{${page.path} (currentPage=${i})}" th:text="${i}">1</a>
						</li>
						<li th:class="|page-item ${page.currentPage==page.totalPage?'disabled':''}|">
							<a class="page-link" th:href="@{${page.path} (currentPage=${page.currentPage+1})}">下一页</a>
						</li>
						<li class="page-item">
							<a class="page-link" th:href="@{${page.path} (currentPage=${page.totalPage})}">末页</a>
						</li>
					</ul>
				</nav>

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值