【论坛java项目】第一章:Spring入门、MyBatis 入门、开发社区首页、项目调试技巧、版本控制

😀如果对你有帮助的话😊
🌺为博主点个赞吧 👍
👍点赞是对博主最大的鼓励😋
💓爱心发射~💓

一、课程介绍

技术架构

  • Spring Boot
  • Spring、Spring MVC、MyBatis
  • Redis、Kafka、Elasticsearch——重点(56)
  • Spring Security、Spring Actuator

Redis——操作内存的数据库,性能好,性能高的数据存这个里,提高服务器的处理能力

Kafka——性能最好,最流行的消息队列的服务器
Elasticsearch——性能最好,最流行的搜索引擎
Spring Security——管理系统权限,让每个功能被正确的人访问,提高系统安全性
Spring Actuator——在系统上线以后,对系统进行全面监控,让运维的人随时掌握运行状态
在这里插入图片描述

开发环境

  • 构建工具:Apache Maven
  • 集成开发工具:Intelli IDEA
  • 数据库:MySQL、Redis
  • 应用服务器:Apache Tomcat。
  • 版本控制工具:Gt

在这里插入图片描述

Apache Maven

maven官网

  • 可以帮助我们构建项目、管理项目中的jar包
  • Maven仓库:存放构件的位置-本地仓库:默认是~/.m2/repository-远程仓库:中央仓库、镜像仓库、私服仓库
  • 示例:安装、配置、常用命令

1、maven换阿里云

在这里插入图片描述

2、配置环境变量

在这里插入图片描述

3、maven一些基本命令

maven官网使用说明

查看maven版本

在这里插入图片描述

新建一个项目
mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4 -DinteractiveMode=false
  • archetype:generate:以模板原型方式生成文件
  • DgroupId:组织名称
  • DartifactId:项目名称
  • DarchetypeArtifactId:版本
  • DinteractiveMode:是否启用交互模式
mvn archetype:generate -DgroupId=com.blue.mavendemo1 -DartifactId=mavendemo1 -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4 -DinteractiveMode=false

在这里插入图片描述
成功是这样
在这里插入图片描述

编译项目
J:\wok\workspace>cd mavendemo1
J:\wok\workspace\mavendemo1>mvn compile

在这里插入图片描述
生成:
在这里插入图片描述

二、spring boot

在这里插入图片描述

包整合:解决包太多的问题

spring initializr

在这里插入图片描述

在这里插入图片描述

<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-aop</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

Spring Boot入门示例

Spring Boot核心作用

  • 起步依赖、自动配置、端点监控

示例

  • 一个简单的处理客户端请求案例

在这里插入图片描述

在这里插入图片描述

改tomacat端口

在这里插入图片描述

写一个网页

@Controller
@RequestMapping("/alpha")
public class AlphaController {

    @RequestMapping("/hello")
    @ResponseBody
    public String sayHello() {
        return "Hello Spring Boot.";
    }

}

改端口号:

server.port=8081
server.servlet.context-path=/community

结果:
在这里插入图片描述

三、Spring入门

3.1、Spring全家桶

  • Spring Framework
  • Spring Boot
  • Spring Cloud
  • Spring Cloud Data Flow

在这里插入图片描述

IoC、AOP:

  • 管理对象的一种思想
  • ioc 面向对象
  • aop 面向切片

3.2、Spring IOC

在这里插入图片描述

  • 减少耦合度
dao层

@Primary:优先调用、装配

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

service层

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

scope

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

装配其他人/jar包里的bean

  • 自己写一个配置类
  • 在配置类中通过bean注解进行声明
config

在这里插入图片描述
在这里插入图片描述
测试
在这里插入图片描述
打印当前日期在这里插入图片描述
在这里插入图片描述

总结
  • controller处理浏览器的请求
  • controller调用业务组件service
  • service调用dao
  • 依赖注入的方式去实现

service调用dao

在这里插入图片描述
在这里插入图片描述

controller调用业务组件service

在这里插入图片描述

3.3、Spring MVC

在这里插入图片描述

HTTP——超文本传输协议
HyperText Transfer Protocol

https://developer.mozilla.org/zh-CN/

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
get请求传参数:

  • 明面上传,参数写到网址
  • 传的参数数据量有限制

