java学习day56(Spring Boot)Spring Boot

news2025/4/19 15:08:09
主要内容:
1.Spring Boot 基本应用
2.Spring Boot 原理深入及源码剖析
3.Spring Boot 数据访问
4.Spring Boot 视图技术
5.Spring Boot 实战演练
6.Spring Boot 项目部署

1. SpringBoot 基本应用
1.1 约定优于配置
Build Anything with Spring Boot Spring Boot is the starting point for
building all Spring-based applications. Spring Boot is designed to get you up and
running as quickly as possible, with minimal upfront configuration of Spring.

 上面是引自官网的一段话,大概是说: Spring Boot 是所有基于 Spring 开发的项目的起点。Spring Boot 的设计是为了让你尽可能快的跑起来 Spring 应用程序并且尽可能减少你的配置文件。

约定优于配置( Convention over Configuration ),又称按约定编程,是一种软件设计范式。
本质上是说,系统、类库或框架应该假定合理的默认值,而非要求提供不必要的配置。
比如说模型中有一个名为User 的类,那么数据库中对应的表就会默认命名为 user 。只有在偏离这一个约定的时候,例如想要将该表命名为person ,才需要写有关这个名字的配置。
比如平时架构师搭建项目就是限制软件开发随便写代码,制定出一套规范,让开发人员按统一的要求进行开发编码测试之类的,这样就加强了开发效率与审查代码效率。所以说写代码的时候就需要按要求命名,这样统一规范的代码就有良好的可读性与维护性了
约定优于配置简单来理解,就是遵循约定
1.2 SpringBoot 概念
1.2.1 Spring 优缺点分析
优点:
Spring Java 企业版( Java Enterprise Edition JEE ,也称 J2EE )的轻量级代替品。无需开发重量级的Enterprise Java Bean( EJB ), Spring 为企业级 Java 开发提供了一种相对简单的方法,通过依赖注入和面向切面编程,用简单的Java 对象( Plain Old Java Object POJO )实现了 EJB 的功能
缺点:
虽然 Spring 的组件代码是轻量级的,但它的配置却是重量级的 。一开始, Spring XML 配置,而且是很多XML 配 置。 Spring 2.5 引入了基于注解的组件扫描,这消除了大量针对应用程序自身组件的显式 XML配置。Spring 3.0 引入 了基于 Java 的配置,这是一种类型安全的可重构配置方式,可以代替 XML
所有这些配置都代表了开发时的损耗。因为在思考 Spring 特性配置和解决业务问题之间需要进行思维切换,所以编写配置挤占了编写应用程序逻辑的时间。和所有框架一样,Spring 实用,但与此同时它要求的回报也不少。
除此之外, 项目的依赖管理也是一件耗时耗力的事情 。在环境搭建时,需要分析要导入哪些库的坐标,而且还需要分析导入与之有依赖关系的其他库的坐标,一旦选错了依赖的版本,随之而来的不兼容问题就会严重阻碍项目的开发进度
SSM 整合: Spring Spring MVC Mybatis Spring-Mybatis 整合包、数据库驱动,引入依赖的数量繁多、容易存在版本冲突。
1.2.2 Spring Boot 解决上述 spring 问题
SpringBoot 对上述 Spring 的缺点进行的改善和优化,基于约定优于配置的思想,可以让开发人员不必在配置与逻辑 业务之间进行思维的切换,全身心的投入到逻辑业务的代码编写中,从而大大提高了开发的效率,一定程度上缩短 了项目周期。
起步依赖
起步依赖本质上是一个 Maven 项目对象模型 (Project Object Model POM) ,定义了对其他库的传递依赖,这些东西加在一起即支持某项功能。
简单的说,起步依赖就是将具备某种功能的依赖坐标打包到一起,并提供一些默认的功能。
自动配置
springboot 的自动配置,指的是 springboot ,会自动将一些配置类的 bean 注册进 ioc 容器,我们可以需要的地方使用@autowired 或者 @resource 等注解来使用它。
自动 的表现形式就是我们只需要引我们想用功能的包,相关的配置我们完全不用管, springboot 会自动注入这些配置bean ,我们直接使用这些 bean 即可springboot: 简单、快速、方便地搭建项目;对主流开发框架的无配置集成;极大提高了开发、部署效率
1.3 Spring Boot 入门案例
案例需求:请求 Controller 中的方法,并将返回值响应到页面
1 )依赖管理
<!--
所用的springBoot项目都会直接或者间接的继承spring-boot-starter-parent
1.指定项目的编码格式为UTF-8
2.指定JDK版本为1.8
3.对项目依赖的版本进行管理,当前项目再引入其他常用的依赖时就需要再指定版本号,避免版本
冲突的问题
4.默认的资源过滤和插件管理
-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
</parent>
<dependencies>
<!--引入Spring Web及Spring MVC相关的依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<!--可以将project打包为一个可以执行的jar-->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
(2) 启动类
/**
* SpringBoot的启动类通常放在二级包中,比如:com.lagou.SpringBootDemo1Application
* 因为SpringBoot项目在做包扫描,会扫描启动类所在的包及其子包下的所有内容。
*/
//标识当前类为SpringBoot项目的启动类
@SpringBootApplication
public class SpringBootDemo1Application {
public static void main(String[] args) {
//样板代码
SpringApplication.run(SpringBootDemo1Application.class,args);
}
}
(3)Controller
package com.lagou.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/hello")
public class HelloController {
@RequestMapping("/boot")
public String helloBoot(){
return "Hello Spring Boot";
}
}
1.4 SpringBoot 快速构建
案例需求:请求 Controller 中的方法,并将返回值响应到页面
1 )使用 Spring Initializr 方式构建 Spring Boot 项目
本质上说, Spring Initializr 是一个 Web 应用,它提供了一个基本的项目结构,能够帮助我们快速构
建一个基础的 Spring Boot 项目

 

Project SDK” 用于设置创建项目使用的 JDK 版本,这里,使用之前初始化设置好的 JDK 版本即可;在 “Choose Initializr Service URL(选择初始化服务地址) 下使用默认的初始化服务地址 https://start.spring.io 进行 Spring Boot 项目创建(注意使用快速方式创建 Spring Boot 项目时,所在主机须在联网状态下)

 

 Spring Boot项目就创建好了。创建好的Spring Boot项目结构如图:

 使用Spring Initializr方式构建的Spring Boot项目会默认生成项目启动类、存放前端静态资源和页

面的文件夹、编写项目配置的配置文件以及进行项目单元测试的测试类
2 ) 创建一个用于 Web 访问的 Controller
com.lagou 包下创建名称为 controller 的包,在该包下创建一个请求处理控制类 HelloController
并编写一个请求处理方法 ( 注意:将项目启动类 SpringBootDemoApplication 移动到 com.lagou 包下 )
@RestController // 该注解为组合注解,等同于Spring中@Controller+@ResponseBody注解
public class DemoController {
@RequestMapping("/demo")
public String demo(){
return "hello spring Boot";
}
}
3 ) 运行项目
运行主程序启动类 SpringbootDemoApplication ,项目启动成功后,在控制台上会发现 Spring
Boot 项目默认启动的端口号为 8080 ,此时,可以在浏览器上访问 http://localhost:8080/hello

 页面输出的内容是“hello Spring Boot”,至此,构建Spring Boot项目就完成了

1.5 单元测试与热部署
1.5.1 单元测试
开发中,每当完成一个功能接口或业务方法的编写后,通常都会借助单元测试验证该功能是否正
确。 Spring Boot 对项目的单元测试提供了很好的支持,在使用时,需要提前在项目的 pom.xml 文件中添加spring-boot-starter-test 测试依赖启动器,可以通过相关注解实现单元测试
演示:
1 .添加 spring-boot-starter-test 测试依赖启动器
在项目的 pom.xml 文件中添加 spring-boot-starter-test 测试依赖启动器,示例代码如下 :
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
注意:使用 Spring Initializr 方式搭建的 Spring Boot 项目,会自动加入 spring-boot-starter-test 测试依赖启动器,无需再手动添加
2 .编写单元测试类和测试方法
使用 Spring Initializr 方式搭建的 Spring Boot 项目,会在 src.test.java 测试目录下自动创建与项目主程序启动类对应的单元测试类
package com.lagou;
import com.lagou.controller.HelloController;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.junit4.SpringRunner;
/**
* SpringJUnit4ClassRunner.class:Spring运行环境
* JUnit4.class:JUnit运行环境
* SpringRunner.class:Spring Boot运行环境
*/
@RunWith(SpringRunner.class) //@RunWith:运行器
@SpringBootTest //标记为当前类为SpringBoot测试类,加载项目的ApplicationContext上下文环境
class Springbootdemo2ApplicationTests {
/**
* 需求:调用HelloController的hello方法
*/
@Autowired
private HelloController helloController;
@Test
void contextLoads() {
String result = helloController.hello();
System.out.println(result);
}
}
上述代码中,先使用 @Autowired 注解注入了 DemoController 实例对象,然后在 contextLoads()
法中调用了 DemoController 类中对应的请求控制方法 contextLoads() ,并输出打印结果

