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

2024-05-15 08:20

本文主要是介绍第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

最后

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

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

开源:为爱发电

学习:为我而行

这篇关于第1章 初始Spring Boot【仿牛客网社区论坛项目】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/991304

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

如何用Docker运行Django项目

本章教程,介绍如何用Docker创建一个Django,并运行能够访问。 一、拉取镜像 这里我们使用python3.11版本的docker镜像 docker pull python:3.11 二、运行容器 这里我们将容器内部的8080端口,映射到宿主机的80端口上。 docker run -itd --name python311 -p