post请求:

    // POST请求
    @RequestMapping(path = "/student", method = RequestMethod.POST)
    @ResponseBody
    public String saveStudent(String name, int age) {
        System.out.println(name);
        System.out.println(age);
        return "success";
    }

在这里插入图片描述

在这里插入图片描述

如何向浏览器返回响应数据?——html

(以前是字符串string,现在要动态的html)

  • 两种方式
  • 推荐第二种
    // 响应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;
    }
    @RequestMapping(path = "/school", method = RequestMethod.GET)
    public String getSchool(Model model) {
        model.addAttribute("name", "北京大学");
        model.addAttribute("age", 80);
        return "/demo/view";
    }

模板需要写出来

  • 创建 html

在这里插入图片描述

  • 声明是模板,不是普通的html
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<!DOCTYPE html>
<!--声明是模板-->
<html lang="en" xmlns:th="http://www.thymeleaf.org">

<head>
    <meta charset="UTF-8">
    <title>Teacher</title>
</head>
<body>
    <!--p的文本等于其中的变量-->
    <p th:text="${name}"></p>
    <p th:text="${age}"></p>
</body>
</html>

在这里插入图片描述

响应JSON数据(异步请求)

例子:
在这里插入图片描述

    // 响应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;
    }

JSON字符串

在这里插入图片描述
在这里插入图片描述
多个相似数据结构情况

   @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;
    }

在这里插入图片描述

四、MyBatis 入门

4.1、安装MySQL

在这里插入图片描述
配置文件
在这里插入图片描述

在这里插入图片描述

修改密码
在这里插入图片描述
在这里插入图片描述
导入数据
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

4.2、mybatis

mybatis官方文档
mybatis-spring
在这里插入图片描述

  • 前三个组件整合了

添加依赖

在这里插入图片描述

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>8.0.16</version>
		</dependency>
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>2.0.1</version>
		</dependency>

添加配置文件

在这里插入图片描述
在这里插入图片描述

# DataSourceProperties
# 数据库驱动
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# mysql连接路径———— ip地址端口号、库名、编码、不启用安全连接、服务器时区
spring.datasource.url=jdbc:mysql://localhost:3306/community?characterEncoding=utf-8&useSSL=false&serverTimezone=Hongkong
spring.datasource.username=root
spring.datasource.password=l
# 连接池性能最好的
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
# 连接池最大的连接数
spring.datasource.hikari.maximum-pool-size=15
spring.datasource.hikari.minimum-idle=5
# 超时时间-等多久关掉
spring.datasource.hikari.idle-timeout=30000

# MybatisProperties
# xml文件存放位置
mybatis.mapper-locations=classpath:mapper/*.xml
# 声明实体类中的包名,封装表中的数据
mybatis.type-aliases-package=com.nowcoder.community.entity
# 自动生成主键
mybatis.configuration.useGeneratedKeys=true
# 表中的字段和类名去匹配  toCame  to came
mybatis.configuration.mapUnderscoreToCamelCase=true

添加SQL代码

在这里插入图片描述

package com.nowcoder.community.entity;

import java.util.Date;

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;

   
}

在这里插入图片描述

package com.nowcoder.community.dao;

import com.nowcoder.community.entity.User;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface UserMapper {

    User selectById(int id);

    User selectByName(String username);

    User selectByEmail(String email);

    int insertUser(User user);

    int updateStatus(int id, int status);

    int updateHeader(int id, String headerUrl);

    int updatePassword(int id, String password);

}

在这里插入图片描述

<?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.nowcoder.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>

测试:

在这里插入图片描述

package com.nowcoder.community;

import com.nowcoder.community.dao.UserMapper;
import com.nowcoder.community.entity.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.Date;

@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(classes = CommunityApplication.class)
public class MapperTests {

    @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);
    }

}

五、开发社区首页

在这里插入图片描述

5.1、dao层

DiscussPost

在这里插入图片描述

public class DiscussPost {

    private int id;
    private int userId;
    private String title;      // 帖子 标题
    private String content;    // 帖子 内容
    private int type;          // 帖子 类型
    private int status;         // 帖子 状态  0 1
    private Date createTime;    // 帖子 日期
    private int commentCount;   // 帖子 评论数量
    private doub

DiscussPostMapper——接口

在这里插入图片描述

package com.nowcoder.community.dao;

import com.nowcoder.community.entity.DiscussPost;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import java.util.List;

@Mapper
public interface DiscussPostMapper {

    /*
        userId:主页不显示,每个用户可以查询
        分页需求:
            - offset:每页起始行的行号
            - limit:每页最多显示多少条数据
     */
    List<DiscussPost> selectDiscussPosts(int userId, int offset, int limit);

    // @Param注解用于给参数取别名,
    // 如果只有一个参数,并且在<if>里使用,则必须加别名.
    /*
        查询帖子有多少条数据
     */
    int selectDiscussPostRows(@Param("userId") int userId);

}