1.5.2 热部署
在开发过程中,通常会对一段业务代码不断地修改测试,在修改之后往往需要重启服务,有些服务
需要加载很久才能启动成功,这种不必要的重复操作极大的降低了程序开发效率。为此, Spring Boot 框架专门提供了进行热部署的依赖启动器,用于进行项目热部署,而无需手动重启项目 。
热部署:在修改完代码之后,不需要重新启动容器,就可以实现更新。
使用步骤:
1 )添加 SpringBoot 的热部署依赖启动器
2 )开启 Idea 的自动编译
3 )开启 Idea 的在项目运行中自动编译的功能
演示:
1 .添加 spring-boot-devtools 热部署依赖启动器
Spring Boot 项目进行热部署测试之前,需要先在项目的 pom.xml 文件中添加 spring-boot-devtools 热部署依赖启动器:
<!-- 引入热部署依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
由于使用的是 IDEA 开发工具,添加热部署依赖后可能没有任何效果,接下来还需要针对 IDEA 开发
工具进行热部署相关的功能设置
2. IDEA 工具热部署设置
选择 IDEA 工具界面的【 File -> Settings 】选项,打开 Compiler 面板设置页面

选择 Build 下的 Compiler 选项,在右侧勾选 “Build project automatically” 选项将项目设置为自动编
译,单击【 Apply OK 】按钮保存设置
在项目任意页面中使用组合快捷键 “Ctrl+Shift+Alt+/” 打开 Maintenance 选项框,选中并打开
Registry 页面,具体如图 1-17 所示

列表中找到 “compiler.automake.allow.when.app.running” ,将该选项后的 Value 值勾选,用于指
IDEA 工具在程序运行过程中自动编译,最后单击【 Close 】按钮完成设置
3 .热部署效果测试
启动 chapter01 http://localhost:8080/hello

页面原始输出的内容是 “hello Spring Boot”
为了测试配置的热部署是否有效,接下来,在不关闭当前项目的情况下,将 DemoController 类中的请求处理方法hello() 的返回值修改为 你好, Spring Boot” 并保存,查看控制台信息会发现项目能够自动构建和编译,说明项目热部署生效

 可以看出,浏览器输出了你好,Spring Boot”,说明项目热部署配置成功

1.6 全局配置文件
全局配置文件能够对一些默认配置值进行修改。 Spring Boot 使用一个 application.properties 或者
application.yaml 的文件作为全局配置文件,该文件存放在 src/main/resource 目录或者类路径
/config ,一般会选择 resource 目录。接下来,将针对这两种全局配置文件进行讲解 :
Spring Boot 配置文件的命名及其格式:
application.properties
application.yaml
application.yml
1.6.1 application.properties 配置文件
使用 Spring Initializr 方式构建 Spring Boot 项目时,会在 resource 目录下自动生成一个空的
application.properties 文件, Spring Boot 项目启动时会自动加载 application.properties 文件。
我们可以在 application.properties 文件中定义 Spring Boot 项目的相关属性,当然,这些相关属性可以是系统属性、环境变量、命令参数等信息,也可以是自定义配置文件名称和位置
#修改tomcat的版本号
server.port=8888
#定义数据库的连接信息 JdbcTemplate
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/lagou
spring.datasource.username=root
spring.datasource.password=wu7787879
接下来,通过一个案例对 Spring Boot 项目中 application.properties 配置文件的具体使用进行讲解
演示:
预先准备了两个实体类文件,后续会演示将 application.properties 配置文件中的自定义配置属性注入到Person实体类的对应属性中
(1)先在项目的 com.lagou 包下创建一个 pojo 包,并在该包下创建两个实体类 Pet Person
public class Pet {
private String type;
private String name;
}
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
private int id; //id
private String name; //名称
private List hobby; //爱好
private String[] family; //家庭成员
private Map map;
private Pet pet; //宠物
}
@ConfigurationProperties(prefix = "person") 注解的作用是将配置文件中以 person 开头的属性值通过setXX()方法注入到实体类对应属性中
@Component 注解的作用是将当前注入属性值的 Person 类对象作为 Bean 组件放到 Spring 容器中,只有这样才能被@ConfigurationProperties 注解进行赋值
(2)打开项目的 resources 目录下的 application.properties 配置文件,在该配置文件中编写需要对
Person 类设置的配置属性
#自定义配置信息
person.id=1
person.name=王二麻子
person.hobby=read,write
person.family=father,mather
person.map.key1=value1
person.map.key2=value2
person.pet.type=dog
person.pet.name=哈士奇
(3)查看 application.properties 配置文件是否正确,同时查看属性配置效果,打开通过 IDEA 工具创建的项目测试类,在该测试类中引入Person 实体类 Bean ,并进行输出测试
@RunWith(SpringRunner.class) // 测试启动器,并加载Spring Boot测试注解
@SpringBootTest // 标记为Spring Boot单元测试类,并加载项目的ApplicationContext上下文环
境
class SpringbootDemoApplicationTests {
// 配置测试
@Autowired
private Person person;
@Test
void configurationTest() {
System.out.println(person);
}
}
打印结果:

可以看出,测试方法 configurationTest() 运行成功,同时正确打印出了 Person 实体类对象。至此,说明application.properties配置文件属性配置正确,并通过相关注解自动完成了属性注入
(4)中文乱码问题解决
调整文件编码格式:

 设置TomcatHttp编码

#解决中文乱码
server.tomcat.uri-encoding=UTF-8
spring.http.encoding.force=true
spring.http.encoding.charset=UTF-8
spring.http.encoding.enabled=true
1.6.2 application.yaml 配置文件
YAML 文件格式是 Spring Boot 支持的一种 JSON 文件格式,相较于传统的 Properties 配置文件, YAML 文件以数据为核心,是一种更为直观且容易被电脑识别的数据序列化格式。application.yaml 配置文件的工作原理和application.properties 是一样的,只不过 yaml 格式配置文件看起来更简洁一些。
YAML 文件的扩展名可以使用 .yml 或者 .yaml
application.yml 文件使用 “key: (空格) value” 格式配置属性,使用缩进控制 层级关系
SpringBoot 的三种配置文件是可以共存的:

这里,针对不同数据类型的属性值,介绍一下 YAML
(1) value 值为普通数据类型(例如数字、字符串、布尔等)
YAML 配置文件中配置的属性值为普通数据类型时,可以直接配置对应的属性值,同时对于字符
串类型的属性值,不需要额外添加引号,示例代码如下
server:
    port: 8080
    servlet:
        context-path: /hello
(2) value 值为数组和单列集合
YAML 配置文件中配置的属性值为数组或单列集合类型时,主要有两种书写方式:缩进式写法和行内 式写法。
其中,缩进式写法还有两种表示形式,示例代码如下
person:
    hobby:
        - play
        - read
        - sleep
或者使用如下示例形式
person:
    hobby:
        play,
        read,
        sleep
上述代码中,在 YAML 配置文件中通过两种缩进式写法对 person 对象的单列集合(或数组)类型的爱好hobby赋值为 play read sleep 。其中一种形式为 “- (空格)属性值 ,另一种形式为多个属性值之前加英文逗号分隔(注意,最后一个属性值后不要加逗号)。
person:
    hobby: [play,read,sleep]
通过上述示例对比发现, YAML 配置文件的行内式写法更加简明、方便。另外,包含属性值的中括
“[]” 还可以进一步省略,在进行属性赋值时,程序会自动匹配和校对
(3) value 值为 Map 集合和对象
YAML 配置文件中配置的属性值为 Map 集合或对象类型时, YAML 配置文件格式同样可以分为两种书写方式:缩进式写法和行内式写法。
其中,缩进式写法的示例代码如下
person:
    map:
        k1: v1
        k2: v2
对应的行内式写法示例代码如下
person:
map: {k1: v1,k2: v2}
YAML 配置文件中,配置的属性值为 Map 集合或对象类型时,缩进式写法的形式按照 YAML 文件格式编写即可,而行内式写法的属性值要用大括号“{}” 包含。
接下来,在 Properties 配置文件演示案例基础上,通过配置 application.yaml 配置文件对 Person 对象进行赋值,具体使用如下
(1)在项目的 resources 目录下,新建一个 application.yaml 配置文件,在该配置文件中编写为 Person类设置的配置属性
#对实体类对象Person进行属性配置
person:
    id: 1
    name: 王二麻子
    family:
        - 妻
        - 妾
    hobby:
        - play
        - read
        - sleep
    map:
        k1: value1
        k2: value2
    pet:
        type: 狗
        name: 哈士奇
