第1章 初始Spring Boot【仿牛客网社区论坛项目】
- 前言
- 推荐
- 项目总结
- 第1章初识Spring Boot,开发社区首页
- 1.课程介绍
- 2.搭建开发环境
- 3.Spring入门
- 体验IOC容器
- 体验Bean的生命周期
- 体验配置类
- 体验依赖注入
- 体验三层架构
- 4.SpringMVC入门
- 配置
- 体验响应数据
- 体验响应Get请求
- 体验响应Post请求
- 体验响应HTML数据
- 体验响应JSON数据
- 5MyBatis入门
- 配置
- User
- UserMapper
- user-mapper.xml
- 测试:MapperTest
- 设置日志级别
- 6开发社区首页
- DiscussPost
- DiscussPostMapper
- discusspost-mapper.xml
- 测试Dao层
- DiscussPostService
- UserService
- 前端资源准备
- HomeController
- index.html
- Page
- 7项目调试技巧
- 测试:日志功能
- 8版本控制
- 最后
前言
2023-4-30 20:42:51
以下内容源自【Java面试项目】
仅供学习交流使用
推荐
仿牛客网项目【面试】
项目总结
第1章初识Spring Boot,开发社区首页
1.课程介绍
2.搭建开发环境
创建项目,完成搭建
添加依赖
- aspectj aop包
- Spring Web web开发
- Thymeleaf 模板引擎
- Spring Boot DevTools 开发者工具
- 其他:使用时添加
配置application.properties
#ServerProperties
#端口配置
server.port=8080
#路径配置
server.servlet.context-path=/community
创建一个AlphaController
编写sayHello()
@Controller
@RequestMapping("/alpha")
public class AlphaController {
@RequestMapping("/hello")
@ResponseBody//返回字符串
public String sayHello(){
return "Hello Spring Boot.";
}
}
访问:http://localhost:8080/community/alpha/hello
3.Spring入门
修改测试代码
体验IOC容器
ApplicationContext,管理Bean
package com.jsss.community;
@SpringBootTest
@ContextConfiguration(classes = CommunityApplication.class)
class CommunityApplicationTests implements ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext=applicationContext;
}
@Test
public void testApplicationContext(){
System.out.println(applicationContext);
}
}
创建一个Bean
AlphaDAO
package com.jsss.community.dao;
public interface AlphaDao {
String select();
}
两个实现类
AlphaDaoHibernateImpl
package com.jsss.community.dao;
import org.springframework.stereotype.Repository;
@Repository("alphaDaoHibernate")//容器管理 指定Bean名字
public class AlphaDaoHibernateImpl implements AlphaDao{
@Override
public String select() {
return "Hibernate";
}
}
AlphaDaoMybatisImpl
package com.jsss.community.dao;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Repository;
@Repository
@Primary//优先装配
public class AlphaDaoMybatisImpl implements AlphaDao{
@Override
public String select() {
return "Mybatis";
}
}
测试:testApplicationContext()
package com.jsss.community;
import com.jsss.community.dao.AlphaDao;
import org.junit.jupiter.api.Test;
import org.springframework.beans.BeansException;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.test.context.ContextConfiguration;
@SpringBootTest
@ContextConfiguration(classes = CommunityApplication.class)
class CommunityApplicationTests implements ApplicationContextAware {//SpringBoot会进行自动配置
private ApplicationContext applicationContext;
//配置方法
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext=applicationContext;
}
//测试容器
@Test
public void testApplicationContext(){
System.out.println(applicationContext);
AlphaDao alphaDao=applicationContext.getBean(AlphaDao.class);
System.out.println(alphaDao.select());//Mybatis
alphaDao= (applicationContext.getBean("alphaDaoHibernate",AlphaDao.class));
System.out.println(alphaDao.select());//Hibernate
}
}
体验Bean的生命周期
创建AlphaService
package com.jsss.community.service;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
@Service//容器管理
//作用域 单例 多态
//@Scope("singleton")
//@Scope("prototype")
public class AlphaService {
@PostConstruct//IOC容器管理Bean生命周期:初始化
public void init(){
System.out.println("初始化AlphaService");
}
@PreDestroy//IOC容器管理Bean生命周期:销毁
public void destroy(){
System.out.println("销毁AlphaService");
}
}
测试:testBean()
//测试Bean的生命周期
//修改Scope作用域
@Test
public void testBean(){
AlphaService alphaService=applicationContext.getBean(AlphaService.class);
System.out.println(alphaService);
alphaService=applicationContext.getBean(AlphaService.class);
System.out.println(alphaService);
}
体验配置类
添加AlphaConfig
package com.jsss.community.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.text.SimpleDateFormat;
@Configuration
public class AlphaConfig {
//配置类使用Bean注解添加Bean
//方法名就是Bean名字
@Bean
public SimpleDateFormat simpleDateFormat(){
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
}
}
测试:getBeanConfig()
//测试配置类
@Test
public void getBeanConfig(){
SimpleDateFormat simpleDateFormat=applicationContext.getBean(SimpleDateFormat.class);
System.out.println(simpleDateFormat.format(new Date()));
}
体验依赖注入
容器的主动getBean
使用注解@AutoWire
测试:testDI()
@Autowired
@Qualifier("alphaDaoHibernate")//指定Bean名字
private AlphaDao alphaDao;
@Autowired
private AlphaService alphaService;
@Autowired
private SimpleDateFormat simpleDateFormat;
@Test
public void testDI(){
System.out.println(alphaDao);
System.out.println(alphaService);
System.out.println(simpleDateFormat);
}
体验三层架构
Controller–Service–Dao
Service调用Dao
package com.jsss.community.service;
import com.jsss.community.dao.AlphaDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
@Service//容器管理
//作用域 单例 多态
//@Scope("singleton")
//@Scope("prototype")
public class AlphaService {
@Autowired
private AlphaDao alphaDao;
@PostConstruct//IOC容器管理Bean生命周期:初始化
public void init(){
System.out.println("初始化AlphaService");
}
@PreDestroy//IOC容器管理Bean生命周期:销毁
public void destroy(){
System.out.println("销毁AlphaService");
}
public String find(){
return alphaDao.select();
}
}
Controller调用Service
package com.jsss.community.controller;
@Controller
@RequestMapping("/alpha")
public class AlphaController {
@Autowired
private AlphaService alphaService;
@RequestMapping("/data")
@ResponseBody
public String getData(){
return alphaService.find();
}
}
访问:http://localhost:8080/community/alpha/data
4.SpringMVC入门
配置
# ThymeleafProperties
spring.thymeleaf.cache=false
体验响应数据
AlphaController.http()
@RequestMapping("/http")
public void http(HttpServletRequest request, HttpServletResponse response){
//获取请求数据
System.out.println(request.getMethod());// GET
System.out.println(request.getServletPath());// /alpha/http
Enumeration<String> enumeration = request.getHeaderNames();
while (enumeration.hasMoreElements()){
String name = enumeration.nextElement();
String value = request.getHeader(name);
System.out.println(name+": "+value);
}
System.out.println(request.getParameter("code"));//123
// 返回响应数据
response.setContentType("text/html;charset=utf-8");
try (
PrintWriter writer = response.getWriter();
){
writer.write("<h1>牛客网</h1>");
} catch (IOException e) {
e.printStackTrace();
}
}
访问:http://localhost:8080/community/alpha/http?code=123
体验响应Get请求
- 路径拼接
- Restful风格
AlphaController.getStudents()
AlphaController.getStudent()
// GET 请求
// /students?current=1&limit=20
@RequestMapping(path = "/students",method = RequestMethod.GET)
@ResponseBody
public String getStudents(
@RequestParam(name = "current",required = false,defaultValue = "1") int current,
@RequestParam(name = "limit",required = false,defaultValue = "10") int limit){
System.out.println(current);
System.out.println(limit);
return "some students";
}
// /student/123
@RequestMapping(path = "/student/{id}",method = RequestMethod.GET)
@ResponseBody
public String getStudent(@PathVariable("id") int id){
System.out.println(id);
return "a student";
}
访问:http://localhost:8080/community/alpha/students?current=1&limit=20
访问:http://localhost:8080/community/alpha/student/123
体验响应Post请求
新增页面:static/html/student.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>增加学生</title>
</head>
<body>
<form method="post" action="/community/alpha/student">
<p>
姓名:<input type="text" name="name">
</p>
<p>
年龄:<input type="text" name="age">
</p>
<p>
<input type="submit" value="保存">
</p>
</form>
</body>
</html>
AlphaController.save()
// POST请求
@RequestMapping(path = "/student",method = RequestMethod.POST)
@ResponseBody
public String save(String name,int age){
System.out.println(name);
System.out.println(age);
return "success";
}
访问:http://localhost:8080/community/html/student.html
体验响应HTML数据
AlphaController.getTeacher()
//响应HTML数据
@RequestMapping(path = "/teacher",method = RequestMethod.GET)
public ModelAndView getTeacher(){
ModelAndView mav=new ModelAndView();
mav.addObject("name","张三");
mav.addObject("age",30);
mav.setViewName("/demo/view");
return mav;
}
新增页面:template/demo/view.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Teacher</title>
</head>
<body>
<p th:text="${name}"></p>
<p th:text="${age}"></p>
</body>
</html>
访问:http://localhost:8080/community/alpha/teacher
AlphaController.getSchool()
@RequestMapping(path = "/school",method = RequestMethod.GET)
public String getSchool(Model model){
model.addAttribute("name","北京大学");
model.addAttribute("age","80");
return "demo/view";
}
访问:http://localhost:8080/community/alpha/school
体验响应JSON数据
AlphaController.getEmp()
AlphaController.getEmps()
// 响应JSON数据(异步请求)
// Java对象 -> JSON字符串 -> JS对象
@RequestMapping(path = "/emp",method = RequestMethod.GET)
@ResponseBody
public Map<String,Object> getEmp(){
Map<String,Object> emp =new HashMap<>();
emp.put("name","张三");
emp.put("age",23);
emp.put("salary",8000.00);
return emp;
}
@RequestMapping(path = "/emps",method = RequestMethod.GET)
@ResponseBody
public List<Map<String,Object>> getEmps(){
List<Map<String,Object>> list=new ArrayList<>();
Map<String,Object> emp =new HashMap<>();
emp.put("name","张三");
emp.put("age",23);
emp.put("salary",8000.00);
list.add(emp);
emp =new HashMap<>();
emp.put("name","李四");
emp.put("age",24);
emp.put("salary",9000.00);
list.add(emp);
emp =new HashMap<>();
emp.put("name","王五");
emp.put("age",25);
emp.put("salary",10000.00);
list.add(emp);
return list;
}
访问:http://localhost:8080/community/alpha/emp
访问:http://localhost:8080/community/alpha/emps
5MyBatis入门
配置
添加依赖
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.22</version>
</dependency>
<!--mybatis整合spring-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.1</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
</dependency>
添加配置
# DataSourceProperties
# 驱动
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# 路径
spring.datasource.url=jdbc:mysql://localhost:3306/community?characterEncoding=utf-8&useSSL=false&serverTimezone=Hongkong
spring.datasource.username=root
spring.datasource.password=root
#spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.type=com.mysql.cj.jdbc.MysqlDataSource
spring.datasource.hikari.maximum-pool-size=15
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.idle-timeout=30000
# MybatisProperties
mybatis.mapper-locations=classpath:mapper/*.xml
mybatis.type-aliases-package=com.jsss.community.entity
#启用自动自增主键
mybatis.configuration.useGeneratedKeys=true
#开启驼峰命名自动匹配
mybatis.configuration.mapUnderscoreToCamelCase=true
User
新建:/entity/User.java
package com.jsss.community.entity;
import java.util.Date;
import lombok.*;
@AllArgsConstructor
@NoArgsConstructor
@Data
public class User {
private int id;
private String username;
private String password;
private String salt;
private String email;
private int type;
private int status;
private String activationCode;
private String headerUrl;
private Date createTime;
}
UserMapper
新建:/dao/UserMapper.java
package com.jsss.community.dao;
import com.jsss.community.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@Mapper
public interface UserMapper {
User selectById(int id);
User selectByName(String name);
User selectByEmail (String email);
int insertUser(User user);
int updateStatus(@Param("id")int id, @Param("status") int status);
int updateHeader(@Param("id")int id, @Param("headerUrl")String headerUrl);
int updatePassword(@Param("id")int id, @Param("password")String password);
}
user-mapper.xml
新建:/mapper/user-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.jsss.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>
<select id="selectById" resultType="User">
select <include refid="selectFields"></include>
from user
where id = #{id}
</select>
<select id="selectByName" resultType="User">
select <include refid="selectFields"></include>
from user
where username = #{username}
</select>
<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>
测试:MapperTest
新建:test:MapperTest.java
package com.jsss.community;
import com.jsss.community.dao.UserMapper;
import com.jsss.community.entity.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ContextConfiguration;
import java.util.Date;
@SpringBootTest
@ContextConfiguration(classes = CommunityApplication.class)
public class MapperTest {
@Autowired
private UserMapper userMapper;
@Test
public void testSelectUser() {
User user = userMapper.selectById(101);
System.out.println(user);
user = userMapper.selectByName("liubei");
System.out.println(user);
user = userMapper.selectByEmail("nowcoder101@sina.com");
System.out.println(user);
}
@Test
public void testInsertUser() {
User user = new User();
user.setUsername("test");
user.setPassword("123456");
user.setSalt("abc");
user.setEmail("test@qq.com");
user.setHeaderUrl("http://www.nowcoder.com/101.png");
user.setCreateTime(new Date());
int rows = userMapper.insertUser(user);
System.out.println(rows);
System.out.println(user.getId());
}
@Test
public void updateUser() {
int rows = userMapper.updateStatus(150, 1);
System.out.println(rows);
rows = userMapper.updateHeader(150, "http://www.nowcoder.com/102.png");
System.out.println(rows);
rows = userMapper.updatePassword(150, "hello");
System.out.println(rows);
}
}
设置日志级别
# logger
logging.level.com.jsss.community=debug
2023-4-30 23:33:09
6开发社区首页
DiscussPost
新增:entity/DiscussPost.java
package com.jsss.community.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@AllArgsConstructor
@NoArgsConstructor
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;
}
DiscussPostMapper
新增:/dao/DiscussPostMapper.java
package com.jsss.community.dao;
import com.jsss.community.entity.DiscussPost;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface DiscussPostMapper {
List<DiscussPost> selectDiscussPosts(int userId,int offset,int limit);
// @Param注解用于给参数取别名,
// 如果只有一个参数,并且在<if>里使用,则必须加别名.
int selectDiscussPostRows(@Param("userId") int userId);
}
discusspost-mapper.xml
新增:/mapper/discusspost-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.jsss.community.dao.DiscussPostMapper">
<sql id="selectFields">
id, user_id, title, content, type, status, create_time, comment_count, score
</sql>
<sql id="insertFields">
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>
测试Dao层
新增:MapperTest.testSelectPosts()
@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);
}
DiscussPostService
新增:/service/DiscussPostService.java
package com.jsss.community.service;
import com.jsss.community.dao.DiscussPostMapper;
import com.jsss.community.entity.DiscussPost;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class DiscussPostService {
@Autowired
private DiscussPostMapper discussPostMapper;
public List<DiscussPost> findDiscussPosts(int userId, int offset, int limit) {
return discussPostMapper.selectDiscussPosts(userId, offset, limit);
}
public int findDiscussPostRows(int userId) {
return discussPostMapper.selectDiscussPostRows(userId);
}
}
对于帖子:
我们要显示用户名称而不是用户id
有两种解决办法:
- 关联查询
- 在高层添加
UserService
新增:/service/UserService.java
package com.jsss.community.service;
import com.jsss.community.dao.UserMapper;
import com.jsss.community.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService{
@Autowired
UserMapper userMapper;
public User findUserById(int id){
return userMapper.selectById(id);
}
}
前端资源准备
复制静态文件到static下
复制网页到templates
顺便把mail复制进来
mail:将来学习发邮件的模板
HomeController
新增:/controller/HomeController()
package com.jsss.community.controller;
import com.jsss.community.entity.DiscussPost;
import com.jsss.community.entity.User;
import com.jsss.community.service.DiscussPostService;
import com.jsss.community.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Controller
public class HomeController {
@Autowired
private DiscussPostService discussPostService;
@Autowired
private UserService userService;
@RequestMapping(path = "/", method = RequestMethod.GET)
public String root() {
return "forward:/index";
}
@RequestMapping(path = "/index", method = RequestMethod.GET)
public String getIndexPage(Model model) {
List<DiscussPost> list = discussPostService.findDiscussPosts(0, 0, 10);
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";
}
}
index.html
修改html标签
<html lang="en" xmlns:th="http://www.thymeleaf.org">
修改静态路径
<!--前面-->
<link rel="stylesheet" th:href="@{/css/global.css}" />
<!--后面-->
<script th:src="@{/js/global.js}"></script>
<script th:src="@{js/index.js}"></script>
主要修改内容main的部分
修改:帖子列表的部分
静态数据改为动态数据
<!-- 帖子列表 -->
<ul class="list-unstyled">
<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="#" 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.post.createTime,'yyyy-MM-dd HH:mm:ss')}">2019-04-15 15:32:18</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>
</ul>
访问:http://localhost:8080/community/index
Page
分页功能
新增:/entity/Page.java
package com.jsss.community.entity;
/**
* 封装分页相关的信息.
*/
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;
}
/**
* 获取当前页的起始行
*
* @return
*/
public int getOffset() {
// current * limit - limit
return (current - 1) * limit;
}
/**
* 获取总页数
*
* @return
*/
public int getTotal() {
// rows / limit [+1]
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;//超的时候,就按最大页算
}
}
修改:HomeController.getIndexPage()
@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";
}
修改:index.html:分页
<!-- 分页 -->
<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 ${i==page.current?'active':''}|" th:each="i:${#numbers.sequence(page.from,page.to)}">
<a class="page-link" th:href="@{${page.path}(current=${i})}" th:text="${i}">1</a>
</li>
<li th:class="|page-item ${page.current==page.total?'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.total})}">末页</a>
</li>
</ul>
</nav>
</div>
</div>
访问:http://localhost:8080/community/index?current=1
7项目调试技巧
测试:日志功能
新增:test:LoggerTests.java
package com.jsss.community;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ContextConfiguration;
@SpringBootTest
@ContextConfiguration(classes = CommunityApplication.class)
public class LoggerTests {
private static final Logger logger= LoggerFactory.getLogger(LoggerTests.class);
@Test
public void testLogger(){
System.out.println(logger.getName());
logger.debug("debug log");
logger.info("info log");
logger.warn("warn log");
logger.error("error log");
}
}
配置:
# logger
logging.level.com.jsss.community=debug
logging.file.name=E:/work/data/jsss/community.log
添加:/logback-spring.xml
8版本控制
git的使用
git add .
git commit -m "消息"
git push
git status
git reset HEAD
最后
这篇博客能写好的原因是:站在巨人的肩膀上
这篇博客要写好的目的是:做别人的肩膀
开源:为爱发电
学习:为我而行