discusspost-mapper.xml——mapper

  • SQL代码
    在这里插入图片描述

在这里插入图片描述

<?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.nowcoder.community.dao.DiscussPostMapper">

    <sql id="selectFields">
        id, 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>

MapperTests测试:

在这里插入图片描述

  • 先将mapper注入:
    @Autowired
    private DiscussPostMapper discussPostMapper;
    @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);
    }

结果

在这里插入图片描述

5.2、service层

DiscussPostService

在这里插入图片描述

package com.nowcoder.community.service;

import com.nowcoder.community.dao.DiscussPostMapper;
import com.nowcoder.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);
    }

}

UserService

在这里插入图片描述

package com.nowcoder.community.service;

import com.nowcoder.community.dao.UserMapper;
import com.nowcoder.community.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    public User findUserById(int id) {
        return userMapper.selectById(id);
    }

}

5.3、视图层

复制页面
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

HomeController

package com.nowcoder.community.controller;

@Controller
public class HomeController {

    @Autowired
    private DiscussPostService discussPostService;

    @Autowired
    private UserService userService;

    /*
        访问首页 —— index
        请求方式 —— RequestMethod.GET
        Model —— 携带数据,给模板
        返回给index

        discussPostService.findDiscussPosts(0,0,10); 查询所有用户,从首页,返回10条数据
     */
    @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");

        // DiscussPost:查询到的数据不完整,userId,只是id,不是用户名
        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()); // 从帖子里找 findUserById
                map.put("user", user);
                discussPosts.add(map);   // 装进去
            }
        }
        model.addAttribute("discussPosts", discussPosts);   // 装到 model
        return "/index";
    }

}

在这里插入图片描述

静态资源用这种方式

在这里插入图片描述

	<link rel="stylesheet" th:href="@{/css/global.css}" />

	<script th:src="@{/js/global.js}"></script>
	<script th:src="@{js/index.js}"></script>
li模板遍历输出
<li class="media pb-3 pt-3 mb-3 border-bottom" th:each="map:${discussPosts}">

在这里插入图片描述

if标签中不成立,就不会显示
<span class="badge badge-secondary bg-primary" th:if="${map.post.type==1}">置顶</span>

日期格式化
固定语法

<b th:text="${#dates.format(map.post.createTime,'yyyy-MM-dd HH:mm:ss')}">

index.html 总代码

<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
	<link rel="icon" href="https://static.nowcoder.com/images/logo_87_87.png"/>
	<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" crossorigin="anonymous">
	<link rel="stylesheet" th:href="@{/css/global.css}"/>
	<title>牛客网-首页</title>