2 )再次执行测试
Person{id=1, name=' 王二麻子 ', hobby=[play, read, sleep], family=[ , ], map={k1=value1,
k2=value2}, pet=Pet{type=' ', name=' 哈士奇 '}}
可以看出,测试方法 configurationTest() 同样运行成功,并正确打印出了 Person 实体类对象。
需要 说明 的是,本次使用 application.yaml 配置文件进行测试时需要提前将 application.properties 配置文件中编写的配置注释,这是因为application.properties 配置文件会覆盖 application.yaml 配置文件
1.7 配置文件属性值的注入
配置文件的优先级如下: 从低到高
<includes>
<include>**/application*.yml</include>
<include>**/application*.yaml</include>
<include>**/application*.properties</include>
</includes>
使用 Spring Boot 全局配置文件设置属性时:
如果配置属性是 Spring Boot 已有属性,例如服务端口 server.port ,那么 Spring Boot 内部会自动扫描并读取这些配置文件中的属性值并覆盖默认属性。
如果配置的属性是用户自定义属性,例如刚刚自定义的 Person 实体类属性,还必须在程序中注入这些配置属性方可生效。
Spring Boot 支持多种注入配置文件属性的方式,下面来介绍如何使用注解 @ConfigurationProperties
@Value 注入属性
1.7.1 使用 @ConfigurationProperties 注入属性
Spring Boot 提供的 @ConfigurationProperties 注解用来快速、方便地将配置文件中的自定义属性值批量注入到某个Bean 对象的多个对应属性中。假设现在有一个配置文件,如果使用
@ConfigurationProperties 注入配置文件的属性,示例代码如下:
@Component
//将配置文件中所有以person开头的配置信息注入当前类中
//前提1:必须保证配置文件中person.xx与当前Person类的属性名一致
//前提2:必须保证当前Person中的属性都具有set方法
@ConfigurationProperties(prefix = "person")
public class Person {
private int id; //id
private String name; //名称
private List hobby; //爱好
private String[] family; //家庭成员
private Map map;
private Pet pet; //宠物
}
上述代码使用 @Component @ConfigurationProperties(prefix = “person”) 将配置文件中的每个属性映射到person 类组件中。
1.7.2 使用 @Value 注入属性
@Value 注解是 Spring 框架提供的,用来读取配置文件中的属性值并逐个注入到 Bean 对象的对应属性中,Spring Boot 框架从 Spring 框架中对 @Value 注解进行了默认继承,所以在 Spring Boot 框架中还可以使用该注解读取和注入配置文件属性值。使用@Value 注入属性的示例代码如下
@Component
public class Person {
@Value("${person.id}")
private int id;
}
上述代码中,使用 @Component @Value 注入 Person 实体类的 id 属性。其中, @Value 不仅可以
将配置文件的属性注入 Person id 属性,还可以直接给 id 属性赋值,这点是 @ConfigurationProperties
不支持的
演示@Value 注解读取并注入配置文件属性的使用 :
(1)在 com.lagou.pojo 包下新创建一个实体类 Student ,并使用 @Value 注解注入属性
@Component
public class Student {
@Value("${person.id}")
private int id;
@Value("${person.name}")
private String name; //名称
//省略toString
}
Student 类使用 @Value 注解将配置文件的属性值读取和注入。
从上述示例代码可以看出,使用 @Value 注解方式需要对每一个属性注入设置,同时又免去了属性的 setXX()方法
(2)再次打开测试类进行测试
@Autowired
private Student student;
@Test
public void studentTest() {
System.out.println(student);
}
打印结果:

可以看出,测试方法 studentTest() 运行成功,同时正确打印出了 Student 实体类对象。需要说明的
是,本示例中只是使用 @Value 注解对实例中 Student 对象的普通类型属性进行了赋值演示,而 @Value 注解对于包含Map 集合、对象以及 YAML 文件格式的行内式写法的配置文件的属性注入都不支持,如果赋值会出现错误
1.8 自定义配置
spring Boot 免除了项目中大部分的手动配置,对于一些特定情况,我们可以通过修改全局配置文
件以适应具体生产环境,可以说,几乎所有的配置都可以写在 application.yml 文件中, Spring Boot 会自动加载全局配置文件从而免除我们手动加载的烦恼。但是,如果我们自定义配置文件,Spring Boot 是无法识别这些配置文件的,此时就需要我们手动加载。接下来,将针对Spring Boot 的自定义配置文件及其加载方式进行讲解
1.8.1 使用 @PropertySource 加载配置文件
对于这种加载自定义配置文件的需求,可以使用 @PropertySource 注解来实现。
@PropertySource 注解用于指定自定义配置文件的具体位置和名称
当然,如果需要将自定义配置文件中的属性值注入到对应类的属性中,可以使用
@ConfigurationProperties 或者 @Value 注解进行属性值注入
演示:
(1)打开 Spring Boot 项目的 resources 目录,在项目的类路径下新建一个 test.properties 自定义配
置文件,在该配置文件中编写需要设置的配置属性
#对实体类对象MyProperties进行属性配置
test.id=110
test.name=test
(2)在 com.lagou.pojo 包下新创建一个配置类 MyProperties ,提供 test.properties 自定义配置文件
中对应的属性,并根据 @PropertySource 注解的使用进行相关配置
@Component // 自定义配置类
@PropertySource("classpath:test.properties") // 指定自定义配置文件位置和名称
@ConfigurationProperties(prefix = "test") // 指定配置文件注入属性前缀
public class MyProperties {
private int id;
private String name;
// 省略属性getXX()和setXX()方法
// 省略toString()方法
}
主要是一个自定义配置类,通过相关注解引入了自定义的配置文件,并完成了自定义属性值的注
入。针对示例中的几个注解,具体说明如下
@PropertySource("classpath:test.properties") 注解指定了自定义配置文件的位置和名称,此示例
表示自定义配置文件为 classpath 类路径下的 test.properties 文件;
@ConfigurationProperties(prefix = "test") 注解将上述自定义配置文件 test.properties 中以 test
头的属性值注入到该配置类属性中。
(3)进行测试
@Autowired
private MyProperties myProperties;
@Test
public void myPropertiesTest() {
System.out.println(myProperties);
}
打印结果:

1.8.2 使用 @Configuration 编写自定义配置类
Spring Boot 框架中,推荐使用配置类的方式向容器中添加和配置组件
Spring Boot 框架中,通常使用 @Configuration 注解定义一个配置类, Spring Boot 会自动扫描和识别配置类,从而替换传统Spring 框架中的 XML 配置文件。
当定义一个配置类后,还需要在类中的方法上使用 @Bean 注解进行组件配置,将方法的返回对象注入到Spring容器中,并且组件名称默认使用的是方法名,当然也可以使用 @Bean 注解的 name value 属性自定义组件的名称
演示:
(1)在项目下新建一个 com.lagou.config 包,并在该包下新创建一个类 MyService ,该类中不需要编写任何代码
public class MyService {
}
创建了一个空的 MyService 类,而该类目前没有添加任何配置和注解,因此还无法正常被 Spring Boot 扫描和识别
(2) 在项目的 com.lagou.config 包下,新建一个类 MyConfig ,并使用 @Configuration 注解将该类声明一个配置类,内容如下:
@Configuration // 定义该类是一个配置类````
public class MyConfig {
@Bean // 将返回值对象作为组件添加到Spring容器中,该组件id默认为方法名
public MyService myService(){
return new MyService();
}
}
MyConfig @Configuration 注解声明的配置类(类似于声明了一个 XML 配置文件),该配置类会
Spring Boot 自动扫描识别;使用 @Bean 注解的 myService() 方法,其返回值对象会作为组件添加到了Spring容器中(类似于 XML 配置文件中的标签配置),并且该组件的 id 默认是方法名 myService
(3)测试类
@Autowired
private ApplicationContext applicationContext;
@Test
public void iocTest() {
System.out.println(applicationContext.containsBean("myService"));
}
上述代码中,先通过 @Autowired 注解引入了 Spring 容器实例 ApplicationContext ,然后在测试方法
iocTest() 中测试查看该容器中是否包括 id myService 的组件。
执行测试方法 iocTest() ,查看控制台输出效果,结果如下:

从测试结果可以看出,测试方法 iocTest() 运行成功,显示运行结果为 true ,表示 Spirng IOC 容器中也已经包含了id myService 的实例对象组件,说明使用自定义配置类的形式完成了向 Spring 容器进行组件的添加和配置
2. SpringBoot 原理深入及源码剖析
传统的 Spring 框架实现一个 Web 服务,需要导入各种依赖 JAR 包,然后编写对应的 XML 配置文件
等,相较而言, Spring Boot 显得更加方便、快捷和高效。那么, Spring Boot 究竟如何做到这些的呢?
接下来分别针对 Spring Boot 框架的依赖管理、自动配置通过源码进行深入分析
2.1 依赖管理
问题:(1)为什么导入 dependency 时不需要指定版本?
Spring Boot 入门程序中,项目 pom.xml 文件有两个核心依赖,分别是 spring-boot-starter
parent spring-boot-starter-web ,关于这两个依赖的相关介绍具体如下:
1 spring-boot-starter-parent 依赖
chapter01 项目中的 pom.xml 文件中找到 spring-boot-starter-parent 依赖,示例代码如下 :
<!-- Spring Boot父项目依赖管理 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent<11./artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

上述代码中,将 spring-boot-starter-parent 依赖作为 Spring Boot 项目的统一父项目依赖管理,并将项目版本号统一为2.2.2.RELEASE ,该版本号根据实际开发需求是可以修改的
使用 “Ctrl+ 鼠标左键 进入并查看 spring-boot-starter-parent 底层源文件,发现 spring-boot
starter-parent 的底层有一个父依赖 spring-boot-dependencies ,核心代码具体如下
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath>../../spring-boot-dependencies</relativePath>
</parent>
继续查看 spring-boot-dependencies 底层源文件,核心代码具体如下:
<properties>
<activemq.version>5.15.11</activemq.version>
...
<solr.version>8.2.0</solr.version>
<mysql.version>8.0.18</mysql.version>
<kafka.version>2.3.1</kafka.version>
<properties>
<activemq.version>5.15.11</activemq.version>
...
<solr.version>8.2.0</solr.version>
<mysql.version>8.0.18</mysql.version>
<kafka.version>2.3.1</kafka.version>

