Spring是什么?
Spring是一个于2003 年兴起的一个轻量级开源Java开发框架,由Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》。Spring是为了解决企业级应用开发的复杂性而创建的,使用Spring可以让简单的JavaBean实现之前只有EJB才能完成的事情。但是Spring不仅仅局限于服务器端开发,任何Java应用都能在简单性、可测试性和松耦合性等方面从Spring中获益。
Spring官网:Spring | Home
SpringBoot是什么?
Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。
SpringBoot有什么用?
简化Spring的配置。
使用Spring开发存在两个十分繁琐的地方;
- 依赖设置繁琐。在开发Spring程序的时候,特别是在整合SSM时,一下就要导入一大推的依赖,让我们的pom.xml文件显得很混乱
- 配置繁琐。在开发Spring程序时,我们通常都需要手动去编写配置类或配置文件,比如:Spring的配置文件、SpringMVC的配置文件,配置文件需要配置的东西也很多,但是大部分的东西都是可以服用的,这就显得繁琐
Spring的核心功能:
- 起步依赖(简化依赖配置):依赖配置的书写简化就是靠这个起步依赖达成的
- 自动配置(简化常用工程相关配置):配置过于繁琐,使用自动配置就可以做响应的简化,但是内部还是很复杂的,后面具体展开说
- 辅助功能(内置服务器,……):除了上面的功能,其实SpringBoot程序还有其他的一些优势,比如我们没有配置Tomcat服务器,但是能正常运行,这是SpringBoot程序的一个可以感知到的功能,也是SpringBoot的辅助功能之一。一个辅助功能都能做的这么6,太牛了
SpringBoot的优点:
避免版本冲突。当一个项目使用了多个技术时,如果版本不选择正确,就会发生冲突,而SpringBoot通过parent
提供了很多套技术搭配,然后我们只需要通过stater
直接引入你想要的一套就行了,此时就只需要引入一个stater依赖就可以了,通过依赖传递能够引入这一套技术所有的依赖,不用像以前一样写一个Spring程序,要搞得pom.xml很混乱、臃肿
注意:praent
的目的是避免依赖冲突,它提供很多套技术组合;stater
的目的是减少依赖配置,只需要依赖一个stater,通过依赖传递,可以使用到其它的依赖
SpringBoot如何用?
参考后文
前置须知:在创建SpringBoot项目之前,必须先安装好Maven
- 推荐使用Maven3.6.1
方式一:直接在IDEA中创建(最常见也是最直接的方式)
备注:这一步需要进行联网,IDEA默认是访问https://start.spring.io
,这是Spring官方提供用来初始化SpringBoot项目的在线工具,它和Github一样在服务器在国外,访问起来有点慢,推荐使用国内的淘宝镜像https://start.aliyun.com/
备注:SpringBoot2版本是当下最稳定的版本
package com.hhxy.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author ghp
* @date 2022/12/16
* @title
* @description
*/
@RestController
@RequestMapping("/test")
public class TestController {
@GetMapping
public String test(){
System.out.println("SpringBoot is running...");
return "SpringBoot is running...";
}
}
使用浏览器访问localhost:8080/test/
,可以看到以下的页面:
Spring和SpringBoot开发SpringMVC程序的比较:
类配置文件 | Spring | SpringBoot |
---|---|---|
pom文件中的坐标 | 手工添加 | 勾选添加 |
web3.0配置类 | 手工制作 | 无 |
Spring/SpringMVC配置类 | 手工制作 | 无 |
控制器 | 手工制作 | 手工制作 |
Spring和SpringBoot相较而言,更加简化、精炼,现在市面上大量开发Java程序的都是选择SpringBoot
方式二:在Spring光网初始化一个SpringBoot工程
直接在SpringBoot的官网创建SpringBoot项目(IDEA本质也是使用SpringBoot官网创建Spring Boot项目的)
方式三:手工制作
先创建一个Maven工程,然后手动编写、配置依赖
SpringBoot可以在application.properties文件中进行配置
# 配置服务器端口号
server.port = 80
# 修改banner(banner就是那个控制台的那个Spring图标)
spring.main.banner.mode=off # 关闭banner
spring.banner.image.laction= 图片地址 # 设置banner,回自动识别图片,然后用特殊符号进行转换,替代原来的Spring图标
# 日志
logging.level.root=info # 设置日志级别
详细配置可以参考官方文档:Spring Boot
SpringBoot的配置文件有三种格式,*.properties
(默认)、*.yml
(推荐)、*.yaml
三种配置文件的优先级:从左往右左边的优先级高。相同属性会根据优先级进行覆盖,不同属性则都会保留
YAML(YAML Ain’t a Markup Language、YAML不是一种标记语言,Yet Another Markup Language、仍是一种标记语言),可能你看着这串英文很懵,前一句想表达的意思是YAML的重心是以数据为中心,而不是像其它标记语言一样以标记为中心,后一句想表达的意思是YAML的确是一种标记语言,所以用反向缩略语重命名。它的后缀名通常为.yml
或.yaml
基础语法学习站点:YAML 入门教程 | 菜鸟教程 (runoob.com)
YAML配置文件中的数据可以通过SpEL表达式进行获取
Spring Expression Language(简称 SpEL)是一种功能强大的表达式语言,支持运行时查询和操作对象图 。表达式语言一般是用最简单的形式完成最主要的工作,以此减少工作量
对于统一数据可以使用引用,类似于xml的${}
引用
temp: student
# 进行引用
temp2: ${temp}
对于转义符的使用:需要将数据使用""
包裹
temp: "a \t b"
使用自动装配,可以将配置文件中所有的数据封装到一个对象中
@Autowire
Environment env;
//得到配置文件中student下的name属性的值
env.getProperty("student.name")
一般开发中,都是需要获取指定的数据的,这里演示一下:
在配置文件中准备好一个待读取的对象:
datasource:
driver: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost/springboot
username: root
password: 123
拓展:解决IDEAyaml配置文件的编写时不给提示
SpringBoot默认就整合了Junit,具体步骤如下:
注意事项:当测试类和引导类属于同一包下,或者属于引导类的子包下,则按照上面的步骤,可以直接进行测试;如果不符合前面所说的要求,则需要添加一个classes
配置项
// 方式一:
@SpringBootTest(classes = 引导类的类名.class)
// 方式二:
@ContextConfiguration(引导类的类名.class)
备注:方式二是原生的Spring注解,SpringBoot的测试类寻找引导类只是表象,本质是要寻找到·@SpringConfiguration
注解,它会现在本包及其子包下寻早是否含有某个类拥有@SpringConfiguration
注解,因为这个类所标识的是类是创建IOC容器的类,测试是需要获取Bean的,这就需要先从IOC容器中获取到Bean,而这个注解是引导类特有的(需要点开@SpringBootApplication
才能看到),所以就需要保障测试类能够找到引导类
前期准备:先准备好一张表,用来测试
Step1:创建SpringBoot工程
和快速入门种创建的方式差不多,只是这里需要勾选一下数据库相关的依赖,而SpringWeb的可以不配置,因为没用到。其实这里也可以不用勾选任何的东西,勾选只是为了让IDEA自动为我们添加所需要的依赖,我们也可以等工程创建完成后,直接手动在pom.xml中进行添加我们所需要的依赖
SpringBooot工程目录结构:
Step2:编写配置文件
# 配置数据连接信息
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/springboot_study?serverTimezone=UTC
username: root
password: 32345678
Step3:编写Java代码
1)编写一个实体类,用来存储数据库中的数据
@Repository
public class Book {
private Integer id;
private String type;
private String name;
private String description;
//为节约篇幅,构造函数、get、set、toString省略了
}
2)编写一个mapper,用来执行SQL
package com.hhxy.dao;
import com.hhxy.domain.Book;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
/**
* @author ghp
* @date 2022/12/17
* @title
* @description
*/
@Mapper
public interface BookDao {
@Select("select * from tb_book where id = #{id}")
public Book getById(Integer id);
}
Step4:编写测试类
package com.hhxy;
import com.hhxy.dao.BookDao;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class Springboot03MybatisApplicationTests {
@Autowired
private BookDao bookDao;
@Test
void contextLoads() {
System.out.println(bookDao.getById(1));
}
}
测试结果:
MyBatisPlus的整合和MyBatis的整合类似,两者唯一不同的就是,在IDEA中无法通过勾选自动添加MyBatis的依赖(因为MyBatisPlus是国人开发的,相较而言中小型公司使用MyBatisPlus的概率要高的多)
Step1:创建SpringBoot工程
此处略,和前面一样,只是这里只能勾选MySQL驱动
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>3.4.3.4version>
dependency>
Step2:编写配置文件
# 配置数据连接信息
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/springboot_study?serverTimezone=UTC
username: root
password: 32345678
# 设置表前缀(MyBatisPlus会自动将数据库中所有表的前缀给去掉)
mybatis-plus:
global-config:
db-config:
table-prefix: tb_
Step3:编写Java代码
1)编写实体类
略,和前面一样
2)编写Mapper
package com.hhxy.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.hhxy.domain.Book;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
/**
* @author ghp
* @date 2022/12/17
* @title
* @description
*/
@Mapper
public interface BookDao extends BaseMapper<Book> {
}
备注:BaseMapper是MyBatisPlus提供的一个类,它里面含有很多常用的方法
Step4:测试
package com.hhxy;
import com.hhxy.dao.BookDao;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class SpringbootApplicationTests {
@Autowired
private BookDao bookDao;
@Test
void contextLoads() {
System.out.println(bookDao.selectById(1));
}
}
测试结果:
Step1:创建SpringBoot项目
和前面一致,需要勾选上MyBatis和MySQL相关依赖,Druid的依赖需要手动导入
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druid-spring-boot-starterartifactId>
<version>1.2.6version>
dependency>
Step2:编写配置文件
# 配置数据连接信息
# 方式一:
#spring:
# datasource:
# driver-class-name: com.mysql.cj.jdbc.Driver
# url: jdbc:mysql://localhost:3306/springboot_study?serverTimezone=UTC
# username: root
# password: 32345678
# type: com.alibaba.druid.pool.DruidDataSource
# 方式二:(推荐使用)
spring:
datasource:
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/springboot_study?serverTimezone=UTC
username: root
password: 32345678
Step3:编写Java代码
1)编写实体类,略
2)编写Mapper,略
Step4:测试
略……
主要实现了SSMP的整合,实现了对tb_book表的增删改查、分页展示数据,期间遇到两个bug,都是数据不同步问题:
多线程操作,一个页面删除数据,另一个页面没有来得及刷新,就去操作已删除的数据,就会导致没有反应,
此时我们的做法是,利用finally的特点,将刷新操作(this.getAll())操作放入其中,当页面发生异常时就进行刷新
当最后一页只有一条数据时,我们将他删除,但是去执行查询操作时,当前页码仍然是之前的最后一页的页码,这就导致查询出来的数据为null,解决方法有两个
- 前端:我们在执行查询操作时,先对当前页码和最大页码进行一个比较,如果当前页码>最大页码,我们就重新调用一下查询操作
- 后端:如果当前页码>最大页码,我们就重新调用一下查询操作
示例:
参考资料:
- 黑马程序员SpringBoot2全套视频教程,springboot零基础到项目实战(spring boot2完整版)_哔哩哔哩_bilibili