</head>
<body>
<div class="nk-container">
	<!-- 头部 -->
	<header class="bg-dark sticky-top">
		<div class="container">
			<!-- 导航 -->
			<nav class="navbar navbar-expand-lg navbar-dark">
				<!-- logo -->
				<a class="navbar-brand" href="#"></a>
				<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
					<span class="navbar-toggler-icon"></span>
				</button>
				<!-- 功能 -->
				<div class="collapse navbar-collapse" id="navbarSupportedContent">
					<ul class="navbar-nav mr-auto">
						<li class="nav-item ml-3 btn-group-vertical">
							<a class="nav-link" href="index.html">首页</a>
						</li>
						<li class="nav-item ml-3 btn-group-vertical">
							<a class="nav-link position-relative" href="site/letter.html">消息<span class="badge badge-danger">12</span></a>
						</li>
						<li class="nav-item ml-3 btn-group-vertical">
							<a class="nav-link" href="site/register.html">注册</a>
						</li>
						<li class="nav-item ml-3 btn-group-vertical">
							<a class="nav-link" href="site/login.html">登录</a>
						</li>
						<li class="nav-item ml-3 btn-group-vertical dropdown">
							<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
								<img src="http://images.nowcoder.com/head/1t.png" class="rounded-circle" style="width:30px;"/>
							</a>
							<div class="dropdown-menu" aria-labelledby="navbarDropdown">
								<a class="dropdown-item text-center" href="site/profile.html">个人主页</a>
								<a class="dropdown-item text-center" href="site/setting.html">账号设置</a>
								<a class="dropdown-item text-center" href="site/login.html">退出登录</a>
								<div class="dropdown-divider"></div>
								<span class="dropdown-item text-center text-secondary">nowcoder</span>
							</div>
						</li>
					</ul>
					<!-- 搜索 -->
					<form class="form-inline my-2 my-lg-0" action="site/search.html">
						<input class="form-control mr-sm-2" type="search" aria-label="Search" />
						<button class="btn btn-outline-light my-2 my-sm-0" type="submit">搜索</button>
					</form>
				</div>
			</nav>
		</div>
	</header>

	<!-- 内容 -->
	<div class="main">
		<div class="container">
			<div class="position-relative">
				<!-- 筛选条件 -->
				<ul class="nav nav-tabs mb-3">
					<li class="nav-item">
						<a class="nav-link active" href="#">最新</a>
					</li>
					<li class="nav-item">
						<a class="nav-link" href="#">最热</a>
					</li>
				</ul>
				<button type="button" class="btn btn-primary btn-sm position-absolute rt-0" data-toggle="modal" data-target="#publishModal">我要发布</button>
			</div>
			<!-- 弹出框 -->
			<div class="modal fade" id="publishModal" tabindex="-1" role="dialog" aria-labelledby="publishModalLabel" aria-hidden="true">
				<div class="modal-dialog modal-lg" role="document">
					<div class="modal-content">
						<div class="modal-header">
							<h5 class="modal-title" id="publishModalLabel">新帖发布</h5>
							<button type="button" class="close" data-dismiss="modal" aria-label="Close">
								<span aria-hidden="true">&times;</span>
							</button>
						</div>
						<div class="modal-body">
							<form>
								<div class="form-group">
									<label for="recipient-name" class="col-form-label">标题:</label>
									<input type="text" class="form-control" id="recipient-name">
								</div>
								<div class="form-group">
									<label for="message-text" class="col-form-label">正文:</label>
									<textarea class="form-control" id="message-text" rows="15"></textarea>
								</div>
							</form>
						</div>
						<div class="modal-footer">
							<button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
							<button type="button" class="btn btn-primary" id="publishBtn">发布</button>
						</div>
					</div>
				</div>
			</div>
			<!-- 提示框 -->
			<div class="modal fade" id="hintModal" tabindex="-1" role="dialog" aria-labelledby="hintModalLabel" aria-hidden="true">
				<div class="modal-dialog modal-lg" role="document">
					<div class="modal-content">
						<div class="modal-header">
							<h5 class="modal-title" id="hintModalLabel">提示</h5>
						</div>
						<div class="modal-body" id="hintBody">
							发布完毕!
						</div>
					</div>
				</div>
			</div>

			<!-- 帖子列表 -->
			<ul class="list-unstyled">
				<!--遍历循环,放到 map-->
				<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>
			<!-- 分页 -->
			<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" href="#" 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>

	<!-- 尾部 -->
	<footer class="bg-dark">
		<div class="container">
			<div class="row">
				<!-- 二维码 -->
				<div class="col-4 qrcode">
					<img src="https://uploadfiles.nowcoder.com/app/app_download.png" class="img-thumbnail" style="width:136px;" />
				</div>
				<!-- 公司信息 -->
				<div class="col-8 detail-info">
					<div class="row">
						<div class="col">
							<ul class="nav">
								<li class="nav-item">
									<a class="nav-link text-light" href="#">关于我们</a>
								</li>
								<li class="nav-item">
									<a class="nav-link text-light" href="#">加入我们</a>
								</li>
								<li class="nav-item">
									<a class="nav-link text-light" href="#">意见反馈</a>
								</li>
								<li class="nav-item">
									<a class="nav-link text-light" href="#">企业服务</a>
								</li>
								<li class="nav-item">
									<a class="nav-link text-light" href="#">联系我们</a>
								</li>
								<li class="nav-item">
									<a class="nav-link text-light" href="#">免责声明</a>
								</li>
								<li class="nav-item">
									<a class="nav-link text-light" href="#">友情链接</a>
								</li>
							</ul>
						</div>
					</div>
					<div class="row">
						<div class="col">
							<ul class="nav btn-group-vertical company-info">
								<li class="nav-item text-white-50">
									公司地址:北京市朝阳区大屯路东金泉时代3-2708北京牛客科技有限公司
								</li>
								<li class="nav-item text-white-50">
									联系方式:010-60728802(电话)&nbsp;&nbsp;&nbsp;&nbsp;admin@nowcoder.com
								</li>
								<li class="nav-item text-white-50">
									牛客科技©2018 All rights reserved
								</li>
								<li class="nav-item text-white-50">
									京ICP备14055008号-4 &nbsp;&nbsp;&nbsp;&nbsp;
									<img src="http://static.nowcoder.com/company/images/res/ghs.png" style="width:18px;" />
									京公网安备 11010502036488号
								</li>
							</ul>
						</div>
					</div>
				</div>
			</div>
		</div>
	</footer>