spring-boot-dependencies 底层源文件可以看出,该文件通过标签对一些常用技术框架的依赖文件进行了统一版本号管理,例如activemq spring tomcat 等,都有与 Spring Boot 2.2.2 版本相匹配的版本,这也是pom.xml 引入依赖文件不需要标注依赖文件版本号的原因。
需要说明的是,如果 pom.xml 引入的依赖文件不是 spring-boot-starter-parent 管理的,那么在
pom.xml 引入依赖文件时,需要使用标签指定依赖文件的版本号。
(2)问题 2 spring-boot-starter-parent 父依赖启动器的主要作用是进行版本统一管理,那么项目运行依赖的JAR 包是从何而来的?
2. spring-boot-starter-web 依赖
查看 spring-boot-starter-web 依赖文件源码,核心代码具体如下
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.2.2.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
<version>2.2.2.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>2.2.2.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<version>2.2.2.RELEASE</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<artifactId>tomcat-embed-el</artifactId>
<groupId>org.apache.tomcat.embed</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.2.2.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.2.RELEASE</version>
<scope>compile</scope>
</dependency>
</dependencies>
从上述代码可以发现, spring-boot-starter-web 依赖启动器的主要作用是提供 Web 开发场景所需的底层所有依赖
正是如此,在 pom.xml 中引入 spring-boot-starter-web 依赖启动器时,就可以实现 Web 场景开发,而不需要额外导入Tomcat 服务器以及其他 Web 依赖文件等。当然,这些引入的依赖文件的版本号还是由 spring-boot-starter-parent父依赖进行的统一管理。
有哪些 starter
https://github.com/spring-projects/spring-boot/tree/v2.1.0.RELEASE/spring-boot-project/spring-bo
ot-starters
https://mvnrepository.com/search?q=starter
Spring Boot 除了提供有上述介绍的 Web 依赖启动器外,还提供了其他许多开发场景的相关依赖,
我们可以打开 Spring Boot 官方文档,搜索 “Starters” 关键字查询场景依赖启动器

列出了 Spring Boot 官方提供的部分场景依赖启动器,这些依赖启动器适用于不同的场景开发,使用时只需要在pox.xml 文件中导入对应的依赖启动器即可。
需要说明的是, Spring Boot 官方并不是针对所有场景开发的技术框架都提供了场景启动器,例如数据库操作框架MyBatis 、阿里巴巴的 Druid 数据源等, Spring Boot 官方就没有提供对应的依赖启动器。为了充分利用Spring Boot 框架的优势,在 Spring Boot 官方没有整合这些技术框架的情况下, MyBatis 、Druid等技术框架所在的开发团队主动与 Spring Boot 框架进行了整合,实现了各自的依赖启动器,例如mybatis-spring-boot-starter、 druid-spring-boot-starter 等。我们在 pom.xml 文件中引入这些第三方的依赖启动器时,切记要配置对应的版本号
2.2 自动配置
概念:能够在我们添加 jar 包依赖的时候,自动为我们配置一些组件的相关配置,我们无需配置或者只需要少量配置就能运行编写的项目
问题: Spring Boot 到底是如何进行自动配置的,都把哪些组件进行了自动配置?
Spring Boot 应用的启动入口是 @SpringBootApplication 注解标注类中的 main() 方法,
@SpringBootApplication SpringBoot 应用标注在某个类上说明这个类是 SpringBoot 的主配置
类, SpringBoot 就应该运行这个类的 main() 方法启动 SpringBoot 应用。
下面,查看 @SpringBootApplication 内部源码进行分析 ,核心代码具体如下
@SpringBootApplication
public class SpringbootDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootDemoApplication.class, args);
}
}
进入到 @SpringBootApplication 内,观察其做了哪些工作:
@Target({ElementType.TYPE}) //注解的适用范围,Type表示注解可以描述在类、接口、注解或枚举中
@Retention(RetentionPolicy.RUNTIME) //表示注解的生命周期,Runtime运行时
@Documented //表示注解可以记录在javadoc中
@Inherited //表示可以被子类继承该注解
@SpringBootConfiguration // 标明该类为配置类
@EnableAutoConfiguration // 启动自动配置功能
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes =
TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes =
AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
// 根据class来排除特定的类,使其不能加入spring容器,传入参数value类型是class类型。
@AliasFor(annotation = EnableAutoConfiguration.class)
Class<?>[] exclude() default {};
// 根据classname 来排除特定的类,使其不能加入spring容器,传入参数value类型是class的全
类名字符串数组。
@AliasFor(annotation = EnableAutoConfiguration.class)
String[] excludeName() default {};
// 指定扫描包,参数是包名的字符串数组。
@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
String[] scanBasePackages() default {};
// 扫描特定的包,参数类似是Class类型数组。
@AliasFor(annotation = ComponentScan.class, attribute =
"basePackageClasses")
Class<?>[] scanBasePackageClasses() default {};
}
从上述源码可以看出, @SpringBootApplication 注解是一个组合注解,前面 4 个是注解的元数据
信息, 我们主要看后面 3 个注解: @SpringBootConfiguration @EnableAutoConfiguration
@ComponentScan 三个核心注解,关于这三个核心注解的相关说明具体如下:
1 @SpringBootConfiguration 注解
@SpringBootConfiguration SpringBoot 的配置类,标注在某个类上,表示这是一个 SpringBoot
的配置类。
查看 @SpringBootConfiguration 注解源码,核心代码具体如下。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration // 配置类的作用等同于配置文件,配置类也是容器中的一个对象
public @interface SpringBootConfiguration {
}
从上述源码可以看出, @SpringBootConfiguration 注解内部有一个核心注解 @Configuration ,该
注解是 Spring 框架提供的,表示当前类为一个配置类( XML 配置文件的注解表现形式),并可以被组件扫描器扫描。由此可见,@SpringBootConfiguration 注解的作用与 @Configuration 注解相同,都是 标识一个可以被组件扫描器扫描的配置类,只不过 @SpringBootConfiguration 是被 Spring Boot 进行 了重新封装命名而已
2 @EnableAutoConfiguration 注解
@EnableAutoConfiguration :开启自动配置功能,以前由我们需要配置的东西,现在由 SpringBoot 帮我们自动配置,这个注解就是 Springboot 能实现自动配置的关键。
同样,查看该注解内部查看源码信息,核心代码具体如下
// 自动配置包
@AutoConfigurationPackage
// Spring的底层注解@Import,给容器中导入一个组件;
// 导入的组件是AutoConfigurationPackages.Registrar.class
@Import(AutoConfigurationImportSelector.class)
// 告诉SpringBoot开启自动配置功能,这样自动配置才能生效。
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
// 返回不会被导入到 Spring 容器中的类
Class<?>[] exclude() default {};
// 返回不会被导入到 Spring 容器中的类名
String[] excludeName() default {};
}
可以发现它是一个组合注解, Spring 中有很多以 Enable 开头的注解,其作用就是借助 @Import
来收集并注册特定场景相关的 Bean ,并加载到 IOC 容器。 @EnableAutoConfiguration 就是借助
@Import 来收集所有符合自动配置条件的 bean 定义,并加载到 IoC 容器。
下面,对这两个核心注解分别讲解 :
1 @AutoConfigurationPackage 注解
查看 @AutoConfigurationPackage 注解内部源码信息,核心代码具体如下:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({Registrar.class}) // 导入Registrar中注册的组件
public @interface AutoConfigurationPackage {
}
从上述源码可以看出, @AutoConfigurationPackage 注解的功能是由 @Import 注解实现的,它是
spring 框架的底层注解,它的作用就是给容器中导入某个组件类,例如
@Import(AutoConfigurationPackages.Registrar.class) ,它就是将 Registrar 这个组件类导入到容器
中,可查看 Registrar 类中 registerBeanDefinitions 方法,这个方法就是导入组件类的具体实现 :

从上述源码可以看出,在 Registrar 类中有一个 registerBeanDefinitions() 方法,使用 Debug 模式启
动项目,可以看到选中的部分就是 com.lagou 。也就是说, @AutoConfigurationPackage 注解的主要作用就是将主程序类所在包及所有子包下的组件到扫描到spring 容器中。
因此 在定义项目包结构时,要求定义的包结构非常规范,项目主程序启动类要定义在最外层的根目录位置,然后在根目录位置内部建立子包和类进行业务开发,这样才能够保证定义的类能够被组件扫描器扫描
(2) @Import({AutoConfigurationImportSelector.class}) 注解
AutoConfigurationImportSelector 这个类导入到 Spring 容器中,
AutoConfigurationImportSelector 可以帮助 Springboot 应用将所有符合条件的 @Configuration
配置都加载到当前 SpringBoot 创建并使用的 IOC 容器 ( ApplicationContext ) 中。
继续研究 AutoConfigurationImportSelector 这个类,通过源码分析这个类中是通过 selectImports 这个方法告诉springboot 都需要导入那些组件:

 深入研究loadMetadata方法

 AutoConfigurationImportSelector getAutoConfigurationEntry方法

