第1章 初始Spring Boot【仿牛客网社区论坛项目】

第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;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext=applicationContext;}@Testpublic 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{@Overridepublic 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{@Overridepublic 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;//配置方法@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext=applicationContext;}//测试容器@Testpublic void testApplicationContext(){System.out.println(applicationContext);AlphaDao alphaDao=applicationContext.getBean(AlphaDao.class);System.out.println(alphaDao.select());//MybatisalphaDao= (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作用域@Testpublic 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名字@Beanpublic SimpleDateFormat simpleDateFormat(){return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");}}

测试:getBeanConfig()

    //测试配置类@Testpublic 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;@Autowiredprivate AlphaService alphaService;@Autowiredprivate SimpleDateFormat simpleDateFormat;@Testpublic 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 {@Autowiredprivate 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 {@Autowiredprivate AlphaService alphaService;@RequestMapping("/data")@ResponseBodypublic 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());// GETSystem.out.println(request.getServletPath());// /alpha/httpEnumeration<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)@ResponseBodypublic 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)@ResponseBodypublic 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)@ResponseBodypublic 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)@ResponseBodypublic 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)@ResponseBodypublic 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=Hongkongspring.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 mapperPUBLIC "-//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 userwhere id = #{id}</select><select id="selectByName" resultType="User">select <include refid="selectFields"></include>from userwhere username = #{username}</select><select id="selectByEmail" resultType="User">select <include refid="selectFields"></include>from userwhere 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 {@Autowiredprivate UserMapper userMapper;@Testpublic 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);}@Testpublic 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());}@Testpublic 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 mapperPUBLIC "-//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_postwhere status != 2<if test="userId!=0">and user_id = #{userId}</if>order by type desc, create_time desclimit #{offset}, #{limit}</select><select id="selectDiscussPostRows" resultType="int">select count(id)from discuss_postwhere status != 2<if test="userId!=0">and user_id = #{userId}</if></select></mapper>
测试Dao层

新增:MapperTest.testSelectPosts()

    @Testpublic 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 {@Autowiredprivate 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{@AutowiredUserMapper 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 {@Autowiredprivate DiscussPostService discussPostService;@Autowiredprivate 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 - limitreturn (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);@Testpublic 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

最后

这篇博客能写好的原因是:站在巨人的肩膀上

这篇博客要写好的目的是:做别人的肩膀

开源:为爱发电

学习:为我而行

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/701734.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何利用3D可视化大屏提升信息展示效果?

老子云3D可视化平台https://www.laozicloud.com/ 引言 在信息爆炸的时代&#xff0c;如何有效地传达和展示信息成为了各行各业的一大挑战。传统的平面展示方式已经无法满足人们对信息展示的需求&#xff0c;3D可视化大屏应运而生&#xff0c;成为了提升信息展示效果的利器。本…

JavaScript异步编程——10-async异步函数【万字长文,感谢支持】

异步函数&#xff08;用 async 声明的函数&#xff09; 异步函数的定义 使用async关键字声明的函数&#xff0c;称之为异步函数。在普通函数前面加上 async 关键字&#xff0c;就成了异步函数。语法举例&#xff1a; // 写法1&#xff1a;函数声明的写法async function foo1(…

Centos 6.10 安装oracle10.2.0.1

由于阿里云机房要下架旧服务器&#xff0c;单位未购买整机迁移服务&#xff0c;且业务较老不兼容Oracle11g&#xff0c;所以新购买一台新服务器进行安装Oracle10.2.0.1 &#xff0c;后续再将数据迁移到新服务器上。 对外ip 内部ip 数据库版本 操作系统版本 实例名 源库 1…

风电功率预测 | 基于PSO-BP神经网络实现风电功率预测(附matlab完整源码)

风电功率预测 风电功率预测完整代码风电功率预测 基于粒子群优化算法(Particle Swarm Optimization, PSO)的BP神经网络是一种常见的方法,用于实现风电功率预测。下面是一个基于PSO-BP神经网络实现风电功率预测的一般步骤: 数据准备:收集与风电场发电功率相关的数据,包括…

sd卡修复方法

如何修复损坏或损坏的SanDisk设备 1.使用命令提示符修复损坏的SanDisk SD卡 按“Windows”按钮&#xff0c;键入“command”并按Enter键现在&#xff0c;使用文件资源管理器窗口中的垂直三个菜单选择“此设备”&#xff0c;查看存储卡字母切换到命令提示符窗口并键入“chkdsk”…

克鲁斯CLOOS机器人维修知识分享

克鲁斯工业机器人是一种高度精密的自动化设备&#xff0c;广泛应用于制造业、物流等领域。为了确保机器人的正常运行&#xff0c;了解一些基本的CLOOS工业机械手维修知识是必不可少的。 【常见CLOOS机械臂故障及解决方法】 1. 机器人无法启动&#xff1a;检查电源是否正常&…

【启程Golang之旅】环境设置、工具安装与代码实践

欢迎来到Golang的世界&#xff01;在当今快节奏的软件开发领域&#xff0c;选择一种高效、简洁的编程语言至关重要。而在这方面&#xff0c;Golang&#xff08;又称Go&#xff09;无疑是一个备受瞩目的选择。在本文中&#xff0c;带领您探索Golang的世界&#xff0c;一步步地了…

3.TCP的三次握手和四次挥手

一、前置知识 TCP是一种面向连接的、可靠的、基于字节流的传输层通信协议。在传输数据前通信双方必须建立连接&#xff08;所谓连接&#xff0c;是指客户端和服务端各自保存一份关于对方的信息&#xff0c;比如ip地址&#xff0c;端口号等&#xff09;。TCP通过三次握手建立一个…

Levenshtein,一个超强的 Python 库!

更多Python学习内容&#xff1a;ipengtao.com 大家好&#xff0c;今天为大家分享一个超强的 Python 库 - Levenshtein。 Github地址&#xff1a;https://github.com/ztane/python-Levenshtein/ 文本相似性在许多领域如自然语言处理、数据清洗和信息检索中都有广泛应用。Python-…

微信支付商户的“商家转账到零钱”产品快速开通指南

微信支付商户的“商家转账到零钱”功能为商家提供了便捷的转账途径&#xff0c;尤其适用于费用报销、员工福利发放、合作伙伴货款或分销返佣等多种场景。那么&#xff0c;如何快速开通这一功能呢&#xff0c;需要快速开通的商户可以联系小编。 首先&#xff0c;确保你的企业已经…

RK3568平台开发系列讲解(SPI篇)spi_dev 驱动分析

🚀返回专栏总目录 文章目录 一、结构体二、API三、spidev驱动分析3.1、init3.2、probe3.3、spidev_write3.4、spidev_read3.5、spidev_open四、spi_register_driver分析五、spi_dev缺点沉淀、分享、成长

基于SVPWM的飞轮控制系统的simulink建模与仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 5.完整工程文件 1.课题概述 基于SVPWM的飞轮控制系统的simulink建模与仿真。SVPWM的核心思想是将逆变器输出的三相电压矢量在两相静止坐标系&#xff08;αβ坐标系&#xff09;中表示&#xff0c;通过控…