</div>

<script src="https://code.jquery.com/jquery-3.3.1.min.js" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" crossorigin="anonymous"></script>
<script th:src="@{/js/global.js}"></script>
<script th:src="@{js/index.js}"></script>
</body>
</html>

运行结果

在这里插入图片描述
在这里插入图片描述

page 分页

在这里插入图片描述

/**
 * 封装分页相关的信息.
 */
public class Page {

    // 当前页码
    private int current = 1;
    // 显示上限
    private int limit = 10;
    // 数据总数(用于计算总页数)
    private int rows;
    // 查询路径(用于复用分页链接)
    private String path;
getter and setter 修改
    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;
        }
    }

需要的功能
    /**
     * 获取当前页的起始行
     *
     * @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;
    }

html 代码
<!-- 分页 -->
			<!-- 分页 -->
			<nav class="mt-5" th:if="${page.rows>0}" th:fragment="pagination">
				<ul class="pagination justify-content-center">
					<li class="page-item">
						<a class="page-link" th:href="@{${page.path}(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>

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

六、项目调试技巧

在这里插入图片描述

响应状态码的含义

HTTP

200 OK——成功响应

请求成功。成功的含义取决于 HTTP 方法:

  • GET: 资源已被提取并在消息正文中传输。
  • HEAD: 实体标头位于消息正文中。
  • PUT or POST: 描述动作结果的资源在消息体中传输。
  • TRACE: 消息正文包含服务器收到的请求消息。

302 Found——重定向消息

此响应代码表示所请求资源的 URI 已 暂时 更改。未来可能会对 URI进行进一步的改变。因此,客户机应该在将来的请求中使用这个相同的 URI。

404 Not Found——客户端错误响应

服务器找不到请求的资源。在浏览器中,这意味着无法识别 URL。在 API 中,这也可能意味着端点有效,但资源本身不存在。服务器也可以发送此响应,而不是 403 Forbidden,以向未经授权的客户端隐藏资源的存在。这个响应代码可能是最广为人知的,因为它经常出现在网络上。

500 Internal Server Error——服务端错误响应

服务器遇到了不知道如何处理的情况。

服务端断点调试技巧

在这里插入图片描述

客户端断点调试技巧

在这里插入图片描述

设置日志级别,并将日志输出到不同的终端

trace < debug < info < warn < error

在这里插入图片描述


@RunWith(SpringRunner.class)
@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.nowcoder.community=debug
#logging.file=j:/work/workspace/data/nowcoder/community.log

在这里插入图片描述

七、版本控制

**加粗样式**

在这里插入图片描述

Git

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

git status

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

传到牛客Git

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在项目中上传

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

-Blue.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值