protected AutoConfigurationEntry
getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
AnnotationMetadata annotationMetadata) {
//判断EnabledAutoConfiguration注解有没有开启,默认开启
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
//获得注解的属性信息
AnnotationAttributes attributes = getAttributes(annotationMetadata);
//获取默认支持的自动配置类列表
List<String> configurations =
getCandidateConfigurations(annotationMetadata, attributes);
//去重
configurations = removeDuplicates(configurations);
//去除一些多余的配置类,根据EnabledAutoConfiguratio的exclusions属性进行排除
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
//根据pom文件中加入的依赖文件筛选中最终符合当前项目运行环境对应的自动配置类
configurations = filter(configurations, autoConfigurationMetadata);
//触发自动配置导入监听事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
深入 getCandidateConfigurations 方法
这个方法中有一个重要方法 loadFactoryNames ,这个方法是让 SpringFactoryLoader 去加载一些组件的名字。

 继续点开loadFactory方法

public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable
ClassLoader classLoader) {
//获取出入的键
String factoryClassName = factoryClass.getName();
return
(List)loadSpringFactories(classLoader).getOrDefault(factoryClassName,
Collections.emptyList());
}
private static Map<String, List<String>> loadSpringFactories(@Nullable
ClassLoader classLoader) {
MultiValueMap<String, String> result =
(MultiValueMap)cache.get(classLoader);
if (result != null) {
return result;
} else {
try {
//如果类加载器不为null,则加载类路径下spring.factories文件,将其中设置的
配置类的全路径信息封装 为Enumeration类对象
Enumeration<URL> urls = classLoader != null ?
classLoader.getResources("META-INF/spring.factories") :
ClassLoader.getSystemResources("META-INF/spring.factories");
LinkedMultiValueMap result = new LinkedMultiValueMap();
//循环Enumeration类对象,根据相应的节点信息生成Properties对象,通过传入的
键获取值,在将值切割为一个个小的字符串转化为Array,方法result集合中
while(urls.hasMoreElements()) {
URL url = (URL)urls.nextElement();
UrlResource resource = new UrlResource(url);
Properties properties =
PropertiesLoaderUtils.loadProperties(resource);
Iterator var6 = properties.entrySet().iterator();
while(var6.hasNext()) {
Entry<?, ?> entry = (Entry)var6.next();
String factoryClassName =
((String)entry.getKey()).trim();
String[] var9 =
StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
int var10 = var9.length;
for(int var11 = 0; var11 < var10; ++var11) {
String factoryName = var9[var11];
result.add(factoryClassName, factoryName.trim());
}
}
}
cache.put(classLoader, result);
return result;
会去读取一个 spring.factories 的文件,读取不到会表这个错误,我们继续根据会看到,最终路径的长这样,而这个是spring 提供的一个工具类
public final class SpringFactoriesLoader {
public static final String FACTORIES_RESOURCE_LOCATION = "METAINF/spring.factories";
}
它其实是去加载一个外部的文件,而这文件是在

 

@EnableAutoConfiguration 就是从 classpath 中搜寻 META-INF/spring.factories 配置文件,并将其中
org.springframework.boot.autoconfigure.EnableutoConfiguration 对应的配置项通过反射( Java
Refletion )实例化为对应的标注了 @Configuration JavaConfig 形式的配置类,并加载到 IOC 容器中 以刚刚的项目为例,在项目中加入了 Web 环境依赖启动器,对应的 WebMvcAutoConfiguration 自动配置类就会生效,打开该自动配置类会发现,在该配置类中通过全注解配置类的方式对Spring MVC 运行所需环境进行了默认配置,包括默认前缀、默认后缀、视图解析器、MVC 校验器等。而这些自动配置类的本质是传统Spring MVC 框架中对应的 XML 配置文件,只不过在 Spring Boot 中以自动配置类的形式进行了预先配置。因此,在Spring Boot 项目中加入相关依赖启动器后,基本上不需要任何配置就可以运行程序,当然,我们也可以对这些自动配置类中默认的配置进行更改
总结
因此 springboot 底层实现自动配置的步骤是:
1. springboot 应用启动;
2. @SpringBootApplication 起作用;
3. @EnableAutoConfiguration
4. @AutoConfigurationPackage :这个组合注解主要是
@Import(AutoConfigurationPackages.Registrar.class) ,它通过将 Registrar 类导入到容器中,而
Registrar 类作用是扫描主配置类同级目录以及子包,并将相应的组件导入到 springboot 创建管理的
容器中;
5. @Import(AutoConfigurationImportSelector.class) :它通过将 AutoConfigurationImportSelector
类导入到容器中, AutoConfigurationImportSelector 类作用是通过 selectImports 方法执行的过程
中,会使用内部工具类 SpringFactoriesLoader ,查找 classpath 上所有 jar 包中的 META
INF/spring.factories 进行加载,实现将配置类信息交给 SpringFactory 加载器进行一系列的容器创
建过程
3. @ComponentScan 注解
@ComponentScan 注解具体扫描的包的根路径由 Spring Boot 项目主程序启动类所在包位置决定,
在扫描过程中由前面介绍的 @AutoConfigurationPackage 注解进行解析,从而得到 Spring Boot 项目主程序启动类所在包的具体位置
总结:
@SpringBootApplication 的注解的功能就分析差不多了, 简单来说就是 3 个注解的组合注解:
|- @SpringBootConfiguration
|- @Configuration //通过javaConfig的方式来添加组件到IOC容器中
|- @EnableAutoConfiguration
|- @AutoConfigurationPackage //自动配置包,与@ComponentScan扫描到的添加到IOC
|- @Import(AutoConfigurationImportSelector.class) //到METAINF/spring.factories中定义的bean添加到IOC容器中
|- @ComponentScan //包扫描
3. SpringBoot 数据访问
3.1 Spring Boot 整合 MyBatis
MyBatis 是一款优秀的持久层框架, Spring Boot 官方虽然没有对 MyBatis 进行整合,但是 MyBatis
团队自行适配了对应的启动器,进一步简化了使用 MyBatis 进行数据的操作
因为 Spring Boot 框架开发的便利性,所以实现 Spring Boot 与数据访问层框架(例如 MyBatis )的
整合非常简单,主要是引入对应的依赖启动器,并进行数据库相关参数设置即可
基础环境搭建:
1 )数据准备
MySQL 中,先创建了一个数据库 springbootdata ,然后创建了两个表 t_article t_comment
向表中插入数据。其中评论表 t_comment a_id 与文章表 t_article 的主键 id 相关联
# 创建数据库
CREATE DATABASE springbootdata;
# 选择使用数据库
USE springbootdata;
# 创建表t_article并插入相关数据
DROP TABLE IF EXISTS t_article;
CREATE TABLE t_article (
id int(20) NOT NULL AUTO_INCREMENT COMMENT '文章id',
title varchar(200) DEFAULT NULL COMMENT '文章标题',
content longtext COMMENT '文章内容',
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
INSERT INTO t_article VALUES ('1', 'Spring Boot基础入门', '从入门到精通讲解...');
INSERT INTO t_article VALUES ('2', 'Spring Cloud基础入门', '从入门到精通讲
解...');
# 创建表t_comment并插入相关数据
DROP TABLE IF EXISTS t_comment;
CREATE TABLE t_comment (
id int(20) NOT NULL AUTO_INCREMENT COMMENT '评论id',
content longtext COMMENT '评论内容',
author varchar(200) DEFAULT NULL COMMENT '评论作者',
a_id int(20) DEFAULT NULL COMMENT '关联的文章id',
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
INSERT INTO t_comment VALUES ('1', '很全、很详细', 'lucy', '1');
INSERT INTO t_comment VALUES ('2', '赞一个', 'tom', '1');
INSERT INTO t_comment VALUES ('3', '很详细', 'eric', '1');
INSERT INTO t_comment VALUES ('4', '很好,非常详细', '张三', '1');
INSERT INTO t_comment VALUES ('5', '很不错', '李四', '2');
2 )创建项目,引入相应的启动器

3 )编写与数据库表 t_comment t_article 对应的实体类 Comment Article
public class Comment {
private Integer id;
private String content;
private String author;
private Integer aId;
}
public class Article {
private Integer id;
private String title;
private String content;
}
4 )编写配置文件
        (1)在application.properties 配置文件中进行数据库连接配置
# MySQL数据库连接配置
spring:
datasource:
url: jdbc:mysql://localhost:3306/springbootdata?
serverTimezone=UTC&characterEncoding=UTF-8
username: root
password: wu7787879
注解方式整合 Mybatis
需求:实现通过 ID 查询 Comment 信息
1 )创建一个对 t_comment 表数据操作的接口 CommentMapper
public interface CommentMapper {
@Select("SELECT * FROM t_comment WHERE id =#{id}")
public Comment findById(Integer id);
}
2 )在 Spring Boot 项目启动类上添加 @MapperScan("xxx") 注解
@SpringBootApplication
@MapperScan("com.lagou.mapper")
public class Springboot02MybatisApplication {
public static void main(String[] args) {
SpringApplication.run(Springboot02MybatisApplication.class, args);
}
}
3 )编写测试方法
@RunWith(SpringRunner.class)
@SpringBootTest
class SpringbootPersistenceApplicationTests {
@Autowired
private CommentMapper commentMapper;
@Test
void contextLoads() {
Comment comment = commentMapper.findById(1);
System.out.println(comment);
}
}
打印结果:

控制台中查询的 Comment aId 属性值为 null ,没有映射成功。这是因为编写的实体类 Comment
中使用了驼峰命名方式将 t_comment 表中的 a_id 字段设计成了 aId 属性,所以无法正确映射查询结果。
为了解决上述由于驼峰命名方式造成的表字段值无法正确映射到类属性的情况,可以在 Spring Boot 全局 配置文件application.properties 中添加开启驼峰命名匹配映射配置,示例代码如下
#开启驼峰命名匹配映射
mybatis:
configuration:
map-underscore-to-camel-case: true
打印结果:

