码匠社区学习笔记(二)

所需资料

功能主体说明:

  • 问题发布
  • 列表展示
  • 分页(mybatis-plus)

数据库新建表
用户表

CREATE TABLE `user` (
 `fd_id` varchar(30) NOT NULL,
 `fd_name` varchar(200) DEFAULT NULL,
 `fd_token` varchar(36) DEFAULT NULL,
 `gmt_create_time` mediumblob,
 `gmt_alter_time` mediumblob,
 `fd_account_id` varchar(50) DEFAULT NULL,
 `avatar_url` varchar(1000) DEFAULT NULL,
 PRIMARY KEY (`fd_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

问题表

CREATE TABLE `question` (
 `id` varchar(30) NOT NULL,
 `title` varchar(100) DEFAULT NULL,
 `description` text,
 `gmt_create` bigint(20) DEFAULT NULL,
 `gmt_modified` bigint(20) DEFAULT NULL,
 `creator` varchar(30) DEFAULT NULL,
 `comment_count` int(11) DEFAULT '0',
 `view_count` int(11) DEFAULT '0',
 `like_count` int(11) DEFAULT '0',
 `tag` varchar(256) DEFAULT NULL,
 PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

新建User model对象

package com.majiang.community.model;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;

/**
* @date 2022-04-20
*/
@Data
public class User {
   @TableId(value = "fd_id",type = IdType.ID_WORKER_STR)
   private String fdId;
   /**
    * 姓名
    */
   private String fdName;
   /**
    * 账号id
    */
   private String fdAccountId;
   /**
    * 授权标识
    */
   private String fdToken;
   /**
    * 图片地址
    */
   private String avatarUrl;
   /**
    * 创建时间
    */
   private Long gmtCreateTime;
   /**
    * 修改时间
    */
   private Long gmtAlterTime;

}


新建Question 对象

package com.majiang.community.model;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;

/**
* @date 2022-04-21
*/
@Data
public class Question {
   @TableId(value = "id",type = IdType.ID_WORKER_STR)
   private String id;
   /**
    * 标题
    */
   private String title;
   /**
    * 描述
    */
   private String description;
   /**
    * 创建时间
    */
   private Long gmtCreate;
   /**
    * 修改时间
    */
   private Long gmtModified;
   /**
    * 创建人
    */
   private String creator;
   /**
    * 评论量
    */
   private Integer commentCount;
   /**
    * 查看量
    */
   private Integer viewCount;
   /**
    * 收藏量
    */
   private Integer likeCount;
   /**
    * 标签
    */
   private String tag;
}

QuestionDTO

package com.majiang.community.dto;

import com.majiang.community.model.User;
import lombok.Data;

/**
 * @date 2022-04-22
 */
@Data
public class QuestionDTO {
    private String id;
    private String title;
    private String description;
    private Long gmtCreate;
    private Long gmtModified;
    private String creator;
    private Integer commentCount;
    private Integer viewCount;
    private Integer likeCount;
    private String tag;
    private User user;
}

**UserMapper **

package com.majiang.community.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.majiang.community.model.User;

public interface UserMapper  extends BaseMapper<User> {
}

***QuestionMapper ***

package com.majiang.community.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.majiang.community.model.Question;


public interface QuestionMapper extends BaseMapper<Question> {
}

问题发布 PublishController

package com.majiang.community.controller;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.majiang.community.mapper.QuestionMapper;
import com.majiang.community.mapper.UserMapper;
import com.majiang.community.model.Question;
import com.majiang.community.model.User;
import com.majiang.community.util.CookieUtil;
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 org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;

import javax.servlet.http.HttpServletRequest;

/**
 * @date 2022-04-21
 */
@Controller
public class PublishController {
    @Autowired
    private  CookieUtil cookieUtil;
    @Autowired(required = false)
    private QuestionMapper questionMapper;
    @Autowired(required = false)
    private UserMapper userMapper;
    @GetMapping("/publish")
    public String createQuestion(HttpServletRequest request){
        String cookieValue = cookieUtil.getCookieValue(request);
        if(StrUtil.isEmpty(cookieValue)){
            return "index";
        }
        return "publish";
    }

    @PostMapping("/publish")
    public String saveQuestion(@RequestParam(name = "title")String title,
                               @RequestParam(name="description")String description,
                               @RequestParam(name = "tag")String tag,
                               HttpServletRequest request,
                               Model model){
        model.addAttribute("title", title);
        model.addAttribute("description", description);
        model.addAttribute("tag", tag);
        if(StrUtil.isEmpty(title)){
            model.addAttribute("error", "标题不能为空");
            return "publish";
        }
        if(StrUtil.isEmpty(description)){
            model.addAttribute("error", "问题描述不能为空");
            return "publish";
        }
        if(StrUtil.isEmpty(tag)){
            model.addAttribute("error", "标签不能为空");
            return "publish";
        }
        String cookieValue = cookieUtil.getCookieValue(request);
        QueryWrapper queryWrapper=new QueryWrapper();
        queryWrapper.eq("fd_token", cookieValue);
        User user = userMapper.selectOne(queryWrapper);
        Question question=new Question();
        question.setTitle(title);
        question.setDescription(description);
        question.setTag(tag);
        question.setCreator(user.getFdAccountId());
        question.setGmtCreate(System.currentTimeMillis());
        question.setGmtModified(System.currentTimeMillis());
        questionMapper.insert(question);
        return "redirect:/";
    }
}

问题添加成功回调首页
在首页显示问题列表

package com.majiang.community.controller;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.majiang.community.dto.QuestionDTO;
import com.majiang.community.mapper.UserMapper;
import com.majiang.community.model.User;
import com.majiang.community.service.IQuestionService;
import com.majiang.community.util.CookieUtil;
import com.majiang.community.util.PageUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.List;

@Controller
public class IndexController {
    @Autowired(required = false)
    private UserMapper userMapper;

    @Autowired
    private CookieUtil cookieUtil;
    @Autowired
    IQuestionService questionService;

    @Value("${gitee.client.id}")
    private  String client_id;
    @Value("${gitee.redirect_uri}")
    private String redirect_uri;

    @GetMapping("/")
    public String index(@RequestParam(name = "current",defaultValue = "0")long current,
            @RequestParam(name="size",defaultValue = "3")long size, HttpServletRequest request, Model model){

        String cookieValue = cookieUtil.getCookieValue(request);
        if(StrUtil.isNotEmpty(cookieValue)){
            QueryWrapper queryWrapper=new QueryWrapper();
            queryWrapper.eq("fd_token", cookieValue);
            User user = userMapper.selectOne(queryWrapper);
            request.getSession().setAttribute("user", user);
        }else{
            request.getSession().setAttribute("user", null);
        }
        model.addAttribute("client_id", client_id);
        model.addAttribute("redirect_uri",redirect_uri);
        PageUtils page =  questionService.getQuestionPage(current,size);
        model.addAttribute("questionPageList",page);
        //未进行分页
        /*List<QuestionDTO> questionDTOList = questionService.getQuestionList();
        System.out.println(questionDTOList.size());
        model.addAttribute("questionDTOList",questionDTOList);*/
        return "index";
    }
    
}

引入分页插件

package com.majiang.community.config;

import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

/**
 * @date 2022-04-26
 */
@Configuration
@EnableTransactionManagement //开启事务
@MapperScan("com.majiang.community.mapper")
public class MyBatisConfig {
    //引入分页插件
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求  默认false
        paginationInterceptor.setOverflow(true);
        // 设置最大单页限制数量,默认 500 条,-1 不受限制
        paginationInterceptor.setLimit(100);
        return paginationInterceptor;
    }
}

定义接口

package com.majiang.community.service;

import com.majiang.community.dto.QuestionDTO;
import com.majiang.community.util.PageUtils;

import java.util.List;

/**
 * @date 2022-04-22
 */
public interface IQuestionService {

    List<QuestionDTO> getQuestionList();


    PageUtils getQuestionPage(long current, long size);
}

接口实现类

package com.majiang.community.service.spring;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.majiang.community.dto.QuestionDTO;
import com.majiang.community.mapper.QuestionMapper;
import com.majiang.community.mapper.UserMapper;
import com.majiang.community.model.Question;
import com.majiang.community.model.User;
import com.majiang.community.service.IQuestionService;
import com.majiang.community.util.PageUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * @date 2022-04-22
 */
@Service
public class QuestionServiceImp extends ServiceImpl<QuestionMapper,Question> implements IQuestionService {

    @Autowired(required = false)
    QuestionMapper questionMapper;
     @Autowired(required = false)
    UserMapper userMapper;

    @Override
    public List<QuestionDTO> getQuestionList() {
        List<QuestionDTO> questionDTOList=new ArrayList<>();
        List<Question> questionList = questionMapper.selectList(null);
        for(Question question:questionList){
            QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
            userQueryWrapper.eq("fd_account_id", question.getCreator());
            User user = userMapper.selectOne(userQueryWrapper);
            QuestionDTO questionDTO = new QuestionDTO();
            BeanUtils.copyProperties(question, questionDTO);
            questionDTO.setUser(user);
            questionDTOList.add(questionDTO);
        }
        return questionDTOList;
    }

    @Override
    public PageUtils getQuestionPage(long current, long size) {
        Page page=new Page(current,size);
        //查询出所有的问题列表
        IPage iPage = questionMapper.selectPage(page, null);
        List<Question>  questionList= iPage.getRecords();
        //
        List<QuestionDTO> questionDTOList=new ArrayList<>();
        for (Question question:questionList){
            QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
            userQueryWrapper.eq("fd_account_id", question.getCreator());
            User user = userMapper.selectOne(userQueryWrapper);
            QuestionDTO questionDTO = new QuestionDTO();
            BeanUtils.copyProperties(question, questionDTO);
            questionDTO.setUser(user);
            questionDTOList.add(questionDTO);
        }
        iPage.setRecords(questionDTOList);
        return new PageUtils(iPage);
    }
}

分页工具类

package com.majiang.community.util;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.majiang.community.dto.QuestionDTO;
import com.majiang.community.model.Question;
import lombok.Data;
import org.springframework.beans.BeanUtils;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
 * @date 2022-04-26
 */
@Data
public class PageUtils implements Serializable {
    private static final long serialVersionUID = 1L;
    /**
     * 总记录数
     */
    private Integer totalCount;
    /**
     * 每页记录数
     */
    private Integer pageSize;
    /**
     * 总页数
     */
    private Integer totalPage;
    /**
     * 当前页数
     */
    private Integer currPage;
    /**
     * 列表数据
     */
    private List<QuestionDTO> list;
    /**
     *
     */
    private List<Integer> pageNumber;
    /**
     * 分页
     * @param list        列表数据
     * @param totalCount  总记录数
     * @param pageSize    每页记录数
     * @param currPage    当前页数
     */
    public PageUtils(List<QuestionDTO> list, int totalCount, int pageSize, int currPage) {
        this.list = list;
        this.totalCount = totalCount;
        this.pageSize = pageSize;
        this.currPage = currPage;
        this.totalPage = (int) Math.ceil((double) totalCount / pageSize);
        for (int i = 1; i <= 3; i++) {
            if (currPage - i > 0) {
                this.pageNumber.add(0, currPage - i);
            }

            if (currPage + i <= totalPage) {
                this.pageNumber.add(currPage + i);
            }
        }
    }

    /**
     * 分页
     */
    public PageUtils(IPage<QuestionDTO> page) {

        this.list = page.getRecords();
        this.totalCount = (int) page.getTotal();
        this.pageSize = (int) page.getSize();
        this.currPage = (int) page.getCurrent();
        this.totalPage = (int) page.getPages();
        List<Integer> pageNumbers=new ArrayList();
        pageNumbers.add(currPage);
        for (int i = 1; i <= 3; i++) {
            if (this.currPage - i > 0) {
                pageNumbers.add(0, this.currPage - i);
            }
            if (this.currPage + i <= this.totalPage) {
                pageNumbers.add(this.currPage + i);
            }
        }
        this.pageNumber=pageNumbers;
    }
}

定义一个模板 navigation.html

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<body>
<div class="container-fluid" th:fragment="navigation">
    <!-- Brand and toggle get grouped for better mobile display -->
    <div class="navbar-header">
        <button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
                data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
            <span class="sr-only">码匠社区</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
        </button>
        <a class="navbar-brand" href="#">码匠社区</a>
    </div>
    <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">

        <form class="navbar-form navbar-left">
            <div class="form-group">
                <input type="text" class="form-control" placeholder="搜索问题">
            </div>
            <button type="submit" class="btn btn-default">搜索</button>
        </form>

        <ul class="nav navbar-nav navbar-right">
            <li th:if="${session.user !=null}">
                <a href="/publish" class="btn btn-default">发布</a>
            </li>
            <li class="dropdown" th:if="${session.user!=null}">
                <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
                   aria-expanded="false">
                    <span th:text="${session.user.getFdName()}"></span>
                    <span class="caret"></span>
                </a>
                <ul class="dropdown-menu">
                    <li><a href="#">消息中心</a></li>
                    <li><a href="#">个人信息</a></li>
                    <li><a href="#">退出登录</a></li>
                </ul>
            </li>
            <li th:if="${session.user==null}"><a
                    th:href="@{'https://gitee.com/oauth/authorize'+'?client_id='+${client_id}+'&redirect_uri='+${redirect_uri}+'&response_type=code&state=1'}">登录</a>
            </li>
        </ul>
    </div>
</div>
</body>
</html>

** 在index.html中引入模板 th:replace=“navigation::navigation”**

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>码匠问题社区</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <!--<script src="http://apps.bdimg.com/libs/jquery/1.9.1/jquery.min.js"></script>-->
    <!--<script type="text/javascript" src="/js/jquery.js"></script>-->
    <link rel="stylesheet" href="css/bootstrap.min.css"/>
    <link rel="stylesheet" href="css/community.css"/>
    <script src="/js/jquery.min.js"></script>
    <script src="js/bootstrap.min.js"></script>
    <link rel="stylesheet" href="css/bootstrap-theme.min.css"/>

</head>
<body>
<nav class="navbar navbar-default">
    <div class="container-fluid" th:replace="navigation::navigation"></div>
</nav>
<div class="container-fluid main">
    <div class="row">
        <div class="col-md-9 col-md-12 col-sm-12 col-xs-12">
            <h2><span class="glyphicon glyphicon-list"/>发现</h2>
            <hr>
            <div class="media" th:each="questionDTO :${questionPageList.getList()}">
                <div class="media-left">
                    <a href="#">
                        <img class="img-rounded"
                             th:src="${questionDTO.user.getAvatarUrl()}">
                    </a>
                </div>
                <div class="media-body">
                    <h4 class="media-heading" th:text="${questionDTO.getTitle()}"></h4>
                    <span th:text="${questionDTO.tag}"></span><br>
                    <span class="text-desc"><span th:text="${questionDTO.getUser().getFdName()}"></span>发表了文章
                        • <span th:text="${questionDTO.getCommentCount()}"></span> 个评论
                        • <span th:text="${questionDTO.getLikeCount()}"></span> 次浏览
                        •<span th:text="${#dates.format(questionDTO.getGmtCreate(),'yyyy-MM-dd')}"></span>发布
                    </span>
                </div>
            </div>
            <nav aria-label="Page navigation">
                <ul class="pagination">
                    <li th:if="${questionPageList.getCurrPage()!=1}">
                        <a th:href="@{/(current=1,size=${questionPageList.getPageSize()})}" aria-label="Previous">
                            <span aria-hidden="true">&lt;&lt;</span><!--首页-->
                        </a>
                    </li>
                    <li th:if="${questionPageList.getCurrPage()!=1}">
                        <a th:href="@{/(current=${questionPageList.getCurrPage()-1},size=${questionPageList.getPageSize()})}" aria-label="Previous">
                            <span aria-hidden="true">&lt;</span><!--上一页-->
                        </a>
                    </li>
                    <li th:each="page:${questionPageList.getPageNumber()}" th:class="${questionPageList.getCurrPage()==page}?'active' : ''">
                        <a th:href="@{/(current=${page},size=${questionPageList.getPageSize()})}" th:text="${page}"></a>
                    </li>
                    <li th:if="${questionPageList.getCurrPage()!=questionPageList.getTotalPage()}">
                        <a th:href="@{/(current=${questionPageList.getCurrPage()+1},size=${questionPageList.getPageSize()})}" aria-label="Previous">
                            <span aria-hidden="true">&gt;</span><!--下一页-->
                        </a>
                    </li>
                    <li th:if="${questionPageList.getCurrPage()!=questionPageList.getTotalPage()}">
                        <a th:href="@{/(current=${questionPageList.getTotalPage()},size=${questionPageList.getPageSize()})}" aria-label="Previous">
                            <span aria-hidden="true">&gt;&gt;</span><!--尾页-->
                        </a>
                    </li>
                </ul>
            </nav>
        </div>
        <div class="col-md-3 col-md-12 col-sm-12 col-xs-12">
            <h3>问题发起指南</h3>
            • 问题标题: 请用精简的语言描述您发布的问题,不超过25字 <br>
            • 问题补充: 详细补充您的问题内容,并确保问题描述清晰直观, 并提供一些相关的资料<br>
            • 选择标签: 选择一个或者多个合适的标签,用逗号隔开,每个标签不超过10个字<br>
        </div>
    </div>
</div>
</body>
</html>

问题发布页面

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>码匠问题社区</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <link rel="stylesheet" href="css/bootstrap.min.css" />
    <link rel="stylesheet" href="css/community.css">
    <script src="/js/jquery.min.js"></script>
    <script src="js/bootstrap.min.js"></script>
    <link rel="stylesheet" href="css/bootstrap-theme.min.css"/>

</head>
<body>
<nav class="navbar navbar-default">
    <div class="container-fluid" th:replace="navigation::navigation"></div>
</nav>
<div class="container-fluid main">
    <div class="row">
        <div class="col-md-9 col-md-12 col-sm-12 col-xs-12">
            <h2><span class="glyphicon glyphicon-plus"/>发起</h2>
            <hr>
            <form action="/publish" method="post">
                <input type="hidden" name="id" th:value="${id}">
                <div class="form-group">
                    <label for="title">问题标题(简单扼要):</label>
                    <input type="text" class="form-control" th:value="${title}" id="title" name="title"
                           placeholder="问题标题……"
                           autocomplete="off">
                </div>
                <div class="form-group" id="question-editor">
                    <label for="description">问题补充 (必填,请参照右侧提示):</label>
                    <textarea name="description" id="description" th:text="${description}"
                              class="form-control"
                              cols="30"
                              rows="10"></textarea>
                </div>
                <div class="form-group">
                    <label for="title">添加标签:</label>
                    <input type="text" class="form-control" th:value="${tag}" id="tag" name="tag"
                           placeholder="问题标题……">
                </div>
                <div class="container-fluid main ">
                    <div class="row">
                        <div class="col-lg-9 col-md-12 col-sm-12 col-xs-12">
                            <div class="alert alert-danger col-lg-12 col-md-12 col-sm-12 col-xs-12"
                                 th:text="${error}"
                                 th:if="${error != null}">
                            </div>
                        </div>
                        <div class="col-lg-3 col-md-12 col-sm-12 col-xs-12">
                            <button type="submit" class="btn btn-success btn-publish ">
                                发布
                            </button>
                        </div>
                    </div>
                </div>
            </form>
        </div>
        <div class="col-md-3 col-md-12 col-sm-12 col-xs-12">
            <h3>问题发起指南</h3>
            • 问题标题: 请用精简的语言描述您发布的问题,不超过25字 <br>
            • 问题补充: 详细补充您的问题内容,并确保问题描述清晰直观, 并提供一些相关的资料<br>
            • 选择标签: 选择一个或者多个合适的标签,用逗号隔开,每个标签不超过10个字<br>
        </div>
    </div>
</div>
</body>
</html>
  • 24
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值