配置文件的方式整合 MyBatis
第一、二步骤使用 Free Mybatis plugin 插件生成
1 )创建一个用于对数据库表 t_article 数据操作的接口 ArticleMapper
@Mapper
public interface ArticleMapper {
public Article selectArticle(Integer id);
}
2 )创建 XML 映射文件
resources 目录下创建一个统一管理映射文件的包 mapper ,并在该包下编写与 ArticleMapper 接口方
应的映射文件 ArticleMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lagou.mapper.ArticleMapper">
<select id="selectArticle" resultType="Article">
select * from Article
</select>
</mapper>
3 )配置 XML 映射文件路径
在项目中编写的 XML 映射文件, Spring Boot 并无从知晓,所以无法扫描到该自定义编写的 XML 配置文 件,还必须在全局配置文件application.properties 中添加 MyBatis 映射文件路径的配置,同时需要添加实体类别名映射路径,示例代码如下
mybatis:
#配置MyBatis的xml配置文件路径
mapper-locations: classpath:mapper/*.xml
#配置XML映射文件中指定的实体类别名路径
type-aliases-package: com.lagou.base.pojo
4 )编写单元测试进行接口方法测试
@Autowired
private ArticleMapper articleMapper;
@Test
void contextLoads2() {
Article article = articleMapper.selectByPrimaryKey(1);
System.out.println(article);
}
打印结果:

3.2 Spring Boot 整合 Redis
1 )添加 Redis 依赖包
在项目的 pom.xml 中添加如下:
<!-- redis依赖包 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2 )配置 Redis 数据库连接
application.properties 中配置 redis 数据库连接信息,如下:
#redis配置
#Redis服务器地址
spring.redis.host=127.0.0.1
#Redis服务器连接端口
spring.redis.port=6379
#Redis数据库索引(默认为0)
spring.redis.database=0
#连接池最大连接数(使用负值表示没有限制)
spring.redis.jedis.pool.max-active=50
#连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.jedis.pool.max-wait=3000
#连接池中的最大空闲连接
spring.redis.jedis.pool.max-idle=20
#连接池中的最小空闲连接
spring.redis.jedis.pool.min-idle=2
#连接超时时间(毫秒)
spring.redis.timeout=5000
3 )编写 Redis 操作工具类
RedisTemplate 实例包装成一个工具类,便于对 redis 进行数据操作。
package com.lagou.utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
@Component
public class RedisUtils {
@Autowired
private RedisTemplate redisTemplate;
/**
* 读取缓存
*
* @param key
* @return
*/
public Object get(final String key) {
return redisTemplate.opsForValue().get(key);
}
/**
* 写入缓存
*/
public boolean set( String key, Object value) {
boolean result = false;
try {
redisTemplate.opsForValue().set(key, value,1, TimeUnit.DAYS);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 更新缓存
*/
public boolean getAndSet(final String key, String value) {
boolean result = false;
try {
redisTemplate.opsForValue().getAndSet(key, value);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 删除缓存
*/
public boolean delete(final String key) {
boolean result = false;
try {
redisTemplate.delete(key);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
}
4 )测试
写一个测试用例类来完成对 redis 的整合
@RunWith(SpringRunner.class)
@SpringBootTest
class Springboot02MybatisApplicationTests {
@Autowired
private RedisUtils redisUtils;
@Autowired
private CommentMapper commentMapper;
@Test
public void setRedisData() {
redisUtils.set("article_1",articleMapper.selectByPrimaryKey(1));
System.out.println("success");
}
@Test
public void getRedisData() {
Article article = (Article) redisUtils.get("article_1");
System.out.println(article);
}
4. SpringBoot 视图技术
4.1 支持的视图技术
前端模板引擎技术的出现,使前端开发人员无需关注后端业务的具体实现,只关注自己页面的呈现效果即可,并且解决了前端代码错综复杂的问题、实现了前后端分离开发。Spring Boot 框架对很多常用的模板引擎技术(如:FreeMarker Thymeleaf Mustache 等)提供了整合支持
Spring Boot 不太支持常用的 JSP 模板,并且没有提供对应的整合配置,这是因为使用嵌入式 Servlet 容器的Spring Boot 应用程序对于 JSP 模板存在一些限制 :
Jetty Tomcat 容器中, Spring Boot 应用被打包成 war 文件可以支持 JSP 。但 Spring Boot 默认使
用嵌入式 Servlet 容器以 JAR 包方式进行项目打包部署,这种 JAR 包方式不支持 JSP
如果使用 Undertow 嵌入式容器部署 Spring Boot 项目,也不支持 JSP 模板。( Undertow 是红帽公
司开发的一款基于 NIO 的高性能 Web 嵌入式服务器)
Spring Boot 默认提供了一个处理请求路径 “/error” 的统一错误处理器,返回具体的异常信息。使用
JSP 模板时,无法对默认的错误处理器进行覆盖,只能根据 Spring Boot 要求在指定位置定制错误页
面。
上面对 Spring Boot 支持的模板引擎进行了介绍,并指出了整合 JSP 模板的一些限制。接下来,对其
中常用的 Thymeleaf 模板引擎进行介绍,并完成与 Spring Boot 框架的整合实现
4.2 Thymeleaf
Thymeleaf 是一种现代的基于服务器端的 Java 模板引擎技术,也是一个优秀的面向 Java XML
XHTML HTML5 页面模板,它具有丰富的标签语言、函数和表达式,在使用 Spring Boot 框架进行页面设计时,一般会选择Thymeleaf 模板
4.2.1 Thymeleaf 语法
常用标签
HTML 页面上使用 Thymeleaf 标签, Thymeleaf 标签能够动态地替换掉静态内容,使页面动态展示。
为了大家更直观的认识 Thymeleaf ,下面展示一个在 HTML 文件中嵌入了 Thymeleaf 的页面文件,示例代码如下:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" type="text/css" media="all"
href="../../css/gtvg.css" th:href="@{/css/gtvg.css}" />
<title>Title</title>
</head>
<body>
<p th:text="${hello}">欢迎进入Thymeleaf的学习</p>
</body>
</html>

上述代码中, “xmlns:th=" http://www.thymeleaf.org "“ 用于引入 Thymeleaf 模板引擎标签,使用关键字 “th”标注标签是 Thymeleaf 模板提供的标签,其中, “th:href” 用于引入外联样式文件, “th:text” 用于动态显示标签文本内容。
除此之外, Thymeleaf 模板提供了很多标签,接下来,通过一张表罗列 Thymeleaf 的常用标签
th :标签
说明
th:insert
布局标签,替换内容到引入的文件
th:replace
页面片段包含(类似 JSP 中的 include 标签)
th:each
元素遍历(类似 JSP 中的 c:forEach 标签)
th:if
条件判断,如果为真
th:unless
条件判断,如果为假
th:switch
条件判断,进行选择性匹配
th:case
条件判断,进行选择性匹配
th:value
属性值修改,指定标签属性值
th:href
用于设定链接地址
th:src
用于设定链接地址
th:text
用于指定标签显示的文本内容
标准表达式
Thymeleaf 模板引擎提供了多种标准表达式语法,在正式学习之前,先通过一张表来展示其主要语法及说明
说明
表达式语法
变量表达式
${...}
选择变量表达式
*{...}
消息表达式
#{...}
链接 URL 表达式
@{...}
片段表达式
~{...}
1 .变量表达式 ${...}
变量表达式 ${...} 主要用于获取上下文中的变量值,示例代码如下:
<p th:text="${title}">这是标题</p>
示例使用了 Thymeleaf 模板的变量表达式 ${...} 用来动态获取 P 标签中的内容,如果当前程序没有启动或者当前上下文中不存在title 变量,该片段会显示标签默认值 这是标题 ;如果当前上下文中存在 title 变量并且程序已经启动,当前P 标签中的默认文本内容将会被 title 变量的值所替换,从而达到模板引擎页面数据动态替换的效果
同时, Thymeleaf 为变量所在域提供了一些内置对象,具体如下所示
# ctx:上下文对象
# vars:上下文变量
# locale:上下文区域设置
# request:(仅限Web Context)HttpServletRequest对象
# response:(仅限Web Context)HttpServletResponse对象
# session:(仅限Web Context)HttpSession对象
# servletContext:(仅限Web Context)ServletContext对象
结合上述内置对象的说明,假设要在 Thymeleaf 模板引擎页面中动态获取当前国家信息,可以使用
#locale 内置对象,示例代码如下
The locale country is: <span th:text="${#locale.country}">US</span>.
上述代码中,使用 th:text="${#locale.country}" 动态获取当前用户所在国家信息,其中标签内默认
内容为 US (美国),程序启动后通过浏览器查看当前页面时, Thymeleaf 会通过浏览器语言设置来识别当前用户所在国家信息,从而实现动态替换
2 .选择变量表达式 *{...}
选择变量表达式和变量表达式用法类似,一般用于从被选定对象而不是上下文中获取属性值,如果
没有选定对象,则和变量表达式一样,示例代码如下
<div th:object="${book}">
<p>titile: <span th:text="*{title}">标题</span>.</p>
</div>
*{title} 选择变量表达式获取当前指定对象 book title 属性值。
3 .消息表达式 #{...}
消息表达式 #{...} 主要用于 Thymeleaf 模板页面国际化内容的动态替换和展示,使用消息表达式 #{...}
进行国际化设置时,还需要提供一些国际化配置文件。
4 .链接表达式 @{...}
链接表达式 @{...} 一般用于页面跳转或者资源的引入,在 Web 开发中占据着非常重要的地位,并且使用也非常频繁,示例代码如下:
<a th:href="@{http://localhost:8080/order/details(orderId=${o.id})}">view</a>
<a th:href="@{/order/details(orderId=${o.id},pid=${p.id})}">view</a>
上述代码中,链接表达式 @{...} 分别编写了绝对链接地址和相对链接地址。在有参表达式中,需要
按照 @{ 路径 ( 参数名称 = 参数值,参数名称 = 参数值 ...)} 的形式编写,同时该参数的值可以使用变量表达式来传递动态参数值
5 .片段表达式 ~{...}
片段表达式 ~{...} 用来标记一个片段模板,并根据需要移动或传递给其他模板。其中,最常见的用法是使用th:insert th:replace 属性插入片段,示例代码如下:
<div th:insert="~{thymeleafDemo::title}"></div>
上述代码中,使用 th:insert 属性将 title片段模板引用到该 标签中。 thymeleafDemo 为模板名称, Thymeleaf 会自动查找 “/resources/templates/” 目录下的 thymeleafDemo 模板, title 为片段名称
4.2.2 基本使用
(1) Thymeleaf 模板基本配置
首先 在 Spring Boot 项目中使用 Thymeleaf 模板,首先必须保证引入 Thymeleaf 依赖,示例代码如
下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
其次,在全局配置文件中配置 Thymeleaf 模板的一些参数。一般 Web 项目都会使用下列配置,示例代码如:
spring.thymeleaf.cache = true #启用模板缓存
spring.thymeleaf.encoding = UTF_8 #模板编码
spring.thymeleaf.mode = HTML5 #应用于模板的模板模式
spring.thymeleaf.prefix = classpath:/templates/ #指定模板页面存放路径
spring.thymeleaf.suffix = .html #指定模板页面名称的后缀
上述配置中, spring.thymeleaf.cache 表示是否开启 Thymeleaf 模板缓存,默认为 true ,在开发过
程中通常会关闭缓存,保证项目调试过程中数据能够及时响应; spring.thymeleaf.prefix 指定了
Thymeleaf 模板页面的存放路径,默认为 classpath:/templates/ spring.thymeleaf.suffix 指定了
Thymeleaf 模板页面的名称后缀,默认为 .html
(2)静态资源的访问
开发 Web 应用时,难免需要使用静态资源。 Spring boot 默认设置了静态资源的访问路径。
使用 Spring Initializr 方式创建的 Spring Boot 项目,默认生成了一个 resources 目录,在 resources 目录中新建public resources static 三个子目录下, Spring boot 默认会挨个从 public resources static 里面查找静态资源
4.2.3 完成数据的页面展示
1. 创建 Spring Boot 项目,引入 Thymeleaf 依赖

2. 编写配置文件
打开 application.properties 全局配置文件,在该文件中对 Thymeleaf 模板页面的数据缓存进行设置
# thymeleaf页面缓存设置(默认为true),开发中方便调试应设置为false,上线稳定后应保持默认
true
spring.thymeleaf.cache=false
使用 “spring.thymeleaf.cache=false” Thymeleaf 默认开启的缓存设置为了 false ,用来关闭模板页面缓存
3. 创建 web 控制类
在项目中创建名为 com.lagou.controller 的包,并在该包下创建一个用于前端模板页面动态数据替
换效果测试的访问实体类 LoginController
@Controller
public class LoginController {
/**
* 获取并封装当前年份跳转到登录页login.html
*/
@RequestMapping("/toLoginPage")
public String toLoginPage(Model model){
model.addAttribute("currentYear",
Calendar.getInstance().get(Calendar.YEAR));
return "login";
}
toLoginPage() 方法用于向登录页面 login.html 跳转,同时携带了当前年份信息 currentYear
4 .创建模板页面并引入静态资源文件
“classpath:/templates/” 目录下引入一个用户登录的模板页面 login.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1,shrinkto-fit=no">
<title>用户登录界面</title>
<link th:href="@{/login/css/bootstrap.min.css}" rel="stylesheet">
<link th:href="@{/login/css/signin.css}" rel="stylesheet">
</head>
<body class="text-center">
<!-- 用户登录form表单 -->
<form class="form-signin">
<img class="mb-4" th:src="@{/login/img/login.jpg}" width="72" height="72">
<h1 class="h3 mb-3 font-weight-normal">请登录</h1>
<input type="text" class="form-control"
th:placeholder="用户名" required="" autofocus="">
<input type="password" class="form-control"
th:placeholder="密码" required="">
<div class="checkbox mb-3">
<label>
<input type="checkbox" value="remember-me"> 记住我
</label>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit" >登录</button>
<p class="mt-5 mb-3 text-muted">© <span
th:text="${currentYear}">2019</span>-<span
th:text="${currentYear}+1">2020</span></p>
</form>
</body>
</html>
通过 “xmlns:th=" http://www.thymeleaf.org "” 引入了 Thymeleaf 模板标签;
使用 “th:href” “th:src” 分别引入了两个外联的样式文件和一个图片;
使用 “th:text” 引入了后台动态传递过来的当前年份 currentYear
5 .效果测试

可以看出,登录页面 login.html 显示正常,在文件 4-3 中使用 “th:*” 相关属性引入的静态文件生效,
并且在页面底部动态显示了当前日期 2019-2020 ,而不是文件中的静态数字 2019-2020 。这进一步说明了Spring Boot Thymeleaf 整合成功,完成了静态资源的引入和动态数据的显示
5. SpringBoot 实战演练
实战技能补充: lombok
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<!--只在编译阶段生效-->
<scope>provided</scope>
</dependency>
需求:实现用户的 CRUD 功能
1 )创建 springboot 工程

2 )导入 pom.xml
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.3</version>
</dependency>
3 User 实体类编写
@Data
public class User implements Serializable {
private Integer id;
private String username;
private String password;
private String birthday;
private static final long serialVersionUID = 1L;
}
4 UserMapper 编写及 Mapper 文件
public interface UserMapper {
int deleteByPrimaryKey(Integer id);
int insert(User record);
int insertSelective(User record);
User selectByPrimaryKey(Integer id);
int updateByPrimaryKeySelective(User record);
int updateByPrimaryKey(User record);
List<User> queryAll();
}
<?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.example.base.mapper.UserMapper">
<resultMap id="BaseResultMap" type="com.example.base.pojo.User">
<id column="id" jdbcType="INTEGER" property="id" />
<result column="username" jdbcType="VARCHAR" property="username" />
<result column="password" jdbcType="VARCHAR" property="password" />
<result column="birthday" jdbcType="VARCHAR" property="birthday" />
</resultMap>
<sql id="Base_Column_List">
id, username, password, birthday
</sql>
<select id="selectByPrimaryKey" parameterType="java.lang.Integer"
resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from user
where id = #{id,jdbcType=INTEGER}
</select>
<select id="queryAll" resultType="com.example.base.pojo.User">
select <include refid="Base_Column_List" />
from user
</select>
.......
</mapper>
5 UserService 接口及实现类编写
package com.lagou.service.impl;
import com.lagou.mapper.UserMapper;
import com.lagou.pojo.User;
import com.lagou.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public List<User> queryAll() {
return userMapper.queryAll();
}
@Override
public User findById(Integer id) {
return userMapper.selectByPrimaryKey(id);
}
@Override
public void insert(User user) {
//userMapper.insert(user); //将除id所有的列都拼SQL
userMapper.insertSelective(user); //只是将不为空的列才拼SQL
}
@Override
public void deleteById(Integer id) {
userMapper.deleteByPrimaryKey(id);
}
@Override
public void update(User user) {
userMapper.updateByPrimaryKeySelective(user);
}
}
6 UserController 编写
package com.lagou.controller;
import com.lagou.pojo.User;
import com.lagou.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.yaml.snakeyaml.events.Event;
import java.util.List;
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
/**
* restful格式进行访问
* 查询:GET
* 新增: POST
* 更新:PUT
* 删除: DELETE
*/
/**
* 查询所有
* @return
*/
@GetMapping("/query")
public List<User> queryAll(){
return userService.queryAll();
}
/**
* 通过ID查询
*/
@GetMapping("/query/{id}")
public User queryById(@PathVariable Integer id){
return userService.findById(id);
}
/**
* 删除
* @param id
* @return
*/
@DeleteMapping("/delete/{id}")
public String delete(@PathVariable Integer id){
userService.deleteById(id);
return "删除成功";
}
/**
* 新增
* @param user
* @return
*/
@PostMapping("/insert")
public String insert(User user){
userService.insert(user);
return "新增成功";
}
/**
* 修改
* @param user
* @return
*/
@PutMapping("/update")
public String update(User user){
userService.update(user);
return "修改成功";
}
}
8 application.yml
##服务器配置
server:
port: 8090
servlet:
context-path: /
##数据源配置
spring:
datasource:
name: druid
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://localhost:3306/springbootdata?characterEncoding=utf-
8&serverTimezone=UTC
username: root
password: wu7787879
#整合mybatis
mybatis:
mapper-locations: classpath:mapper/*Mapper.xml #声明Mybatis映射文件所在的位置
9 )启动类
@SpringBootApplication
//使用的Mybatis,扫描com.lagou.mapper
@MapperScan("com.lagou.mapper")
public class Springbootdemo5Application {
public static void main(String[] args) {
SpringApplication.run(Springbootdemo5Application.class, args);
}
}
10 )使用 Postman 测试

 

 

6. Spring Boot 项目部署
需求:将 Spring Boot 项目使用 maven 指令打成 jar 包并运行测试
分析:
1. 需要添加打包组件将项目中的资源、配置、依赖包打到一个 jar 包中;可以使用 maven
package
2. 部署: java -jar 包名
步骤实现:
添加打包组件
<build>
<plugins>
<!-- 打jar包时如果不配置该插件,打出来的jar包没有清单文件 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
部署运行
java -jar 包名

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【数据结构】堆的实现及排序

目录一、树的相关概念及其特殊二叉树1、数的相关概念2、特殊二叉树二、堆1、堆的实现1.1、堆向下调整算法和向上调整算法的时间复杂度1.2、堆的构建1.3、堆的插入1.4、堆的删除1.5、取堆顶的数据、堆的个数及堆的判空2、堆的排序一、树的相关概念及其特殊二叉树 讲堆之前&#…

透视虎牙斗鱼三季报:游戏直播在各自“求变”中见分晓

游戏直播行业&#xff0c;依然硝烟弥漫。 经历千播大战、熊猫出局的洗礼后&#xff0c;虎牙和斗鱼双方缠斗升级&#xff0c;另有B站和抖音、快手等视频平台来势汹汹&#xff0c;抢夺仅有的市场蛋糕。 而在游戏行业遇冷、政策趋严等因素多重考验下&#xff0c;这场争夺战无疑将…

fsync

由于目前操作系统都具有延迟写(delayed write)功能&#xff0c; fwrite/write并不会直接把数据写到磁盘上&#xff0c; 而是在buffer满时才开始写入到磁盘。 要想把数据写到磁盘上&#xff0c;需要调用fsync函数 open(fd) write(fd) fsync(fd) close(fd) 或者 fopen(fp…

金仓数据库KingbaseES查询计划剖析

目录 1、KingbaseES数据库中的查询生命周期 2、数据设置 3、KingbaseES解释一个查询 4、什么是数据库中的缓冲区和缓存&#xff1f; 5、VERBOSE 命令参数 6、KingbaseES中的 FORMAT 解释 7、总结EXPLAIN使用方式 8、执行计划查看 了解KingbaseES查询计划对于开发人员和…

HarmonyOS应用API手势方法-绑定手势方法

述&#xff1a;为组件绑定不同类型的手势事件&#xff0c;并设置事件的响应方法。 Api&#xff1a;从API Version 7开始支持 一、绑定手势识别&#xff1a; 通过如下属性给组件绑定手势识别&#xff0c;手势识别成功后可以通过事件回调通知组件。 名称参数类型默认值描述ge…

银河麒麟V10+达梦数据库8保姆级安装教程

银河麒麟V10达梦数据库8保姆级安装教程 一、系统和数据库的下载 银河麒麟V10版本&#xff1a; 首页 → 桌面操作系统 → 银河麒麟桌面操作系统V10 → 试用&#xff08;填写信息&#xff09; → 点击地址进行下载&#xff08;X86centos7&#xff09; #如果不想进行上面的操作,…

Casbin——Java版本(笔记)

文章目录一、Casbin 是什么&#xff1f;二、快速开始2.1 载入配置2.2 如何判断权限2.3 model.conf2.3.1 基本格式2.3.2 SpringBoot下的使用2.3.3 匹配的函数内置函数自定义函数2.3.4 基于角色的访问控制角色的层次区分用户和角色隐式角色权限域内RBAC角色与函数2.3.5 优先级模型…

react事件系统(老版本)

带着问题阅读探索 React 为什么有自己的事件系统&#xff1f;什么是事件合成 &#xff1f;如何实现的批量更新&#xff1f;事件系统如何模拟冒泡和捕获阶段&#xff1f;如何通过 dom 元素找到与之匹配的fiber&#xff1f;为什么不能用 return false 来阻止事件的默认行为&…

python【PyQt5】的环境搭建和使用(全网最全)其一

什么是pyQT pyqt是一个用于创建GUI应用程序的跨平台工具包&#xff0c;它将python与qt库融为一体。也就是说&#xff0c;pyqt允许使用python语言调用qt库中的API。这样做的最大好处就是在保存了qt高运行效率的同时&#xff0c;大大提高开发效率。因为&#xff0c;使用python语言…

城市路边停车收费系统/停车收费管理系统

摘 要 近年来&#xff0c;随着社会的进步和发展&#xff0c;车辆也在迅速增加&#xff0c;城市交通的瓶颈不仅体现在道路交通的拥挤上&#xff0c;也体现在传统停车场管理效率和安全性大大滞后于社会的需要&#xff0c;给人们的生活带来了极大的不便。尤其&#xff0c;随着汽车…

二、MongoDB简介及基本操作

mongodb是一个基于文档的强大、灵活、易于扩展的通用型数据库。是基于分布式文件存储的数据库。其由 C 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。 mongodb也是一个介于关系数据库和非关系数据库之间的产品&#xff0c;是非关系数据库当中功能最丰富&…

运动健身买什么耳机好用、最优秀的健身耳机推荐分享

冬天绝对是个减肥的好季节&#xff0c;因为这个季节天气比较冷&#xff0c;我们在运动过程中消耗的热量也就会更多&#xff0c;因此选择一款不错的运动耳机来用坚持就显得尤为重要了。这款运动耳机要能稳定在耳朵上&#xff0c;还要具备防水功能&#xff0c;同时音质上也要有保…

闲人闲谈PS之三十四——项目成本费用控制阈值

**惯例闲话&#xff1a;**最近有小伙伴问闲人有没有PS顾问资源&#xff0c;闲人问了一圈&#xff0c;结果发现都没有档期&#xff0c;不免让闲人有些失落&#xff0c;好心答应帮忙&#xff0c;结果帮不上…但是隐隐约约觉得在几年前说的话被应验了&#xff0c;PS模块一定是个热…

Ubuntu G++ 编译C++源文件

工程项目代码简短的时候使用 G 进行功能模块测试 过程分为&#xff1a; 预处理&#xff1a;展开头文件&#xff0c;去掉主食&#xff0c;条件编译和文件包含编译&#xff1a;检查语法&#xff0c;生成汇编代码汇编&#xff1a;汇编代码转换成机器码链接&#xff1a;Link 主要是…

王学岗音视频开发(一)—————配置NDK开发环境

Android studio准备 Android studio需要下载Android6.0版本(Android SDK Platform 23)&#xff0c;最小支持Android6.0 NDK 下载 cmake下载安装 Android studio 代理配置 dl.google.com可能会被屏蔽&#xff0c;首先查下其IP地址。查到IP地址后修改etc/hosts文件。 Andr…

pytorch深度学习实战lesson25

第二十五课 network in network(NIN) NIN 叫做network in network或者叫做网络中的网络。这个网络现在用的不多&#xff0c;几乎很少被用到。但是它里面提出了比较重要的概念&#xff0c;在之后很多网络都会被持续的用到。所以今天认识一下这一个网络。 目录 理论部分 实践部…

高并发下丢失更新的解决方案

作者&#xff1a;谢益培 1 背景 关键词&#xff1a;并发、丢失更新 预收款账户表上有个累计抵扣金额的字段&#xff0c;该字段的含义是统计商家预收款账户上累计用于抵扣结算成功的金额数。更新时机是&#xff0c;账单结算完成时&#xff0c;更新累计抵扣金额累计抵扣金额账…

ImmunoChemistry艾美捷Annexin V-FITC细胞凋亡检测试剂盒方案

膜联蛋白V是具有血管抗凝血活性的钙和磷脂结合蛋白家族的成员。体外实验结果表明&#xff0c;它可能通过与凝血酶原竞争磷脂酰丝氨酸&#xff08;PS&#xff09;结合位点而在抑制凝血中发挥作用。在健康细胞中&#xff0c;PS通常保存在细胞膜的内小叶&#xff08;胞质侧&#x…

网络是怎样连接的--TCP大致控制流程

文章目录5.1 协议栈内部结构5.2 套接字作用5.3 创建套接字5.4 两类控制信息5.5 连接操作的实际过程5.6 收发数据5.6.1将http请求消息发给协议栈5.6.2 注意对较大数据进行拆分5.6.3 序号和ACK5.6.4 等待超时时间5.6.5 窗口机制提升效率5.6.6 ACK与窗口合并5.7 断开连接5.8 删除套…

MCE | 新冠 德尔塔病毒

冠状病毒&#xff0c;其表面有突出的棒状尖峰&#xff0c;在电镜下可以观察到像王冠一样的放射状凸起而得名。冠状病毒的基本结构如图 1 所示&#xff0c;包括刺突糖蛋白 (S)、包膜 (E)、膜 (M) 和核衣壳 (N)。 图 1. 冠状病毒结构2020 年石正丽教授在 Nature 发表的论文 A …