spring boot

This commit is contained in:
luoxiang 2019-08-25 17:44:01 +08:00
parent 358200d448
commit ba3e36dca9
20 changed files with 3896 additions and 4524 deletions

View File

@ -1,25 +1,23 @@
# spring boot 实现分布式 session
## 目录<br/>
# Spring Boot 实现分布式 Session
<nav>
<a href="#一项目结构">一、项目结构</a><br/>
<a href="#二分布式session的配置">二、分布式session的配置</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#21-引入依赖">2.1 引入依赖</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#22-Redis配置">2.2 Redis配置</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#23-启动类上添加EnableRedisHttpSession-注解开启-spring-session-redis-整合方案的自动配置">2.3 启动类上添加@EnableRedisHttpSession 注解开启 spring-session-redis 整合方案的自动配置</a><br/>
<a href="#三验证分布式session">三、验证分布式session</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#31-创建测试controller和测试页面">3.1 创建测试controller和测试页面</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#32-启动项目">3.2 启动项目</a><br/>
## 正文<br/>
<a href="#二实现分布式-Session">二、实现分布式 Session</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#21-基本依赖">2.1 基本依赖</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#22-实现原理">2.2 实现原理</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#23-自动配置">2.3 自动配置</a><br/>
<a href="#三验证分布式-Session">三、验证分布式 Session</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#31-测试准备">3.1 测试准备</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#32-测试结果">3.2 测试结果</a><br/>
</nav>
## 一、项目结构
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-boot-session.png"/> </div>
## 二、实现分布式 Session
## 二、分布式session的配置
#### 2.1 引入依赖
### 2.1 基本依赖
```xml
<!--分布式 session 相关依赖-->
@ -33,7 +31,11 @@
</dependency>
```
#### 2.2 Redis配置
### 2.2 实现原理
Spring 通过将 Session 信息存储到公共容器中,这样不同的 Web 服务就能共享到相同的 Session 信息,从而实现分布式 Session。Spring 支持使用 Redis JdbcmongodbHazelcast 等作为公共的存储容器,可以在配置文件中使用参数 session.store-type 进行指定。
这里我们以 Redis 作为公共的存储容器,配置如下。同时对于 Redis 存储方案,官方提供了 Jedis 和 Lettuce 两种客户端连接,这里我们选用的是 Jedis 连接:
```yaml
spring:
@ -57,15 +59,11 @@ spring:
# 如果是集群节点 采用如下配置指定节点
#spring.redis.cluster.nodes
```
有两点需要特别说明:
### 2.3 自动配置
1. spring-session 不仅提供了 redis 作为公共 session 存储的方案,同时也支持 jdbc、mongodb、Hazelcast 等作为公共 session 的存储,可以用 session.store-type 指定;
2. 对于 redis 存储方案而言,官方也提供了不止一种整合方式,这里我们选取的整合方案是 jedis 客户端作为连接,当然也可以使用 Lettuce 作为客户端连接。
#### 2.3 启动类上添加@EnableRedisHttpSession 注解开启 spring-session-redis 整合方案的自动配置
在启动类上添加 @EnableRedisHttpSession 开启 spring-session-redis 整合方案的自动配置:
```java
@SpringBootApplication
@ -81,9 +79,11 @@ public class SpringBootSessionApplication {
## 三、验证分布式session
## 三、验证分布式 Session
#### 3.1 创建测试controller和测试页面
### 3.1 测试准备
创建测试接口和测试页面:
```java
@Controller
@ -129,7 +129,7 @@ public class LoginController {
</html>
```
session 信息展示页面 home.ftl
Session 信息展示页面 home.ftl
```jsp
<!doctype html>
@ -144,20 +144,17 @@ session 信息展示页面 home.ftl
</html>
```
#### 3.2 启动项目
### 3.2 测试结果
由于我们这里采用的是 spring boot 的内置容器作为 web 容器,所以直接启动两个实例测试即可。
这里我采用的是 Spring Boot 的内置的 Web 容器,直接启动两个实例测试即可:
应用 1 启动配置:
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-boot-session-app1.png"/> </div>
应用 2 启动配置,需要用 `--server.port ` 指定不同的端口号:
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-boot-session-app2.png"/> </div>
**测试结果:**
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-boot-session-8080.png"/> </div>
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-boot-session-8090.png"/> </div>

View File

@ -1,25 +1,23 @@
# spring session 实现分布式 session
## 目录<br/>
# Spring 实现分布式 Session
<nav>
<a href="#一项目结构">一、项目结构</a><br/>
<a href="#二分布式session的配置">二、分布式session的配置</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#21-引入依赖">2.1 引入依赖</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#22-在webxml中配置session拦截器">2.2 在web.xml中配置session拦截器</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#23-创建配置文件spring--sessionxml配置redis连接">2.3 创建配置文件spring- session.xml配置redis连接</a><br/>
<a href="#三验证分布式session">三、验证分布式session</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#31-创建测试controller和测试页面">3.1 创建测试controller和测试页面</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#32-启动项目">3.2 启动项目</a><br/>
## 正文<br/>
<a href="#二实现分布式-Session">二、实现分布式 Session</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#21-基本依赖">2.1 基本依赖</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#22-Session-拦截器">2.2 Session 拦截器</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#23-实现原理">2.3 实现原理</a><br/>
<a href="#三验证分布式-Session">三、验证分布式 Session</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#31-测试准备">3.1 测试准备</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#32-测试结果">3.2 测试结果</a><br/>
</nav>
## 一、项目结构
分布式 session 主要配置文件为 spring-session.xml 和 web.xml其他的配置为标准的 web 工程的配置
分布式 Session 主要配置文件为 spring-session.xml 和 web.xml其他的配置为标准的 web 工程的配置
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-session.png"/> </div>
## 二、实现分布式 Session
## 二、分布式session的配置
#### 2.1 引入依赖
### 2.1 基本依赖
```xml
<!--分布式 session 相关依赖-->
@ -40,7 +38,9 @@
</dependency>
```
#### 2.2 在web.xml中配置session拦截器
### 2.2 Session 拦截器
在 web.xml 中配置 Session 拦截器:
```xml
<!--配置http session-->
@ -55,12 +55,9 @@
```
#### 2.3 创建配置文件spring- session.xml配置redis连接
### 2.3 实现原理
有两点需要特别说明:
1. spring-session 不仅提供了 redis 作为公共 session 存储的方案,同时也支持 jdbc、mongodb、Hazelcast 等作为公共 session 的存储;
2. 对于 redis 存储方案而言,官方也提供了不止一种整合方式,这里我们选取的整合方案是 jedis 客户端作为连接,当然也可以使用 Lettuce 作为客户端连接。
Spring 通过将 Session 信息存储到公共容器中,这样不同的 Web 服务就能共享到相同的 Session 信息,从而实现分布式 Session。Spring 支持使用 Redis JdbcmongodbHazelcast 等作为公共的存储容器。这里我们以 Redis 作为公共的存储容器,需要创建配置文件 spring- session.xml内容如下
```xml
<?xml version="1.0" encoding="UTF-8"?>
@ -116,9 +113,11 @@
</beans>
```
## 三、验证分布式session
## 三、验证分布式 Session
#### 3.1 创建测试controller和测试页面
### 3.1 测试准备
创建测试接口和测试页面:
```java
@Controller
@ -181,20 +180,17 @@ session 信息展示页面 (home.jsp)
</html>
```
#### 3.2 启动项目
### 3.2 测试结果
这里我们采用两个 tomcat 分别启动项目,在第一个项目 index.jsp 页面进行登录,第二个项目不登录,直接访问 session 展示页home.jsp
这里采用两个 Tomcat 分别启动项目,在第一个项目的 index.jsp 页面进行登录;第二个项目不登录,直接访问 Session 展示页home.jsp :
tomcat 1 配置:
Tomcat 1 配置:
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-session-tomcat01.png"/> </div>
tomcat 2 配置:
Tomcat 2 配置:
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-session-tomcat02.png"/> </div>
**测试结果:**
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-session-8080.png"/> </div>
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-session-8090.png"/> </div>

View File

@ -1,52 +1,48 @@
# spring boot actuator
# Spring Boot Actuator
## 目录<br/>
<a href="#一用例涉及到的概念综述">一、用例涉及到的概念综述</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#11-端点">1.1 端点</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#12-启用端点">1.2 启用端点</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#13-暴露端点">1.3 暴露端点</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#14-健康检查信息">1.4 健康检查信息</a><br/>
<nav>
<a href="#一相关概念">一、相关概念</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#11-执行端点">1.1 执行端点</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#12-启用端点">1.2 启用端点</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#13-暴露端点">1.3 暴露端点</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#14-健康检查">1.4 健康检查</a><br/>
<a href="#二项目说明">二、项目说明</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#11-项目结构说明">1.1 项目结构说明</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#12-主要依赖">1.2 主要依赖</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#13-项目配置">1.3 项目配置</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#14-查看监控状态">1.4 查看监控状态</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#21-项目结构">2.1 项目结构</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#22-主要依赖">2.2 主要依赖</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#23-项目配置">2.3 项目配置</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#24-监控状态">2.4 监控状态</a><br/>
<a href="#三自定义健康检查指标">三、自定义健康检查指标</a><br/>
<a href="#四自定义健康状态聚合规则">四、自定义健康状态聚合规则</a><br/>
<a href="#五Endpoint自定义端点">五、@Endpoint自定义端点</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#51-自定义端点">5.1 自定义端点</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#52-访问自定义端点http//1270018080/actuator/customEndPoint">5.2 访问自定义端点http://127.0.0.1:8080/actuator/customEndPoint</a><br/>
## 正文<br/>
<a href="#五自定义端点">五、自定义端点</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#51-Hyperic-Sigar">5.1 Hyperic Sigar </a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#52-自定义端点">5.2 自定义端点</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#53-访问自定义端点">5.3 访问自定义端点</a><br/>
</nav>
## 一、相关概念
### 1.1 执行端点
## 一、用例涉及到的概念综述
### 1.1 端点
执行器端点endpoints可用于监控应用及与应用进行交互Spring Boot 包含很多内置的端点你也可以添加自己的。例如health 端点提供了应用的基本健康信息。 端点暴露的方式取决于你采用的技术类型,大部分应用选择 HTTP 监控,端点的 ID 映射到一个 URL。例如health 端点默认映射到/health。
下面的端点都是可用的:
Spring Boot 提供了很多执行器端点endpoints用于监控应用的运行情况以及与应用进行交互并支持将这些端点按需暴露给外部使用。 端点暴露的方式取决于你采用的技术类型,通常可以端点的 ID 映射到一个 URL从而可以将端口暴露为 HTTP 服务。例如将health 端点默认映射到 /health。Spring Boot 内置的常用端点如下:
| ID | 描述 | 是否敏感 |
| ----------- | ------------------------------------------------------------ | -------- |
| actuator | 为其他端点提供基于超文本的导航页面,需要添加 Spring HATEOAS 依赖 | true |
| autoconfig | 显示一个自动配置类的报告,该报告展示所有自动配置候选者及它们被应用或未被应用的原因 | true |
| beans | 显示一个应用中所有 Spring Beans 的完整列表 | true |
| configprops | 显示一个所有@ConfigurationProperties 的集合列表 | true |
| beans | 显示一个应用中所有 Spring Beans 的完整列表 | true |
| configprops | 显示一个所有 @ConfigurationProperties 的集合列表 | true |
| dump | 执行一个线程转储 | true |
| env | 暴露来自 Spring ConfigurableEnvironment 的属性 | true |
| env | 暴露来自 Spring ConfigurableEnvironment 的属性 | true |
| flyway | 显示数据库迁移路径,如果有的话 | true |
| health | 展示应用的健康信息(当使用一个未认证连接访问时显示一个简单的'status',使用认证连接访问则显示全部信息详情) | false |
| health | 展示应用的健康信息(当使用一个未认证连接访问时显示一个简单的 'status',使用认证连接访问则显示全部信息详情) | false |
| info | 显示任意的应用信息 | false |
| liquibase | 展示任何 Liquibase 数据库迁移路径,如果有的话 | true |
| metrics | 展示当前应用的'metrics'信息 | true |
| mappings | 显示一个所有@RequestMapping 路径的集合列表 | true |
| liquibase | 展示任何 Liquibase 数据库迁移路径,如果有的话 | true |
| metrics | 展示当前应用的 'metrics' 信息 | true |
| mappings | 显示一个所有 @RequestMapping 路径的集合列表 | true |
| shutdown | 允许应用以优雅的方式关闭(默认情况下不启用) | true |
| trace | 显示 trace 信息(默认为最新的 100 条 HTTP 请求) | true |
| trace | 显示 trace 信息(默认为最新的 100 条 HTTP 请求) | true |
如果使用 Spring MVC你还可以使用以下端点:
如果使用了 Spring MVC还有以下额外的端点:
| ID | 描述 | 是否敏感 |
| -------- | ------------------------------------------------------------ | -------- |
@ -55,13 +51,13 @@
| jolokia | 通过 HTTP 暴露 JMX beans依赖 Jolokia | true |
| logfile | 返回日志文件内容(如果设置 logging.file 或 logging.path 属性),支持使用 HTTP Range 头接收日志文件内容的部分信息 | |
根据端点暴露的方式sensitive 属性可用做安全提示,例如,在使用 HTTP 访问敏感sensitive端点时需要提供用户名/密码(如果没有启用 web 安全,可能会简化为禁止访问该端点)
端点按照安全属性可以分为敏感和非敏感两类,在启用 Web 安全服务后,访问敏感端点时需要提供用户名和密码,如果没有启用 web 安全服务Spring Boot 可能会直接禁止访问该端点
### 1.2 启用端点
默认情况下,除了以外的所有端点 shutdown 都已启用。要配置端点的启用,请使用其 management.endpoint.<id>.enabled 属性。以下示例启用 shutdown 端点
默认情况下,除了 shutdown 以外的所有端点都已启用。端点的启停可以使用 management.endpoint.\<id>.enabled 属性来进行控制,示例如下
```properties
management.endpoint.shutdown.enabled = true
@ -71,7 +67,7 @@ management.endpoint.shutdown.enabled = true
### 1.3 暴露端点
由于端点可能包含敏感信息,因此应仔细考虑何时公开它们。下表显示了内置端点的默认曝光情况:
由于端点可能包含敏感信息,因此应仔细考虑后再决定是否公开。下表显示了内置端点的默认公开情况:
| ID | JMX | Web |
| -------------- | ----- | ---- |
@ -97,7 +93,7 @@ management.endpoint.shutdown.enabled = true
| shutdown | 是 | 没有 |
| threaddump | 是 | 没有 |
**可以选择是否暴露端点include或者排除端点exclude,其中排除优先于暴露:**
可以选择是否暴露端点include或者排除端点exclude,其中排除属性优先于暴露属性
| 属性 | 默认 |
| ----------------------------------------- | ------------ |
@ -108,9 +104,9 @@ management.endpoint.shutdown.enabled = true
### 1.4 健康检查信息
### 1.4 健康检查
您可以使用健康信息来检查正在运行的应用程序的状态。health 端点公开的信息取决于 management.endpoint.health.show-details 可以使用以下值之一配置的属性
health 端点用于暴露程序运行的健康状态,暴露的信息的详细程度由 management.endpoint.health.show-details 来控制,它具有以下三个可选值
| 名称 | 描述 |
| --------------- | ------------------------------------------------------------ |
@ -122,14 +118,14 @@ management.endpoint.shutdown.enabled = true
## 二、项目说明
#### 1.1 项目结构说明
### 2.1 项目结构
1. CustomHealthIndicator 自定义健康指标;
2. CustomHealthAggregator自定义健康聚合规则;
3. CustomEndPoint:自定义端点。
- **CustomHealthIndicator** 自定义健康指标;
- **CustomHealthAggregator**:自定义健康状态聚合规则;
- **CustomEndPoint**:自定义端点。
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-boot-actuator.png"/> </div>
#### 1.2 主要依赖
### 2.2 主要依赖
```xml
<dependency>
@ -138,7 +134,7 @@ management.endpoint.shutdown.enabled = true
</dependency>
```
#### 1.3 项目配置
### 2.3 项目配置
```yaml
management:
@ -158,12 +154,12 @@ management:
FATAL: 503
```
#### 1.4 查看监控状态
### 2.4 监控状态
导入 actuator 的 start 并进行配置后,访问 http://127.0.0.1:8080/actuator/health 就可以看到对应的项目监控状态。
导入 Actuator 的 starter 并进行配置后,访问 http://127.0.0.1:8080/actuator/health 就可以看到对应的项目监控状态。
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/health.png"/> </div>
需要注意的是这里的监控状态根据实际项目所用到的技术不同而不同。因为以下 HealthIndicators 情况在适当时由 Spring Boot 自动配置的:
健康指标 HealthIndicators 由 Spring Boot 自动配置,因此这里显示监控信息是由项目所使用的技术栈而决定的:
| 名称 | 描述 |
| ------------------------------------------------------------ | -------------------------------- |
@ -186,7 +182,6 @@ management:
```java
/**
* @author : heibaiying
* @description : 自定义健康检查指标
*/
@Component
@ -213,8 +208,7 @@ public class CustomHealthIndicator implements HealthIndicator {
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/health-fatal-200.png"/> </div>
这里我们可以看到自定义检查不论是否通过都不会影响整体的 status,两种情况下都是 status 都是“up”。如果我们想通过自定义的检查检查去影响最终的检查结果比如我们健康检查针对的是支付业务在支付业务的不可用的情况下我们就认为整个服务是不可用的。这个时候就需要实现自定义实现健康状态的聚合。
自定义检查不论是否通过都不会影响整体的 status因此两种情况下的 status 值都是 `up`。如果想通过自定义检查去影响整体的检查结果,比如健康检查针对的是支付业务,在支付业务的不可用的情况下,我们就应该认为整个服务是不可用的,这个时候就需要通过自定义健康状态的聚合规则来实现。
@ -222,8 +216,7 @@ public class CustomHealthIndicator implements HealthIndicator {
```java
/**
* @author : heibaiying
* @description : 对所有的自定义健康指标进行聚合,按照自定义规则返回总和健康状态
* @description : 对所有的自定义健康指标进行聚合,按照自定义规则返回总的健康状态
*/
@Component
public class CustomHealthAggregator implements HealthAggregator {
@ -241,16 +234,16 @@ public class CustomHealthAggregator implements HealthAggregator {
}
```
当我们自定义健康检查不通过时候的结果如下:
当我们自定义健康检查不通过时候的结果如下:
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/actuator-heath-503.png"/> </div>
这里需要注意的是返回我们自定义的聚合状态的时候,状态码也变成了 503,这是我们在配置文件中进行定义的:
这里需要注意的是返回自定义的聚合状态时,状态码也变成了 503这是我们在配置文件中进行定义的:
```properties
management.health.status.http-mapping.FATAL = 503
```
下表显示了内置状态的默认状态映射:
下表显示了内置状态的默认映射:
| Status | Mapping |
| -------------- | -------------------------------------------- |
@ -261,19 +254,18 @@ management.health.status.http-mapping.FATAL = 503
## 五、@Endpoint自定义端点
## 五、自定义端点
#### 5.1 自定义端点
### 5.1 Hyperic Sigar
spring boot 支持使用@Endpoint 来自定义端点暴露应用信息。这里我们采用第三方 sigar 来暴露服务所在硬件的监控信息
Spring Boot 支持使用 `@Endpoint` 来自定义端点暴露信息,这里以暴露服务所在硬件的监控信息为例。想要获取服务器信息需要通过第三方工具来实现,这里我们使用的是 Sigar。Sigar 是 Hyperic HQ 下的数据收集组件,其底层采用 C 语言进行编写,它通过本地方法调用操作系统的 API 来获取系统相关数据 ,其 JAR 包的下载地址为https://sourceforge.net/projects/sigar/
Sigar 是 Hyperic-hq 产品的基础包,是 Hyperic HQ 主要的数据收集组件。Sigar.jar 的底层是用 C 语言编写的,它通过本地方法来调用操作系统 API 来获取系统相关数据 [jar 包下载地址](https://sourceforge.net/projects/sigar/)。
Sigar 为不同平台提供了不同的库文件,下载后需要将库文件放到服务所在主机的对应位置:
Sigar 为不同平台提供了不同的库文件,下载后需要将库文件放到服务所在主机的对应位置:
- **Windows** :根据操作系统版本选择 sigar-amd64-winnt.dll 或 sigar-x86-winnt.dll 并拷贝到 C:\Windows\System32 下;
- **Linux**:将 libsigar-amd64-linux.so 或 libsigar-x86-linux.so 拷贝以下任意目录:`/usr/lib64` `/lib64` `/lib` `/usr/lib` ,如果不起作用,还需要通过 `sudo chmod 744` 命令修改 libsigar-amd64-linux.so 的文件权限。
- Windows 下配置:根据自己的操作系统版本选择 sigar-amd64-winnt.dll 或 sigar-x86-winnt.dll 拷贝到 C:\Windows\System32 中
- Linux 下配置:将 libsigar-amd64-linux.so 或 libsigar-x86-linux.so 拷贝到/usr/lib64 或/lib64 或/lib 或/usr/lib 目录下,如果不起作用,还需要 sudochmod 744 修改 libsigar-amd64-linux.so 文件权限
### 5.2 自定义端点
```java
@Endpoint(id = "customEndPoint")
@ -309,7 +301,7 @@ public class CustomEndPoint {
}
```
其中可用的方法注解由 http 操作决定:
可用的方法注解由 HTTP 操作所决定:
| operation | HTTP 方法 |
| ---------------- | -------- |
@ -317,13 +309,12 @@ public class CustomEndPoint {
| @WriteOperation | POST |
| @DeleteOperation | DELETE |
#### 5.2 访问自定义端点http://127.0.0.1:8080/actuator/customEndPoint
### 5.3 访问自定义端点
地址为http://127.0.0.1:8080/actuator/customEndPoint
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/actuator-customEndPoint.png"/> </div>
关于 Sigar 的 更多监控参数可以参考博客:[java 读取计算机 CPU、内存等信息Sigar 使用)](https://blog.csdn.net/wudiazu/article/details/73829324)
Sigar 下载包中也提供了各种参数的参考用例:
关于 Sigar 的更多监控参数可以参考博客:[java 读取计算机 CPU、内存等信息Sigar 使用)](https://blog.csdn.net/wudiazu/article/details/73829324) 或 Sigar 下载包中的用例:
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/sigar.png"/> </div>

View File

@ -1,37 +1,34 @@
# spring-boot 基础
# Spring-Boot 基础
## 目录<br/>
<a href="#一说明">一、说明</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#11-项目结构说明">1.1 项目结构说明</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#12-项目依赖">1.2 项目依赖</a><br/>
<a href="#二spring-boot-主启动类">二、spring boot 主启动类</a><br/>
<a href="#三开箱即用的web工程">三、开箱即用的web工程</a><br/>
<nav>
<a href="#一项目说明">一、项目说明</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#11-项目结构">1.1 项目结构</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#12-基本依赖">1.2 基本依赖</a><br/>
<a href="#二主启动类">二、主启动类</a><br/>
<a href="#三开箱即用">三、开箱即用</a><br/>
<a href="#四模板引擎">四、模板引擎</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#41-freemarker">4.1 freemarker</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#42-thymeleaf">4.2 thymeleaf</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#43-文档说明">4.3 文档说明</a><br/>
## 正文<br/>
</nav>
## 一、项目说明
### 1.1 项目结构
## 一、说明
#### 1.1 项目结构说明
1. 本项目搭建一个简单的 hello spring 的 web 工程,简单说明 spring-boot 的开箱即用的特性;
1. 本项目搭建一个简单的 hello spring 的 Web 工程,简单说明 Spring-Boot 的开箱即用的特性;
2. 模板引擎采用 freemaker 和 thymeleaf 作为示例,分别对应模板文件 makershow.ftl 和 leafShow.html
3. spring boot 2.x 默认是不支持 jsp 的,需要额外的配置,关于使用 jsp 的整合可以参考[spring-boot-jsp](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring-boot/spring-boot-jsp) 项目。
3. Spring Boot 2.x 默认不支持 Jsp ,需要额外的配置,关于使用 jsp 的整合可以参考 [spring-boot-jsp](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring-boot/spring-boot-jsp) 项目。
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-boot-base.png"/> </div>
### 1.2 基本依赖
#### 1.2 项目依赖
导入相关的 starter(启动器)
导入相关的 starter (启动器)
```xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
@ -90,20 +87,18 @@
</build>
</project>
```
1. spring boot 项目默认继承自 spring-boot-starter-parent而 spring-boot-starter-parent 继承自 spring-boot-dependencies, spring-boot-dependencies 中定义了关于 spring boot 依赖的各种 jar 包的版本,是 spring boot 的版本管理中心。
+ Spring Boot 项目默认继承自 spring-boot-starter-parent而 spring-boot-starter-parent 则继承自 spring-boot-dependenciesspring-boot-dependencies 中定义了关于 spring boot 依赖的各种 jar 包的版本,它是 Spring Boot 的版本管理中心。
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-boot-dependencies.png"/> </div>
2. 关于 spring boot 2.x 官方支持的所有 starter 可以参见官方文档 [Table 13.1. Spring Boot application starters](https://docs.spring.io/spring-boot/docs/2.1.1.RELEASE/reference/htmlsingle/#using-boot-starter)
+ 关于Spring Boot 2.x 官方支持的所有 starter 可以参见官方文档:[Table 13.1. Spring Boot application starters](https://docs.spring.io/spring-boot/docs/2.1.1.RELEASE/reference/htmlsingle/#using-boot-starter)
## 二、spring boot 主启动类
## 二、主启动类
如果采用 IDEA 或者 Spring Tool Suite (STS) 等开发工具创建的 spring boot 工程,会默认创建启动类,如果没有创建,需要手动创建启动类
如果采用 IDEA 或者 Spring Tool Suite (STS) 等开发工具创建的 Spring Boot 工程,会默认创建启动类,如果没有创建,需要手动创建启动类
```java
package com.heibaiying.springbootbase;
@ -122,7 +117,7 @@ public class SpringBootBaseApplication {
}
```
@SpringBootApplication 注解是一个复合注解,里面包含了@ComponentScan 注解,默认开启包扫描,扫描与主程序所在包及其子包,对于本工程而言 默认扫描 com.heibaiying.springbootbase
@SpringBootApplication 是一个复合注解,里面包含了 @ComponentScan 注解,即默认开启包扫描,扫描主程序所在包及其子包,对于本工程而言,默认扫描 com.heibaiying.springbootbase
```java
@Target(ElementType.TYPE)
@ -141,15 +136,11 @@ public @interface SpringBootApplication {
## 三、开箱即用的web工程
## 三、开箱即用
在 springbootBaseApplication.java 的同级目录创建 controller 文件夹,并在其中创建 RestfulController.java,启动项目访问 localhost:8080/restful/programmers 即可看到项目搭建成功
采用 Spring Boot 构建的 Web 项目具备开箱即用的特性,不需要做任何额外的配置就可以正常使用。这里我们在 springbootBaseApplication 的同级目录创建 controller 文件夹,并在其中创建 RestfulController 控制器,之后启动项目访问 `localhost:8080/restful/programmers` ,即可看到返回相关的信息
```java
/**
* @author : heibaiying
* @description : restful 控制器
*/
@RestController
@RequestMapping("restful")
public class RestfulController {
@ -164,19 +155,18 @@ public class RestfulController {
}
```
这里之所以能够开箱即用,是因为我们在项目中导入 spring-boot-starter-web 启动器,而@SpringBootApplication 复合注解中默认开启了@EnableAutoConfiguration 注解允许开启自动化配置spring 在检查导入 starter-web 的依赖后就会开启 web 的自动化配置。
Spring Boot 之所以能够开箱即用,是因为我们在项目中导入 spring-boot-starter-web 启动器,而 @SpringBootApplication 复合注解中默认开启了 @EnableAutoConfiguration ,即允许开启自动化配置。 Spring Boot 检查到存在 starter-web 依赖后就会开启 Web 相关的自动化配置。
## 四、模板引擎
这里我们在一个项目中同时导入了 freemaker 和 thymeleaf 的 starter虽然并不推荐但是在同一个项目中是可以混用这两种模板引擎的
这里我们在一个项目中同时导入了 freemaker 和 thymeleaf 的 starter虽然并不推荐但是在同一个项目中是可以混用这两种模板引擎的:
#### 4.1 freemarker
### 4.1 freemarker
```java
/**
* @author : heibaiying
* @description : 跳转渲染模板引擎 默认模板的存放位置为 classpath:templates
*/
@Controller
@ -212,11 +202,10 @@ public class FreeMarkerController {
</html>
```
#### 4.2 thymeleaf
### 4.2 thymeleaf
```java
/**
* @author : heibaiying
* @description : 跳转渲染模板引擎 默认模板的存放位置为 classpath:templates
*/
@Controller
@ -253,10 +242,9 @@ public class ThymeleafController {
</html>
```
#### 4.3 文档说明
### 4.3 文档说明
freemarker提供了完善的中文文档地址 http://freemarker.foofun.cn/
关于这两种模板引擎的语法可以参考其官方文档:
thymeleaf官方英文文档地址[thymeleaf 3.0.11RELEASE](https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.pdf)
注:我在本仓库中也上传了一份[thymeleaf 中文文档gangzi828(刘明刚 译)](https://github.com/heibaiying/spring-samples-for-all/tree/master/referenced%20documents),翻译的版本为 3.0.5RELEASE
- **freemarker**:提供了完善的中文文档,地址为: http://freemarker.foofun.cn/ 。
- **thymeleaf**:官方英文文档地址:[thymeleaf 3.0.11RELEASE](https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.pdf) 。我在本仓库中上传了一份 [thymeleaf 中文文档gangzi828(刘明刚 译)](https://github.com/heibaiying/spring-samples-for-all/tree/master/referenced%20documents),翻译的版本为 3.0.5RELEASE。

View File

@ -1,25 +1,21 @@
# spring boot data jpa
# Spring Boot Data JPA
## 目录<br/>
<a href="#一说明">一、说明</a><br/>
<nav>
<a href="#一项目说明">一、项目说明</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#11-项目结构">1.1 项目结构</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#12-项目主要依赖">1.2 项目主要依赖</a><br/>
<a href="#二data-jpa-的使用">二、data jpa 的使用</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#21-在applicationyml-中配置数据源">2.1 在application.yml 中配置数据源</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#22-新建查询接口">2.2 新建查询接口</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#23--测试">2.3 测试</a><br/>
## 正文<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#12-基本依赖">1.2 基本依赖</a><br/>
<a href="#二-使用-Data-JPA">二、 使用 Data JPA</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#21-数据源配置">2.1 数据源配置</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#22-查询接口">2.2 查询接口</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#23--单元测试">2.3 单元测试</a><br/>
</nav>
## 一、项目说明
## 一、说明
#### 1.1 项目结构
### 1.1 项目结构
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-boot-data-jpa.png"/> </div>
#### 1.2 项目主要依赖
### 1.2 基本依赖
```xml
<dependencies>
@ -43,9 +39,11 @@
</dependencies>
```
## 二、data jpa 的使用
## 二、 使用 Data JPA
#### 2.1 在application.yml 中配置数据源
### 2.1 数据源配置
在 application.yml 中配置数据源:
```yaml
spring:
@ -62,11 +60,10 @@ spring:
show-sql: true
```
#### 2.2 新建查询接口
### 2.2 查询接口
```java
/**
* @author : heibaiying
* @description : 查询接口继承自 CrudRepository,CrudRepository 默认定义了部分增删改查方法
*/
public interface ProgRepository extends CrudRepository<Programmer, Integer> {
@ -99,7 +96,7 @@ public interface ProgRepository extends CrudRepository<Programmer, Integer> {
```
关于查询方法遵循的命名规范和关键词见下表:
在使用 Spring Data JPA 时你甚至可以不用写 SQL 语句,只需要在定义方法名时满足 Spring 的规范即可Spring 会自动将这些方法按照其命名转换为对应的 SQL 语句,以下是其转换对照表:
| Keyword | Sample | JPQL snippet |
| ------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
@ -128,7 +125,7 @@ public interface ProgRepository extends CrudRepository<Programmer, Integer> {
| `False` | `findByActiveFalse()` | `… where x.active = false` |
| `IgnoreCase` | `findByFirstnameIgnoreCase` | `… where UPPER(x.firstame) = UPPER(?1)` |
#### 2.3 测试
### 2.3 单元测试
```java
@RunWith(SpringRunner.class)

View File

@ -1,37 +1,35 @@
# spring boot 整合 druid+mybatis
# Spring Boot 整合 Druid+Mybatis
## 目录<br/>
<a href="#一说明">一、说明</a><br/>
<nav>
<a href="#一项目说明">一、项目说明</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#11-项目结构">1.1 项目结构</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#12-项目主要依赖">1.2 项目主要依赖</a><br/>
<a href="#二整合-druid-+-mybatis">二、整合 druid + mybatis</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#21-在applicationyml-中配置数据源">2.1 在application.yml 中配置数据源</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#22--新建查询接口和controller">2.2 新建查询接口和controller</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#23-关于druid监控数据的外部化调用">2.3 关于druid监控数据的外部化调用</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#24-druid-控制台的使用默认访问地址-http//localhost8080/druid/loginhtml">2.4 druid 控制台的使用,默认访问地址 http://localhost:8080/druid/login.html</a><br/>
## 正文<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#12-基本依赖">1.2 基本依赖</a><br/>
<a href="#二整合-Druid-+-Mybatis">二、整合 Druid + Mybatis</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#21-配置数据源">2.1 配置数据源</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#22--整合查询">2.2 整合查询</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#23-监控数据">2.3 监控数据</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#24-Druid-控制台">2.4 Druid 控制台</a><br/>
</nav>
## 一、项目说明
### 1.1 项目结构
1. 项目涉及表的建表语句放置在 resources 的 sql 文件夹下;
## 一、说明
#### 1.1 项目结构
1. 项目查询用的表对应的建表语句放置在 resources 的 sql 文件夹下;
2. 为了使用 druid 控制台的功能,项目以 web 的方式构建。
2. 为了演示 Druid 控制台的功能,项目以 Web 的方式构建。
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-boot-druid-mybatis.png"/> </div>
### 1.2 基本依赖
#### 1.2 项目主要依赖
需要说明的是按照 spring 官方对于自定义的 starter 命名规范的推荐:
按照 Spring 官方对于自定义的 starter 命名规范的要求:
- 官方的 starter 命名spring-boot-starter-XXXX
- 其他第三方 starter 命名XXXX-spring-boot-starte
- 其他第三方 starter 命名XXXX-spring-boot-starter
所以 mybatis 的 starter 命名为 mybatis-spring-boot-starter如果有自定义 starter 需求,也需要按照此命名规则进行命名。
所以 Mybatis 的 starter 命名为 mybatis-spring-boot-starter如果有自定义 starter 需求,也需要按照此命名规则进行命名。
```xml
<dependency>
@ -53,7 +51,7 @@
</dependency>
```
spring boot 与 mybatis 版本的对应关系:
Spring Boot 与 Mybatis 版本的对应关系:
| MyBatis-Spring-Boot-Starter | [MyBatis-Spring](http://www.mybatis.org/spring/index.html#Requirements) | Spring Boot |
| --------------------------- | ------------------------------------------------------------ | ------------- |
@ -64,11 +62,11 @@ spring boot 与 mybatis 版本的对应关系:
## 二、整合 druid + mybatis
## 二、整合 Druid + Mybatis
#### 2.1 在application.yml 中配置数据源
### 2.1 配置数据源
本用例采用 druid 作为数据库连接池,虽然 druid 性能略逊于 Hikari但是提供了更为全面的监控管理可以按照实际需求选用 druid 或者 Hikari。关于 Hikari 数据源的配置可以参考[spring-boot-mybatis 项目](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring-boot/spring-boot-mybatis)
本用例采用 Druid 作为数据库连接池,虽然 Druid 性能略逊于 Hikari但提供了更为全面的监控管理可以按照实际需求选用 Druid 或者 Hikari。关于 Hikari 数据源的配置可以参考 [spring-boot-mybatis 项目](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring-boot/spring-boot-mybatis)
```yaml
spring:
@ -143,7 +141,9 @@ mybatis:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
```
#### 2.2 新建查询接口和controller
### 2.2 整合查询
新建查询接口和测试 Controller
```java
@Mapper
@ -181,15 +181,11 @@ public class ProgrammerController {
}
```
#### 2.3 关于druid监控数据的外部化调用
### 2.3 监控数据
在 Spring Boot 中可以通过 HTTP 接口将 Druid 的监控数据以 JSON 的形式暴露出去,可以用于健康检查等功能:
```java
/**
* @author : heibaiying
* @description :在 Spring Boot 中可以通过 HTTP 接口将 Druid 监控数据以 JSON 的形式暴露出去,
* 实际使用中你可以根据你的需要自由地对监控数据、暴露方式进行扩展。
*/
@RestController
public class DruidStatController {
@ -203,8 +199,8 @@ public class DruidStatController {
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/druid-status.png"/> </div>
### 2.4 Druid 控制台
#### 2.4 druid 控制台的使用,默认访问地址 http://localhost:8080/druid/login.html
默认访问地址为 http://localhost:8080/druid/login.html
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-boot-druid%20%E6%8E%A7%E5%88%B6%E5%8F%B0.png"/> </div>

View File

@ -1,39 +1,32 @@
# spring boot 整合 dubbo
# Spring Boot 整合 Dubbo
## 目录<br/>
<a href="#一-项目结构说明">一、 项目结构说明</a><br/>
<a href="#二关键依赖">二、关键依赖</a><br/>
<a href="#三公共模块boot-dubbo-common">三、公共模块boot-dubbo-common</a><br/>
<a href="#四-服务提供者boot-dubbo-provider">四、 服务提供者boot-dubbo-provider</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#41-提供方配置">4.1 提供方配置</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#42--使用注解Service暴露服务">4.2 使用注解@Service暴露服务</a><br/>
<a href="#五服务消费者boot-dubbo-consumer">五、服务消费者boot-dubbo-consumer</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#1消费方的配置">1.消费方的配置</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#2使用注解Reference引用远程服务">2.使用注解@Reference引用远程服务</a><br/>
<a href="#六项目构建的说明">六、项目构建的说明</a><br/>
<a href="#七关于dubbo新版本管理控制台的安装说明">七、关于dubbo新版本管理控制台的安装说明</a><br/>
## 正文<br/>
<nav>
<a href="#一-项目结构">一、 项目结构</a><br/>
<a href="#二基本依赖">二、基本依赖</a><br/>
<a href="#三公共模块">三、公共模块</a><br/>
<a href="#四服务提供者">四、服务提供者</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#41-提供者配置">4.1 提供者配置</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#42-暴露服务">4.2 暴露服务</a><br/>
<a href="#五服务消费者">五、服务消费者</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#51-消费者配置">5.1 消费者配置</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#52-调用服务">5.2 调用服务</a><br/>
<a href="#六项目构建">六、项目构建</a><br/>
<a href="#七Dubbo-控制台">七、Dubbo 控制台</a><br/>
</nav>
## 一、 项目结构
按照 Dubbo 文档推荐的服务最佳化实践的要求,建议将服务接口、服务模型、服务异常等均放在 API 包中,所以项目采用 Maven 多模块的构建方式,在 spring-boot-dubbo 下构建三个子模块:
## 一、 项目结构说明
1.1 按照 dubbo 文档推荐的服务最佳实践,建议将服务接口、服务模型、服务异常等均放在 API 包中,所以项目采用 maven 多模块的构建方式,在 spring-boot-dubbo 下构建三个子模块:
1. boot-dubbo-common 是公共模块,用于存放公共的接口和 bean,被 boot-dubbo-provider 和 boot-dubbo-consumer 在 pom.xml 中引用;
2. boot-dubbo-provider 是服务的提供者,提供商品的查询服务;
3. boot-dubbo-consumer 是服务的消费者,调用 provider 提供的查询服务。
1.2 本项目 dubbo 的搭建采用 zookeeper 作为注册中心, 关于 zookeeper 的安装和基本操作可以参见我的手记 [Zookeeper 基础命令与 Java 客户端](https://github.com/heibaiying/LearningNotes/blob/master/notes/%E4%B8%AD%E9%97%B4%E4%BB%B6/ZooKeeper/ZooKeeper%E9%9B%86%E7%BE%A4%E6%90%AD%E5%BB%BA%E4%B8%8EJava%E5%AE%A2%E6%88%B7%E7%AB%AF.md)
- **boot-dubbo-common** :是公共模块,用于存放公共的接口和 Java Bean被 boot-dubbo-provider 和 boot-dubbo-consumer 在 pom.xml 中引用;
- **boot-dubbo-provider** :服务的提供者,提供商品的查询服务;
- **boot-dubbo-consumer** :是服务的消费者,调用 provider 提供的查询服务。
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-boot-dubbo.png"/> </div>
## 二、基本依赖
## 二、关键依赖
在父工程的项目中统一导入依赖 dubbo 的 starter父工程的 pom.xml 如下
在父工程的项目中统一导入依赖 Dubbo 的 starter父工程的 pom.xml 如下:
```xml
<?xml version="1.0" encoding="UTF-8"?>
@ -102,18 +95,16 @@
## 三、公共模块boot-dubbo-common
## 三、公共模块
- api 下为公共的调用接口;
- bean 下为公共的实体类。
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/boot-dubbo-common.png"/> </div>
## 四、 服务提供者boot-dubbo-provider
## 四、服务提供者
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/boot-dubbo-provider.png"/> </div>
#### 4.1 提供方配置
### 4.1 提供者配置
```yaml
dubbo:
@ -126,23 +117,14 @@ dubbo:
protocol.name: dubbo
```
#### 4.2 使用注解@Service暴露服务
### 4.2 暴露服务
需要注意的是这里的@Service 注解不是 spring 的注解,而是 dubbo 的注解 com.alibaba.dubbo.config.annotation.Service
使用注解 @Service 暴露服务,需要注意的是这里的 @Service 不是 Spring 的注解,而是 Dubbo 的注解:
```java
package com.heibaiying.dubboprovider.service;
import com.alibaba.dubbo.config.annotation.Service;
import com.heibaiying.api.IProductService;
import com.heibaiying.bean.Product;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* @author : heibaiying
* @description : 产品提供接口实现类
*/
@Service(timeout = 5000)
@ -173,11 +155,10 @@ public class ProductService implements IProductService {
```
## 五、服务消费者boot-dubbo-consumer
## 五、服务消费者
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/boot-dubbo-consumer1.png"/> </div>
#### 1.消费方的配置
### 5.1 消费者配置
```yaml
dubbo:
@ -195,20 +176,12 @@ server:
port: 8090
```
#### 2.使用注解@Reference引用远程服务
### 5.2 调用服务
使用 @Reference 注解引用远程服务:
```java
package com.heibaiying.dubboconsumer.controller;
import com.alibaba.dubbo.config.annotation.Reference;
import com.heibaiying.api.IProductService;
import com.heibaiying.bean.Product;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.List;
@Controller
@RequestMapping("sell")
@ -234,108 +207,17 @@ public class SellController {
}
```
## 六、项目构建的说明
## 六、项目构建
因为在项目中consumer 和 provider 模块均依赖公共模块,所以在构建 consumer 和 provider 项目前需要将 common 模块安装到本地仓库,**依次**对**父工程**和**common 模块**执行:
因为在项目中consumer 和 provider 模块均依赖公共模块,所以在构建 consumer 和 provider 项目前需要将 common 模块安装到本地仓库,依次对父工程和 common 模块执行:
```shell
mvn install -Dmaven.test.skip = true
```
consumer 中 pom.xml 如下
## 七、Dubbo 控制台
```xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>spring-boot-dubbo</artifactId>
<groupId>com.heibaiying</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>boot-dubbo-consumer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>boot-dubbo-consumer</name>
<description>dubbo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<!--引入对公共模块的依赖-->
<dependencies>
<dependency>
<groupId>com.heibaiying</groupId>
<artifactId>boot-dubbo-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
```
provider 中 pom.xml 如下
```xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>spring-boot-dubbo</artifactId>
<groupId>com.heibaiying</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>boot-dubbo-provider</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>boot-dubbo-provider</name>
<description>dubbo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<!--引入对公共模块的依赖-->
<dependencies>
<dependency>
<groupId>com.heibaiying</groupId>
<artifactId>boot-dubbo-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
```
## 七、关于dubbo新版本管理控制台的安装说明
安装:
Dubbo 新版本管理控制台的安装步骤如下:
```sh
git clone https://github.com/apache/incubator-dubbo-ops.git /var/tmp/dubbo-ops
@ -345,21 +227,22 @@ mvn clean package
配置:
```sh
配置文件为:
```properties
# 配置文件为:
dubbo-admin-backend/src/main/resources/application.properties
主要的配置有 默认的配置就是 127.0.0.1:2181
# 可以在其中修改zookeeper的地址
dubbo.registry.address=zookeeper://127.0.0.1:2181
```
启动:
启动
```sh
mvn --projects dubbo-admin-backend spring-boot:run
```
访问:
访问
```
```shell
http://127.0.0.1:8080
```

View File

@ -1,25 +1,22 @@
# spring boot 内置容器 整合 jsp
# Spring Boot 整合 JSP
<nav>
<a href="#一项目说明">一、项目说明</a><br/>
<a href="#二整合-JSP">二、整合 JSP</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#21-基本依赖">2.1 基本依赖</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#22-配置视图">2.2 配置视图</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#23--整合测试">2.3 整合测试</a><br/>
</nav>
## 目录<br/>
<a href="#一说明">一、说明</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#11-项目结构">1.1 项目结构</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#12-项目主要依赖">1.2 项目主要依赖</a><br/>
<a href="#二整合-jsp">二、整合 jsp</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#21-导入整合的依赖">2.1 导入整合的依赖</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#22-在applicationyml-中指定访问视图文件的前缀和后缀">2.2 在application.yml 中指定访问视图文件的前缀和后缀 </a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#23--新建controller和showjsp-测试整合是否成功">2.3 新建controller和show.jsp 测试整合是否成功</a><br/>
## 正文<br/>
## 一、说明
#### 1.1 项目结构
## 一、项目说明
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-boot-jsp.png"/> </div>
#### 1.2 项目主要依赖
## 二、整合 JSP
### 2.1 基本依赖
导入整合所需的依赖:
```xml
<!--整合 jsp 依赖包-->
@ -35,25 +32,9 @@
</dependency>
```
## 二、整合 jsp
### 2.2 配置视图
#### 2.1 导入整合的依赖
```xml
<!--整合 jsp 依赖包-->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<!--jsp jstl 标签支持-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
```
#### 2.2 在application.yml 中指定访问视图文件的前缀和后缀
在 application.yml 中指定访问视图文件的前缀和后缀
```yml
spring:
@ -63,7 +44,9 @@ spring:
suffix: .jsp
```
#### 2.3 新建controller和show.jsp 测试整合是否成功
### 2.3 整合测试
新建 controller 和 show.jsp 测试整合是否成功:
```java
@Controller

View File

@ -1,89 +1,35 @@
# spring boot 整合 kafka
## 目录<br/>
<a href="#一kafka的相关概念">一、kafka的相关概念</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#1主题和分区">1.主题和分区</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#2分区复制">2.分区复制</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#3-生产者">3. 生产者</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#4-消费者">4. 消费者</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#5broker和集群">5.broker和集群</a><br/>
<a href="#二项目说明">二、项目说明</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#11-项目结构说明">1.1 项目结构说明</a><br/>
# Spring Boot 整合 Kafka
<nav>
<a href="#一项目说明">一、项目说明</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#11-项目结构">1.1 项目结构</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#12-主要依赖">1.2 主要依赖</a><br/>
<a href="#二-整合-kafka">二、 整合 kafka</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#21-kafka基本配置">2.1 kafka基本配置</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#22-KafkaTemplate实现消息发送">2.2 KafkaTemplate实现消息发送</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#23--KafkaListener注解实现消息监听">2.3 @KafkaListener注解实现消息监听</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#24-测试整合结果">2.4 测试整合结果</a><br/>
<a href="#三关于多消费者组测试">三、关于多消费者组测试</a><br/>
<a href="#二-整合-Kafka">二、 整合 Kafka</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#21-基本配置">2.1 基本配置</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#22-消息发送">2.2 消息发送</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#23--消息监听">2.3 消息监听</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#24-整合测试">2.4 整合测试</a><br/>
<a href="#三多消费者组测试">三、多消费者组测试</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#31--创建多分区主题">3.1 创建多分区主题</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#32-多消费者组对同一主题的监听">3.2 多消费者组对同一主题的监听</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#32-发送消息时候指定主题的具体分区">3.2 发送消息时候指定主题的具体分区</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#32-消息监听">3.2 消息监听</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#33-消息发送">3.3 消息发送</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#34-测试结果">3.4 测试结果</a><br/>
<a href="#四序列化与反序列化">四、序列化与反序列化</a><br/>
## 正文<br/>
</nav>
## 一、项目说明
### 1.1 项目结构
本项目提供 Kafka 发送简单消息、对象消息、和多消费者组消费消息三种情况下的 sample
## 一、kafka的相关概念
### 1.主题和分区
kafka 的消息通过主题进行分类。一个主题可以被分为若干个分区一个分区就是一个提交日志。消息以追加的方式写入分区然后以先入先出的顺序读取。kafka 通过分区来实现数据的冗余和伸缩性,分区可以分布在不同的服务器上,也就是说一个主题可以横跨多个服务器,以此来提供比单个服务器更强大的性能(类比 HDFS 分布式文件系统)。
注意:由于一个主题包含多个分区,因此无法在整个主题范围内保证消息的顺序性,**但可以保证消息在单个分区内的顺序性**。
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/kafka主题和分区.png"/> </div>
### 2.分区复制
每个主题被分为若干个分区,每个分区有多个副本。那些副本被保存在 broker 上,每个 broker 可以保存成百上千个属于不同主题和分区的副本。副本有以下两种类型
- 首领副本 每个分区都有一个首领副本 。 为了保证一致性,所有生产者请求和消费者请求都会经过这个副本。
- 跟随者副本 首领以外的副本都是跟随者副本。跟随者副本不处理来自客户端的请求,它们唯一的任务就是从首领那里复制消息,保持与首领一致的状态。如果首领发生崩渍,其中的一个跟随者会被提升为新首领。
### 3. 生产者
- 默认情况下生产者在把消息均衡地分布到在主题的所有分区上,而并不关心特定消息会被写到那个分区;
- 如果指定消息键,则通过对消息键的散列来实现分区;
- 也可以通过消息键和分区器来实现把消息直接写到指定的分区,这个需要自定义分区器,需要实现 Partitioner 接口,并重写其中的 partition 方法。
### 4. 消费者
消费者是**消费者群组**的一部分。也就是说,会有一个或者多个消费者共同读取一个主题,群组保证每个分区只能被一个消费者使用。
**一个分区只能被同一个消费者群组里面的一个消费者读取,但可以被不同消费者群组里面的多个消费者读取。多个消费者群组可以共同读取同一个主题,彼此之间互不影响**。
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/kafka消费者.png"/> </div>
### 5.broker和集群
一个独立的 kafka 服务器被称为 broker。broker 接收来自生产者的消息为消息设置偏移量并提交消息到磁盘保存。broker 为消费者提供服务,对读取分区的请求做出响应,返回已经提交到磁盘的消息。
broker 是集群的组成部分。每一个集群都有一个 broker 同时充当了集群控制器的角色(自动从集群的活跃成员中选举出来)。控制器负责管理工作,包括将分区分配给 broker 和监控 broker。**在集群中,一个分区从属一个 broker,该 broker 被称为分区的首领**。一个分区可以分配给多个 broker,这个时候会发生分区复制。这种复制机制为分区提供了消息冗余,如果有一个 broker 失效,其他 broker 可以接管领导权。
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/kafka集群复制.png"/> </div>
更多 kafka 的说明可以参考我的个人笔记:[《Kafka 权威指南》读书笔记](https://github.com/heibaiying/LearningNotes/blob/master/notes/%E4%B8%AD%E9%97%B4%E4%BB%B6/Kafka/%E3%80%8AKafka%E6%9D%83%E5%A8%81%E6%8C%87%E5%8D%97%E3%80%8B%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0.md#53-%E5%A4%8D%E5%88%B6)
## 二、项目说明
#### 1.1 项目结构说明
本项目提供 kafka 发送简单消息、对象消息、和多消费者组消费消息三种情况下的 sample。
1. kafkaSimpleConsumer 用于普通消息的监听;
2. kafkaBeanConsumer 用于对象消息监听;
3. kafkaGroupConsumer 用于多消费者组和多消费者对主题分区消息监听的情况。
- **kafkaSimpleConsumer** :用于普通消息的监听;
- **kafkaBeanConsumer** :用于对象消息的监听;
- **kafkaGroupConsumer** :用于多消费者组和多消费者对主题分区消息监听的情况。
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-boot-kafka.png"/> </div>
#### 1.2 主要依赖
### 1.2 主要依赖
```xml
<dependency>
@ -99,9 +45,9 @@ broker 是集群的组成部分。每一个集群都有一个 broker 同时充
## 二、 整合 kafka
## 二、 整合 Kafka
#### 2.1 kafka基本配置
### 2.1 基本配置
```yaml
spring:
@ -142,9 +88,7 @@ spring:
```
这里需要说明的是:
在 spring boot 2.X 版本 auto-commit-interval自动提交的时间间隔采用的是值的类型为 Duration Duration 是 jdk 1.8 版本之后引入的类,在其源码中我们可以看到对于其字符串的表达需要符合一定的规范,即数字 + 单位,如下的写法 1s 1.5s 0s 0.001S 1h 2d 在 yaml 中都是有效的。如果传入无效的字符串,则 spring boot 在启动阶段解析配置文件的时候就会抛出异常。
在 Spring Boot 2.x 后 auto-commit-interval自动提交的时间间隔采用的是值的类型为 Duration Duration 是 JDK 1.8 后引入的类,在其源码中我们可以看到对于其字符串的表达需要符合一定的规范,即数字 + 单位,如下的写法 1s 1.5s 0s 0.001S 1h 2d 都是有效的。如果传入无效的字符串,则 Spring Boot 在启动阶段解析配置文件时就会抛出异常。
```java
public final class Duration
@ -162,7 +106,9 @@ public final class Duration
}
```
#### 2.2 KafkaTemplate实现消息发送
### 2.2 消息发送
使用 KafkaTemplate 来发送消息:
```java
@Component
@ -197,7 +143,9 @@ public class KafKaCustomrProducer {
```
#### 2.3 @KafkaListener注解实现消息的监听
### 2.3 消息监听
使用 @KafkaListener 注解来实现消息的监听:
```java
@Component
@ -216,7 +164,7 @@ public class KafkaSimpleConsumer {
}
```
#### 2.4 测试整合结果
### 2.4 整合测试
```java
@Slf4j
@ -240,15 +188,11 @@ public class SendMsgController {
## 三、关于多消费者组测试
## 三、多消费者组测试
#### 3.1 创建多分区主题
### 3.1 创建多分区主题
```java
/**
* @author : heibaiying
* @description : kafka 配置类
*/
@Configuration
public class KafkaConfig {
@ -257,24 +201,19 @@ public class KafkaConfig {
// 指定主题名称,分区数量,和复制因子
return new NewTopic(Topic.GROUP, 10, (short) 2);
}
}
```
#### 3.2 多消费者组对同一主题的监听
### 3.2 消息监听
1. 消费者 1-1 监听主题的 0、1 分区
2. 消费者 1-2 监听主题的 2、3 分区
3. 消费者 1-3 监听主题的 0、1 分区
4. 消费者 2-1 监听主题的所有分区
创建多消费者,并监听同一主题的不同分区:
- 消费者 1-1 监听主题的 0、1 分区
- 消费者 1-2 监听主题的 2、3 分区
- 消费者 1-3 监听主题的 0、1 分区
- 消费者 2-1 监听主题的所有分区
```java
/**
* @author : heibaiying
* @description : kafka 消费者组
* <p>
* 多个消费者群组可以共同读取同一个主题,彼此之间互不影响。
*/
@Component
@Slf4j
public class KafkaGroupConsumer {
@ -312,12 +251,11 @@ public class KafkaGroupConsumer {
```
#### 3.2 发送消息时候指定主题的具体分区
### 3.3 消息发送
发送消息时候指定主题的具体分区:
```java
/***
* 多消费者组、组中多消费者对同一主题的消费情况
*/
@GetMapping("sendGroup")
public void sendGroup() {
for (int i = 0; i < 4; i++) {
@ -362,16 +300,16 @@ consumer1-2 收到消息:hello group 3
consumer1-2 收到消息:hello group 2
```
#### 3.4 测试结果
### 3.4 测试结果
1. 和 kafka 原本的机制一样,多消费者组之间对于同一个主题的消费彼此之间互不影响;
2. 和 kafka 原本机制不一样的是,这里我们消费者 1-1 和消费 1-3 共同属于同一个消费者组,并且监听同样的分区,按照原本 kafka 的机制,群组保证每个分区只能被同一个消费者组的一个消费者使用,但是按照 spring 的声明方式实现的消息监听,这里被两个消费者都监听到了。
- 和 Kafka 原本的机制一样,多消费者组之间对于同一个主题的消费彼此之间互不影响;
- 和 Kafka 原本机制不一样的是,这里我们消费者 1-1 和消费 1-3 共同属于同一个消费者组,并且监听同样的分区,按照 Kafka 原本的机制,群组保证每个分区只能被同一个消费者组的一个消费者使用,但是按照 Spring 的方式实现消息监听后,被两个消费者都监听到了。
## 四、序列化与反序列化
用例采用的是第三方 fastjson 将实体类序列化为 json 后发送。实现如下:
用例采用的是第三方 fastjson 将实体类序列化为 Json 后发送。实现如下:
```java
/***

View File

@ -1,34 +1,32 @@
# spring boot 整合 mecached
# Spring Boot 整合 Memcached
## 目录<br/>
<a href="#一说明">一、说明</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#11--XMemcached客户端说明">1.1 XMemcached客户端说明</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#12-项目结构说明">1.2 项目结构说明</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#13-主要依赖">1.3 主要依赖</a><br/>
<a href="#二spring-boot-整合-memcached">二、spring boot 整合 memcached</a><br/>
<nav>
<a href="#一项目说明">一、项目说明</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#11--XMemcached">1.1 XMemcached</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#12-项目结构">1.2 项目结构</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#13-基本依赖">1.3 基本依赖</a><br/>
<a href="#二整合-Memcached">二、整合 Memcached</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#21-单机配置">2.1 单机配置</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#22-集群配置">2.2 集群配置</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#23-存储基本类型测试用例">2.3 存储基本类型测试用例</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#25-存储实体对象测试用例">2.5 存储实体对象测试用例</a><br/>
<a href="#附memcached-基本命令">memcached 基本命令</a><br/>
## 正文<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#23-存储基本类型">2.3 存储基本类型</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#24-存储实体对象">2.4 存储实体对象</a><br/>
<a href="#附Memcached-基本命令">Memcached 基本命令</a><br/>
</nav>
## 一、项目说明
### 1.1 XMemcached
Spring 官方并没有提供关于 Memcached 的 starter所以我们还是采用 XMemcached 作为客户端进行整合。XMemcached 是基于 Java NIO 的 Memcached 高性能客户端,支持完整的 Memcached 协议,支持客户端分布并且提供了一致性哈希 (consistent hash) 算法的实现。
## 一、说明
### 1.2 项目结构
### 1.1 XMemcached客户端说明
spring boot 官方并没有提供关于 memcached 的 starter所以我们这里还是采用 XMemcached 作为客户端进行整合。 XMemcached 是基于 java nio 的 memcached 高性能客户端,支持完整的 memcached 协议,支持客户端分布并且提供了一致性哈希 (consistent hash) 算法的实现。
### 1.2 项目结构说明
memcached 的整合配置位于 config 文件夹下。
Memcached 的整合配置位于 config 文件夹下:
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-boot-memcached.png"/> </div>
### 1.3 主要依赖
### 1.3 基本依赖
```xml
<!--memcached java 客户端-->
@ -41,9 +39,9 @@ memcached 的整合配置位于 config 文件夹下。
## 二、spring boot 整合 memcached
## 二、整合 Memcached
#### 2.1 单机配置
### 2.1 单机配置
```java
@Bean
@ -59,7 +57,7 @@ try {
}
```
#### 2.2 集群配置
### 2.2 集群配置
```java
@Bean
@ -89,15 +87,9 @@ public MemcachedClient memcachedClientForCluster() {
}
```
#### 2.3 存储基本类型测试用例
xmemcached 单机版本和集群版本注入的实例是相同的。
### 2.3 存储基本类型
```java
/**
* @author : heibaiying
* @description : Memcached 操作基本对象
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class MemSamples {
@ -117,13 +109,9 @@ public class MemSamples {
}
```
#### 2.5 存储实体对象测试用例
### 2.4 存储实体对象
```java
/**
* @author : heibaiying
* @description :Memcached 序列化与反序列化
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class MemObjectSamples {
@ -146,7 +134,7 @@ public class MemObjectSamples {
## 附:memcached 基本命令
## 附:Memcached 基本命令
| 命令 | 格式 | 说明 |
| --------------- | -------------------------------------------------- | ------------------------------------- |

View File

@ -1,29 +1,25 @@
# spring boot 整合 mongodb
# Spring Boot 整合 MongoDB
## 目录<br/>
<a href="#一说明">一、说明</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#11-用例结构">1.1 用例结构</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#12-项目主要依赖">1.2 项目主要依赖</a><br/>
<a href="#二整合-mongodb">二、整合 mongodb</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#21-在applicationyml-中配置mongodb数据源">2.1 在application.yml 中配置mongodb数据源</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#22--基于MongoTemplate实现对mongodb的操作">2.2 基于MongoTemplate实现对mongodb的操作</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#23-使用-data-jpa-方式操作mongodb-推荐使用">2.3 使用 data jpa 方式操作mongodb (推荐使用)</a><br/>
## 正文<br/>
<nav>
<a href="#一项目说明">一、项目说明</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#11-项目结构">1.1 项目结构</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#12-基本依赖">1.2 基本依赖</a><br/>
<a href="#二整合-MongoDB">二、整合 MongoDB </a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#21-配置数据源">2.1 配置数据源</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#22--MongoTemplate">2.2 MongoTemplate</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#23-Spring-Data-JPA">2.3 Spring Data JPA</a><br/>
</nav>
## 一、项目说明
### 1.1 项目结构
## 一、说明
#### 1.1 用例结构
1. 本用例提供 mongdb 的简单整合用例;
2. 提供用 MongoTemplate 的方式操作 mongdb见测试用例 MongoOriginalTests.java
3. 提供基于 spring data jpa 的方式操作 mongodb(推荐),见测试用例 MongoJPATests.java
- 本用例提供 MongoDB 的简单整合用例;
- 提供基于 MongoTemplate 的方式操作 MongoDB见测试用例 MongoOriginalTests
- 提供基于 Spring Data JPA 的方式操作 MongoDB (推荐),见测试用例 MongoJPATests。
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-boot-mongodb.png"/> </div>
#### 1.2 项目主要依赖
### 1.2 基本依赖
```xml
<dependency>
@ -34,9 +30,9 @@
## 二、整合 mongodb
## 二、整合 MongoDB
#### 2.1 在application.yml 中配置mongodb数据源
### 2.1 配置数据源
```yaml
spring:
@ -46,7 +42,9 @@ spring:
uri: mongodb://192.168.0.108:27017
```
#### 2.2 基于MongoTemplate实现对mongodb的操作
### 2.2 MongoTemplate
基于 MongoTemplate 实现对 MongoDB 的操作:
```java
@RunWith(SpringRunner.class)
@ -96,9 +94,9 @@ public class MongoOriginalTests {
}
```
#### 2.3 使用 data jpa 方式操作mongodb (推荐使用)
### 2.3 Spring Data JPA
1.新建查询结构,查询方法按照支持的关键字命名
使用 Spring Data JPA 时,只需要将查询方法按照 Spring 的规范命令即可:
```java
public interface ProgrammerRepository extends MongoRepository<Programmer, String> {
@ -112,7 +110,7 @@ public interface ProgrammerRepository extends MongoRepository<Programmer, String
}
```
2.测试
单元测试:
```java
@RunWith(SpringRunner.class)
@ -160,7 +158,7 @@ public class MongoJPATests {
}
```
查询方法支持的关键字如下,更多命名规范可以参见 Spring Data MongoDB 官方文档[Query Methods](https://docs.spring.io/spring-data/mongodb/docs/2.1.3.RELEASE/reference/html/#mongodb.repositories.queries)
查询方法所有支持的关键字如下,更多命名规范可以参见 Spring Data MongoDB 官方文档 [Query Methods](https://docs.spring.io/spring-data/mongodb/docs/2.1.3.RELEASE/reference/html/#mongodb.repositories.queries)
| Keyword | Sample | Logical result |
| ------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |

View File

@ -1,40 +1,36 @@
# spring boot 整合 mybatis
# Spring Boot 整合 Mybatis
## 目录<br/>
<a href="#一说明">一、说明</a><br/>
<nav>
<a href="#一项目说明">一、项目说明</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#11-项目结构">1.1 项目结构</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#12-项目主要依赖">1.2 项目主要依赖</a><br/>
<a href="#二整合-mybatis">二、整合 mybatis</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#21-在applicationyml-中配置数据源">2.1 在application.yml 中配置数据源</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#22--xml方式的sql语句">2.2 xml方式的sql语句</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#23-注解方式的sql语句">2.3 注解方式的sql语句</a><br/>
## 正文<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#12-主要依赖">1.2 主要依赖</a><br/>
<a href="#二整合-Mybatis">二、整合 Mybatis</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#21-配置数据源">2.1 配置数据源</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#22--XML-方式">2.2 XML 方式</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#23-注解方式">2.3 注解方式</a><br/>
</nav>
## 一、项目说明
### 1.1 项目结构
- 项目涉及表的建表语句放置在 resources 的 sql 文件夹下;
## 一、说明
- 关于 Mybatis SQL 的写法提供两种方式:
#### 1.1 项目结构
**xml 写法**:对应的类为 ProgrammerMapper.java 和 programmerMapper.xml用 MybatisXmlTest 进行测试;
1. 项目查询用的表对应的建表语句放置在 resources 的 sql 文件夹下;
2. 关于 mybatis sql 的写法提供两种方式:
xml 写法:对应的类为 ProgrammerMapper.java 和 programmerMapper.xml用 MybatisXmlTest 进行测试;
注解写法:对应的类为 Programmer.java ,用 MybatisAnnotationTest 进行测试。
**注解写法**:对应的类为 Programmer.java ,用 MybatisAnnotationTest 进行测试。
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-boot-mybatis.png"/> </div>
### 1.2 主要依赖
#### 1.2 项目主要依赖
需要说明的是按照 spring 官方对应自定义的 starter 命名规范的推荐:
按照 Spring 官方对于自定义的 starter 命名规范的要求:
- 官方的 starter 命名spring-boot-starter-XXXX
- 其他第三方 starter 命名XXXX-spring-boot-starte
所以 mybatis 的 starter 命名为 mybatis-spring-boot-starter如果有自定义 starter 需求,也需要按照此命名规则进行命名。
所以 Mybatis 的 starter 命名为 mybatis-spring-boot-starter如果有自定义 starter 需求,也需要按照此命名规则进行命名。
```xml
<!--spring 1.5 x 以上版本对应 mybatis 1.3.x (1.3.1)
@ -71,11 +67,11 @@ spring boot 与 mybatis 版本的对应关系:
| **1.1.x (1.1.1)** | 1.3 or higher | 1.3 or higher |
| **1.0.x (1.0.2)** | 1.2 or higher | 1.3 or higher |
## 二、整合 mybatis
## 二、整合 Mybatis
#### 2.1 在application.yml 中配置数据源
### 2.1 配置数据源
spring boot 2.x 版本默认采用 Hikari 作为数据库连接池Hikari 是目前 java 平台性能最好的连接池,性能好于 druid。
Spring Boot 2.x 版本默认采用 Hikari 作为数据库连接池Hikari 是目前 Java 平台性能最好的连接池,性能好于 druid
```yaml
spring:
@ -118,9 +114,9 @@ mybatis:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
```
#### 2.2 xml方式的sql语句
### 2.2 XML 方式
新建 ProgrammerMapper.java 和 programmerMapper.xml及其测试类
新建 ProgrammerMapper.java 和 programmerMapper.xml及其测试类
```java
@Mapper
@ -161,12 +157,9 @@ public interface ProgrammerMapper {
</mapper>
```
测试类
测试类
```java
/***
* @description: xml Sql 测试类
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class MybatisXmlTest {
@ -200,7 +193,7 @@ public class MybatisXmlTest {
}
```
#### 2.3 注解方式的sql语句
### 2.3 注解方式
```java
@Mapper
@ -220,12 +213,9 @@ public interface ProgrammerDao {
}
```
测试类
测试类
```java
/***
* @description: 注解 Sql 测试类
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class MybatisAnnotationTest {

View File

@ -1,39 +1,32 @@
# spring boot 整合 rabbitmq
## 目录<br/>
<a href="#一-项目结构说明">一、 项目结构说明</a><br/>
<a href="#二关键依赖">二、关键依赖</a><br/>
<a href="#三公共模块rabbitmq-common">三、公共模块rabbitmq-common</a><br/>
<a href="#四服务消费者rabbitmq-consumer">四、服务消费者rabbitmq-consumer</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#41-消息消费者配置">4.1 消息消费者配置</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#42-使用注解RabbitListener和RabbitHandler创建消息监听者">4.2 使用注解@RabbitListener和@RabbitHandler创建消息监听者</a><br/>
<a href="#五-消息生产者rabbitmq-producer">五、 消息生产者rabbitmq-producer</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#51-消息生产者配置">5.1 消息生产者配置</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#52--创建消息生产者">5.2 创建消息生产者</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#53--以单元测试的方式发送消息">5.3 以单元测试的方式发送消息</a><br/>
<a href="#六项目构建的说明">六、项目构建的说明</a><br/>
## 正文<br/>
# Spring Boot 整合 RabbitMQ
<nav>
<a href="#一-项目结构">一、 项目结构</a><br/>
<a href="#二主要依赖">二、主要依赖</a><br/>
<a href="#三公共模块">三、公共模块</a><br/>
<a href="#四消息消费者">四、消息消费者</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#41-消费者配置">4.1 消费者配置</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#42-创建监听者">4.2 创建监听者</a><br/>
<a href="#五消息生产者">五、消息生产者</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#51-生产者配置">5.1 生产者配置</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#52--创建生产者">5.2 创建生产者</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#53--单元测试">5.3 单元测试</a><br/>
<a href="#六项目构建">六、项目构建</a><br/>
</nav>
## 一、 项目结构
## 一、 项目结构说明
之前关于 Spring 整合 RabbitMQ 我们采用的是单项目的方式,为了使得用例更具有实际意义,这里采用 Maven 多模块的构建方式,在 spring-boot-rabbitmq 下构建三个子模块:
1.1 之前关于 spring 整合 rabbitmq 我们采用的是单项目的方式,为了使得用例更具有实际意义,这里采用 maven 多模块的构建方式,在 spring-boot-rabbitmq 下构建三个子模块:
1. rabbitmq-common 是公共模块,用于存放公共的接口、配置和 bean,被 rabbitmq-producer 和 rabbitmq-consumer 在 pom.xml 中引用;
2. rabbitmq-producer 是消息的生产者模块;
3. rabbitmq-consumer 是消息的消费者模块。
1.2 关于 rabbitmq 安装、交换机、队列、死信队列等基本概念可以参考我的手记[《RabbitMQ 实战指南》读书笔记](https://github.com/heibaiying/LearningNotes/blob/master/notes/%E4%B8%AD%E9%97%B4%E4%BB%B6/RabbitMQ/%E3%80%8ARabbitMQ%E5%AE%9E%E6%88%98%E6%8C%87%E5%8D%97%E3%80%8B%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0.md),里面有详细的配图说明。
- **rabbitmq-common** :公共模块,用于存放公共的接口、配置和 Java Bean被 rabbitmq-producer 和 rabbitmq-consumer 在 pom.xml 中引用;
- **rabbitmq-producer** :消息的生产者模块;
- **rabbitmq-consumer** :是消息的消费者模块。
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-boot-rabbitmq.png"/> </div>
## 二、主要依赖
## 二、关键依赖
在父工程的项目中统一导入依赖 rabbitmq 的 starter(spring-boot-starter-amqp),父工程的 pom.xml 如下
在父工程的项目中统一导入依赖 RabbitMQ 的 starter父工程的 pom.xml 如下:
```xml
<?xml version="1.0" encoding="UTF-8"?>
@ -92,20 +85,13 @@
## 三、公共模块rabbitmq-common
## 三、公共模块
- bean 下为公共的实体类。
- constant 下为公共配置,用静态常量引用。这里我使用静态常量是为了方便引用,实际中也可以按照情况,抽取为公共配置文件)
- constant 下为公共配置,用静态常量进行引用。这里我使用静态常量是为了方便引用,实际中也可以按照情况,抽取为公共的配置文件。
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/rabbitmq-common.png"/> </div>
```java
package com.heibaiying.constant;
/**
* @author : heibaiying
* @description : rabbit 公用配置信息
*/
public class RabbitInfo {
// queue 配置
@ -124,11 +110,10 @@ public class RabbitInfo {
## 四、服务消费者rabbitmq-consumer
## 四、消息消费者
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/rabbitmq-consumer.png"/> </div>
#### 4.1 消息消费者配置
### 4.1 消费者配置
```yaml
spring:
@ -149,17 +134,11 @@ spring:
max-concurrency: 50
```
#### 4.2 使用注解@RabbitListener和@RabbitHandler创建消息监听者
### 4.2 创建监听者
1. 使用注解创建的交换机、队列、和绑定关系会在项目初始化的时候自动创建,但是不会重复创建;
2. 这里我们创建两个消息监听器,分别演示消息是基本类型和消息是对象时的配置区别。
使用注解 @RabbitListener@RabbitHandler 创建消息的监听者,使用注解创建的交换机、队列、和绑定关系会在项目初始化的时候自动创建,但是不会重复创建。这里我们创建两个消息监听器,分别演示消息是基本类型和消息是对象时区别:
```java
/**
* @author : heibaiying
* @description : 消息是对象的消费者
*/
@Component
@Slf4j
public class RabbitmqBeanConsumer {
@ -204,11 +183,10 @@ public class RabbitmqConsumer {
## 五、 消息生产者rabbitmq-producer
## 五、消息生产者
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/rabbitmq-producer.png"/> </div>
#### 5.1 消息生产者配置
### 5.1 生产者配置
```yaml
spring:
@ -230,13 +208,9 @@ server:
port: 8090
```
#### 5.2 创建消息生产者
### 5.2 创建生产者
```java
/**
* @author : heibaiying
* @description : 消息生产者
*/
@Component
@Slf4j
public class RabbitmqProducer {
@ -272,7 +246,9 @@ public class RabbitmqProducer {
}
```
#### 5.3 以单元测试的方式发送消息
### 5.3 单元测试
以单元测试的方式发送消息:
```java
@RunWith(SpringRunner.class)
@ -308,100 +284,11 @@ public class RabbitmqProducerTests {
}
```
## 六、项目构建
## 六、项目构建的说明
因为在项目中consumer 和 producer 模块均依赖公共模块,所以在构建 consumer 和 producer 项目前需要将 common 模块安装到本地仓库,**依次**对**父工程**和**common 模块**执行:
因为在项目中consumer 和 producer 模块均依赖公共模块,所以在构建 consumer 和 producer 项目前需要将 common 模块安装到本地仓库,依次对父工程和 common 模块执行:
```shell
mvn install -Dmaven.test.skip = true
```
consumer 中 pom.xml 如下
```xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.heibaiying</groupId>
<artifactId>spring-boot-rabbitmq</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>rabbitmq-consumer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>rabbitmq-consumer</name>
<description>RabbitMQ consumer project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>com.heibaiying</groupId>
<artifactId>rabbitmq-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
```
producer 中 pom.xml 如下
```xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.heibaiying</groupId>
<artifactId>spring-boot-rabbitmq</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>rabbitmq-producer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>rabbitmq-producer</name>
<description>RabbitMQ producer project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>com.heibaiying</groupId>
<artifactId>rabbitmq-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
```

View File

@ -1,50 +1,25 @@
# spring boot 整合 redis
# Spring Boot 整合 Redis
## 目录<br/>
<a href="#一说明">一、说明</a><br/>
<nav>
<a href="#一项目说明">一、项目说明</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#11-项目结构">1.1 项目结构</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#12-项目主要依赖">1.2 项目主要依赖</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#12-基本依赖">1.2 基本依赖</a><br/>
<a href="#二整合-Redis">二、整合 Redis</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#21-在applicationyml-中配置redis数据源">2.1 在application.yml 中配置redis数据源</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#22--封装redis基本操作">2.2 封装redis基本操作</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#23-redisTemplate-序列化为json格式与反序列化">2.3 redisTemplate 序列化为json格式与反序列化</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#24-测试">2.4 测试</a><br/>
<a href="#附Redis的数据结构和操作命令">Redis的数据结构和操作命令</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#11-预备">1.1 预备</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#111-全局命令">1.1.1 全局命令</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#112-数据结构和内部编码">1.1.2 数据结构和内部编码</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#113-单线程架构">1.1.3 单线程架构</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#12-字符串">1.2 字符串</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#13-哈希">1.3 哈希</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#14-列表">1.4 列表</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#15-集合">1.5 集合</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#16-有序集合">1.6 有序集合</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#17-键管理">1.7 键管理</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#171-单个键管理">1.7.1 单个键管理</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#1键重命名">1.键重命名 </a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#2-随机返回键">2. 随机返回键 </a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#3键过期">3.键过期</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#172-键遍历">1.7.2 键遍历</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#1-全量键遍历">1. 全量键遍历</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#2-渐进式遍历">2. 渐进式遍历</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#173-数据库管理">1.7.3 数据库管理</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#1切换数据库">1.切换数据库</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#2flushdb/flushall">2.flushdb/flushall </a><br/>
## 正文<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#21-配置数据源">2.1 配置数据源</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#22--基本操作">2.2 基本操作</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#23-自定义序列化器">2.3 自定义序列化器</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#24-单元测试">2.4 单元测试</a><br/>
</nav>
## 一、项目说明
### 1.1 项目结构
## 一、说明
#### 1.1 项目结构
1. RedisConfig.java 实现了 redisTemplate 序列化与反序列化的配置;
2. RedisOperation 和 RedisObjectOperation 分别封装了对基本类型和对象的操作。
- RedisConfig.java 实现了 redisTemplate 序列化与反序列化的配置;
- RedisOperation 和 RedisObjectOperation 分别封装了对基本类型和对象的操作。
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-boot-redis.png"/> </div>
#### 1.2 项目主要依赖
### 1.2 基本依赖
```xml
<!--redis starter -->
@ -64,7 +39,7 @@
## 二、整合 Redis
#### 2.1 在application.yml 中配置redis数据源
### 2.1 配置数据源
```yaml
spring:
@ -78,16 +53,15 @@ spring:
#spring.redis.cluster.nodes
```
#### 2.2 封装redis基本操作
### 2.2 基本操作
需要说明的是 spring boot 提供了两个 template 用于操作 redis:
Spring Boot 提供了两个 Template 用于操作 Redis
- StringRedisTemplate由于 redis 在大多数使用情况下都是操作字符串类型的存储,所以 spring boot 将对字符串的操作单独封装在 StringRedisTemplate
- RedisTemplate<Object, Object> redis 用于操作任意类型的 template。
- **StringRedisTemplate**:由于 Redis 在大多数使用情况下都是操作字符串类型的存储,所以 Spring Boot 将对字符串的操作单独封装在 StringRedisTemplate
- **RedisTemplate<Object, Object>** :用于操作任意类型的 Template。
```java
/**
* @author : heibaiying
* @description : redis 基本操作
*/
@ -150,7 +124,6 @@ public class RedisOperation {
```java
/**
* @author : heibaiying
* @description : redis 基本操作
*/
@ -211,15 +184,12 @@ public class RedisObjectOperation {
}
```
#### 2.3 redisTemplate 序列化为json格式与反序列化
### 2.3 自定义序列化器
这里需要说明的 spring boot 的 redisTemplate 本身是实现了对象的序列化与反序列化的,是支持直接存取对象的。但是这里的序列化默认采用的是 JdkSerializationRedisSerializer.serialize() 序列化为二进制码,这个本身是不影响 redisTemplate 的操作的,因为 redisTemplate 在取出数据的时候会自动进行反序列化。
但是如果我们在命令行中使用 get 命令去获取数据时候,得到的是一串不直观的二进制码,所以我们尽量将其序列化为直观的 json 格式存储。
Spring Boot 的 RedisTemplate 本身是实现了对象的序列化与反序列化的,但是这里的序列化默认采用的是 JDK 的序列化方式JdkSerializationRedisSerializer.serialize() 序列化为二进制码,此时如果我们在命令行中使用 get 命令去获取数据时候,得到的就是一串不直观的二进制码,所以我们尽量将其序列化为直观的 json 格式存储。自定义序列化器的方式如下:
```java
/**
* @author : heibaiying
* @description : 自定义序列化器
* 不定义的话默认采用的是 serializer.JdkSerializationRedisSerializer.serialize() 序列化为二进制字节码 存储在数据库中不直观
*/
@ -251,7 +221,7 @@ public class RedisConfig {
}
```
#### 2.4 测试
### 2.4 单元测试
```java
@RunWith(SpringRunner.class)
@ -288,192 +258,3 @@ public class RedisTests {
}
```
<br/>
## 附Redis的数据结构和操作命令
### 1.1 预备
#### 1.1.1 全局命令
1. 查看所有键: **keys \***
2. 查看键总数:**dbsize**
3. 检查键是否存在:**exists key**
4. 删除键:**del key [key ...]** 支持删除多个键
5. 键过期:**expire key seconds**
ttl 命令会返回键的剩余过期时间, 它有 3 种返回值:
- 大于等于 0 的整数: 键剩余的过期时间。
- -1 键没设置过期时间。
- -2 键不存在
6. 键的数据结构 **type key**
#### 1.1.2 数据结构和内部编码
type 命令实际返回的就是当前键的数据结构类型, 它们分别是:**string**(字符串) 、 **hash**(哈希) 、 **list**(列表) 、 **set**(集合) 、 **zset**(有序集合)
#### 1.1.3 单线程架构
1. 纯内存访问, Redis 将所有数据放在内存中, 内存的响应时长大约为 100 纳秒, 这是 Redis 达到每秒万级别访问的重要基础。
2. 非阻塞 I/O Redis 使用 epoll 作为 I/O 多路复用技术的实现, 再加上 Redis 自身的事件处理模型将 epoll 中的连接、 读写、 关闭都转换为事件, 不在网络 I/O 上浪费过多的时间, 如图 2-6 所示。
3. 单线程避免了线程切换和竞态产生的消耗。
### 1.2 字符串
| 作用 | 格式 | 参数或示例 |
| ---------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
| 设置值 | set key value \[ex seconds]\[px milliseconds][nx\|xx] setnx setex | ex seconds 为键设置秒级过期时间。 <br/>px milliseconds 为键设置毫秒级过期时间。<br/>nx 键必须不存在, 才可以设置成功, 用于添加。<br/>xx 与 nx 相反, 键必须存在, 才可以设置成功, 用于更新。 |
| 获取值 | get key | r 如果获取的键不存在 ,则返回 nil(空) |
| 批量设置 | mset key value [key value ...] | mset a 1 b 2 c 3 d 4 |
| 批量获取值 | mget key [key ...] | mget a b c d |
| 计数 | incr key decr key incrby key increment指定数值自增<br/>decrby key decrement指定数值自减<br/>incrbyfloat key increment (浮点数自增) | 值不是整数, 返回错误。 值是整数, 返回自增或自减后的结果。<br/>键不存在,创建键,并按照值为 0 自增或自减, 返回结果为 1。 |
| 追加值 | append key value | 向字符串的默认追加值 |
| 字符串长度 | strlen key | 获取字符串长度,中文占用三个字节 |
| 设置并返回原值 | getset key value | |
| 设置指定位置的租字符串 | setrange key offeset value | |
| 获取部分字符串 | getrange key start end | |
### 1.3 哈希
| 作用 | 格式 | 参数或示例 |
| ------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
| 设置值 | hset key field value | hset user:1 name tom<br/>hset user:1 age 12 |
| 获取值 | hget key field | hget user:1 name |
| 删除 field | hdel key field [field ...] | |
| 计算 field 个数 | hlen key | |
| 批量设置或获取 field-value | hmget key field [field]<br/>hmset key field value [field value...] | hmset user:1 name mike age 12 city tianjin<br/>hmget user:1 name city |
| 判断 field 是否存在 | hexists key field | |
| 获取所有 field | hkeys key | |
| 获取所有 value | hvals key | |
| 获取所有的 filed-value | hgetall key | 如果哈希元素个数比较多, 会存在阻塞 Redis 的可能。<br/>获取全部 可以使用 hscan 命令, 该命令会渐进式遍历哈希类型 |
| 计数 | hincrby key field<br/>hincrbyfloat key field | |
### 1.4 列表
| 作用 | 格式 | 参数或示例 |
| -------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
| 增 | 左侧插入lpush key value [value ...] 右侧插入rpush key value [value ...] 某个指定元素前后插入linsert key before\|after pivot value | |
| 查 | 获取指定范围内的元素列表lrange key start end 获取列表指定索引下标的元素lindex key index 获取列表指定长度llen key | lrange listkey 0 -1 |
| 删 | 从列表左侧弹出元素lpop key 从列表右侧弹出元素rpop key 删除指定元素lrem key count value 截取列表ltrim key start end | count>0 从左到右, 删除最多 count 个元素。<br/>count<0 从右到左 删除最多 count 绝对值个元素<br/>count=0 删除所有 |
| 改 | 修改指定索引下标的元素lset key index newValue | |
| 阻塞操作 | blpop key [key ...] timeout brpop key [key ...] timeout | key[key...] 多个列表的键。 timeout 阻塞时间\|等待时间(单位: 秒) |
### 1.5 集合
集合set 类型也是用来保存多个的字符串元素, 但和列表类型不一样的是, **集合中不允许有重复元素** 并且集合中的元素是无序的, **不能通过索引下标获取元素**
**集合内操作**
| 作用 | 格式 | 参数或示例 |
| -------------------- | ------------------------------ | ----------------------------------------- |
| 添加元素 | sadd key element [element ...] | 返回结果为添加成功的元素个数 |
| 删除元素 | srem key element [element ...] | 返回结果为成功删除的元素个数 |
| 计算元素个数 | scard key | |
| 判断元素是否在集合中 | sismember key element | |
| 随机返回 | srandmember key [count] | 随机从集合返回指定个数元素count 默认为 1 |
| 从集合随机弹出元素 | spop key | srandmember 不会从集合中删除元素spop 会 |
| 获取集合中所有元素 | smembers key | 可用 sscan 代替 |
**集合间操作**
| 作用 | 格式 |
| ---------------------------- | ------------------------------------------------------------ |
| 求多个集合的交集 | sinter key [key ...] |
| 求多个集合的并集 | suinon key [key ...] |
| 求多个集合的差集 | sdiff key [key ...] |
| 将交集、并集、差集的结果保存 | sinterstore destination key [key ...] <br/>suionstore destination key [key ...]<br/>sdiffstore destination key [key ...] |
### 1.6 有序集合
有序集合中的元素可以排序。 但是它和列表使用索引下标作为排序依据不同的是, 它给每个元素设置一个分数score 作为排序的依据。
**集合内操作**
| 作用 | 格式 | 参数或示例 |
| ------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
| 添加成员 | zadd key score member [score member ...] | nx member 必须不存在, 才可设置成功, 用于添加。<br> xx member 必须存在, 才可以设置成功, 用于更新。<br/>ch 返回此次操作后, 有序集合元素和分数发生变化的个数<br/>incr 对 score 做增加, 相当于后面介绍的 zincrby。 |
| 计算成员个数 | zcard key | |
| 计算某个成员的分数 | zscore key member | |
| 计算某个成员的排名 | zrank key member zrevrank key member | zrank 是从分数从低到高返回排名, zrevrank 反之。 |
| 删除成员 | zrem key member [member ...] | |
| 增加成员分数 | zincrby key increment member | zincrby user:ranking 9 tom |
| 返回指定排名范围的成员 | zrange key start end [withscores] zrange key start end [withscores] | zrange 是从低到高返回, zrevrange 反之。 |
| 返回指定分数范围内的成员 | zrangebyscore key min max \[withscores][limit offset count] zrevrangebyscore key max min \[withscores][limit offset count] | 其中 zrangebyscore 按照分数从低到高返回, zrevrangebyscore 反之。 [limit offset count]选项可以限制输出的起始位置和个数: 同时 min 和 max 还支持开区间(小括号) 和闭区间(中括号) -inf 和 +inf 分别代表无限小和无限大 |
| 删除指定排名内的升序元素 | zremrangerank key start end | |
| 删除指定分数范围的成员 | zremrangebyscore key min max | |
**集合间操作**
| 作用 | 格式 |
| ---- | ------------------------------------------------------------ |
| 交集 | zinterstore destination numkeys key \[key ...] [weights weight [weight ...]] \[aggregate sum\|min\|max] |
| 并集 | zunionstore destination numkeys key \[key ...] [weights weight [weight ...]] \[aggregate sum\|min\|max] |
- destination 交集计算结果保存到这个键。
- numkeys 需要做交集计算键的个数。
- key[key...] 需要做交集计算的键。
- weights weight[weight...] 每个键的权重, 在做交集计算时, 每个键中的每个 member 会将自己分数乘以这个权重, 每个键的权重默认是 1。
- aggregate sum|min|max 计算成员交集后, 分值可以按照 sum 、min最小值 、 max最大值 做汇总, 默认值是 sum。
### 1.7 键管理
#### 1.7.1 单个键管理
##### 1.键重命名
**rename key newkey**
为了防止被强行 rename Redis 提供了 renamenx 命令, 确保只有 newKey 不存在时候才被覆盖。
##### 2. 随机返回键
**random key**
##### 3.键过期
- expire key seconds 键在 seconds 秒后过期。
- expireat key timestamp 键在秒级时间戳 timestamp 后过期。
- pexpire key milliseconds 键在 milliseconds 毫秒后过期。
- pexpireat key milliseconds-timestamp 键在毫秒级时间戳 timestamp 后过期
注意:
1. 如果 expire key 的键不存在, 返回结果为 0
2. 如果设置过期时间为负值, 键会立即被删除, 犹如使用 del 命令一样
3. persist key t 命令可以将键的过期时间清除
4. 对于字符串类型键, 执行 set 命令会去掉过期时间, 这个问题很容易在开发中被忽视
5. Redis 不支持二级数据结构(例如哈希、 列表) 内部元素的过期功能, 例如不能对列表类型的一个元素做过期时间设置
6. setex 命令作为 set+expire 的组合, 不但是原子执行, 同时减少了一次网络通讯的时间
#### 1.7.2 键遍历
##### 1. 全量键遍历
**keys pattern**
##### 2. 渐进式遍历
scan cursor \[match pattern] \[count number]
- cursor 是必需参数, 实际上 cursor 是一个游标, 第一次遍历从 0 开始, 每次 scan 遍历完都会返回当前游标的值, 直到游标值为 0 表示遍历结束。
- match pattern 是可选参数, 它的作用的是做模式的匹配, 这点和 keys 的模式匹配很像。
- count number 是可选参数, 它的作用是表明每次要遍历的键个数, 默认值是 10 此参数可以适当增大。
#### 1.7.3 数据库管理
##### 1.切换数据库
**select dbIndex**
##### 2.flushdb/flushall
flushdb/flushall 命令用于清除数据库, 两者的区别的是 flushdb 只清除当前数据库, flushall 会清除所有数据库。

View File

@ -1,70 +1,66 @@
# spring boot 整合 servlet
# Spring Boot 整合 Servlet
## 目录<br/>
<a href="#一说明">一、说明</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#11-项目结构说明">1.1 项目结构说明</a><br/>
<nav>
<a href="#一项目说明">一、项目说明</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#11-结构说明">1.1 结构说明</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#12-项目依赖">1.2 项目依赖</a><br/>
<a href="#二采用spring-注册方式整合-servlet">二、采用spring 注册方式整合 servlet</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#21-新建过滤器监听器和servlet">2.1 新建过滤器、监听器和servlet</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#22-注册过滤器监听器和servlet">2.2 注册过滤器、监听器和servlet</a><br/>
<a href="#三采用注解方式整合-servlet">三、采用注解方式整合 servlet</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#31-新建过滤器监听器和servlet分别使用WebFilterWebListenerWebServlet注解标注">3.1 新建过滤器、监听器和servlet,分别使用@WebFilter@WebListener@WebServlet注解标注</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#32-使注解生效">3.2 使注解生效</a><br/>
## 正文<br/>
<a href="#二Spring-注册方式">二、Spring 注册方式</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#21-组件声明">2.1 组件声明</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#22-组件注册">2.2 组件注册</a><br/>
<a href="#三原生注解方式">三、原生注解方式</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#31-组件声明">3.1 组件声明</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#32-组件生效">3.2 组件生效</a><br/>
</nav>
## 一、项目说明
### 1.1 结构说明
## 一、说明
#### 1.1 项目结构说明
1. 项目提供与 servlet 整合的两种方式,一种是 servlet3.0 原生的注解方式,一种是采用 spring 注册的方式;
2. servlet、过滤器、监听器分别位于 servlet、filter、listen 下,其中以 Annotation 命名结尾的代表是 servlet 注解方式实现,采用 spring 注册方式则在 ServletConfig 中进行注册;
3. 为了说明外置容器对 servlet 注解的自动发现机制,项目采用外置容器构建,关于 spring boot 整合外置容器的详细说明可以参考[spring-boot-tomcat](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring-boot/spring-boot-tomcat)
- 项目提供与 Servlet 整合的两种方式,一种是 Servlet 3.0 原生的注解方式,一种是采用 Spring 注册的方式;
- Servlet、过滤器、监听器分别位于 servlet、filter、listen 下,其中以 Annotation 命名结尾的代表是 Servlet 是以注解方式实现,采用 Spring 注册方式则需要在 ServletConfig 中进行注册;
- 为了说明外置容器对 Servlet 注解的自动发现机制,项目采用外置容器构建,关于 Spring Boot 整合外置容器的详细说明可以参考:[spring-boot-tomcat](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring-boot/spring-boot-tomcat) 。
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-boot-servlet.png"/> </div>
#### 1.2 项目依赖
### 1.2 项目依赖
```xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!--排除依赖 使用外部 tomcat 容器启动-->
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<!--使用外置容器时候 SpringBootServletInitializer 依赖此包 -->
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<!--servlet api 注解依赖包-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
</dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!--排除依赖 使用外部 tomcat 容器启动-->
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<!--使用外置容器时候 SpringBootServletInitializer 依赖此包 -->
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<!--servlet api 注解依赖包-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
</dependencies>
```
## 二、采用spring 注册方式整合 servlet
## 二、Spring 注册方式
#### 2.1 新建过滤器、监听器和servlet
### 2.1 组件声明
声明过滤器、监听器和 Servlet
```java
/**
* @author : heibaiying
* @description : 自定义过滤器
*/
public class CustomFilter implements Filter {
@Override
@ -88,7 +84,6 @@ public class CustomFilter implements Filter {
```java
/**
* @author : heibaiying
* @description : 自定义监听器
*/
public class CustomListen implements ServletContextListener {
@ -113,7 +108,6 @@ public class CustomListen implements ServletContextListener {
```java
/**
* @author : heibaiying
* @description : 自定义 servlet
*/
public class CustomServlet extends HttpServlet {
@ -131,12 +125,9 @@ public class CustomServlet extends HttpServlet {
}
```
#### 2.2 注册过滤器、监听器和servlet
### 2.2 组件注册
```java
/**
* @author : heibaiying
*/
@Configuration
public class ServletConfig {
@ -161,13 +152,14 @@ public class ServletConfig {
}
```
## 三、采用注解方式整合 servlet
## 三、原生注解方式
#### 3.1 新建过滤器、监听器和servlet,分别使用@WebFilter@WebListener@WebServlet注解标注
### 3.1 组件声明
新建过滤器、监听器和 servlet,分别使用 @WebFilter@WebListener@WebServlet 注解进行声明:
```java
/**
* @author : heibaiying
* @description : 自定义过滤器
*/
@ -194,7 +186,6 @@ public class CustomFilterAnnotation implements Filter {
```java
/**
* @author : heibaiying
* @description :自定义监听器
*/
@WebListener
@ -219,9 +210,7 @@ public class CustomListenAnnotation implements ServletContextListener {
```
```java
/**
* @author : heibaiying
* @description : 自定义 servlet
*/
@WebServlet(urlPatterns = "/servletAnn")
@ -239,7 +228,9 @@ public class CustomServletAnnotation extends HttpServlet {
}
```
#### 3.2 使注解生效
### 3.2 组件生效
1. 如果是内置容器,需要在启动类上添加@ServletComponentScan("com.heibaiying.springbootservlet") ,指定扫描的包目录;
2. 如果是外置容器,不需要进行任何配置,依靠容器内建的 discovery 机制自动发现,需要说明的是这里的容器必须支持 servlet3.0tomcat 从 7.0 版本开始支持 Servlet3.0)。
想要让使用 Servlet 3.0 原生注解方式声明的组件生效,有以下两种方式:
- 如果是内置容器,需要在启动类上添加 @ServletComponentScan ,指定扫描的包目录;
- 如果是外置容器,不需要进行任何配置,依靠容器内建的 Discovery 机制自动发现,需要说明的是这里的容器必须支持 Servlet 3.0 Tomcat 从 7.0 版本开始支持 Servlet3.0)。

View File

@ -1,53 +1,49 @@
# spring-boot 集成 Swagger2 打造在线接口文档
# Spring Boot 集成 Swagger2 打造在线接口文档
<nav>
<a href="#一概念综述">一、概念综述</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#11-SpringFox">1.1 SpringFox </a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#12-Swagger">1.2 Swagger</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#13-关联关系">1.3 关联关系</a><br/>
<a href="#二集成-Swagger-20">二、集成 Swagger 2.0</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#21-基本依赖">2.1 基本依赖</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#22-Swagger--配置">2.2 Swagger 配置 </a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#23-Swagger-注解">2.3 Swagger 注解 </a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#24-可视化接口文档">2.4 可视化接口文档</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#25-接口测试">2.5 接口测试</a><br/>
</nav>
## 目录<br/>
<a href="#一Springfox-与-Swagger-简介">一、Springfox 与 Swagger 简介</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#11-Springfox">1.1 Springfox</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#12-Swagger">1.2 Swagger</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#13-OpenApiSwaggerSpringfox的关系">1.3 OpenApi、Swagger、Springfox的关系</a><br/>
<a href="#二spring-boot-集成-swagger-20">二、spring boot 集成 swagger 2.0</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#21-导入项目相关依赖">2.1 导入项目相关依赖</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#22--进行swagger个性化配置并用EnableSwagger2开启Swagger支持">2.2 进行swagger个性化配置、并用@EnableSwagger2开启Swagger支持</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#23-swagger注解的使用和说明">2.3 swagger注解的使用和说明</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#24-swagger-ui-可视化接口文档">2.4 swagger-ui 可视化接口文档</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#25-利用swagger-ui进行接口测试">2.5 利用swagger-ui进行接口测试</a><br/>
## 正文<br/>
## 一、概念综述
## 一、Springfox 与 Swagger 简介
### 1.1 SpringFox
### 1.1 Springfox
Springfox 是一个开源的 API Doc 的框架, 它的前身是 swagger-springmvc能够完美的支持 springmvc可以将 spring 接口方法自动转换为接口文档。 目前 spring fox 正致力于对更多 JSON API 规范和标准的扩展和支持,例如:[swagger](http://swagger.io/)[RAML](http://raml.org/) 和[jsonapi](http://jsonapi.org/)。
SpringFox 是一个开源的 API 文档框架, 它的前身是 Swagger-SpringMVC ,能够完美的支持 SpringMVC 并将其中接口方法自动转换为接口文档。 目前 SpringFox 正致力于对更多 JSON API 规范和标准的扩展和支持,例如:[swagger](http://swagger.io/)[RAML](http://raml.org/) 和 [jsonapi](http://jsonapi.org/)。
### 1.2 Swagger
Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务,支持从整个 API 生命周期(从设计和文档到测试和部署)的开发。
Swagger 是一个规范框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务,支持 API 全生命周期的开发和管理。它是一个综合的开源项目,包含 [swagger-core](https://github.com/swagger-api/swagger-core)、[swagger-ui](https://github.com/swagger-api/swagger-ui)、[swagger-codegen](https://github.com/swagger-api/swagger-codegen)、[swagger-editor](https://github.com/swagger-api/swagger-editor) 等多个子项目:
swagger 是一个综合的开源项目,包含[swagger-core](https://github.com/swagger-api/swagger-core)、[swagger-ui](https://github.com/swagger-api/swagger-ui)、[swagger-codegen](https://github.com/swagger-api/swagger-codegen)、[swagger-editor](https://github.com/swagger-api/swagger-editor) 等多个子项目
+ **swagger-core**Swagger Core 是 OpenAPI 规范(以前称为 Swagger 规范)的 Java 实现。
+ **swagger-core**Swagger Core 是 OpenAPI 规范(以前称为 Swagger 规范)的**Java 实现**
+ **swagger-ui**:根据可视化文档,提供与 API 资源的可视化交互
+ **swagger-ui**:依据可视化文档,提供与 API 资源的可视化交互
+ **swagger-codegen**:开源的代码生成器,根据 Swagger 定义的 RESTful API 可以自动建立服务端和客户端的连接
+ **swagger-codegen**:开源的代码生成器,根据 Swagger 定义的 RESTful API 可以自动建立服务端和客户端的连接。
+ **swagger-editor**:开源的 api 文档编辑器。
+ **swagger-editor**:开源的 API 文档编辑器。
下图为 swagger-ui 提供的文档可视化界面示例:
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/Swagger_UI.png"/> </div>
### 1.3 关联关系
### 1.3 OpenApi、Swagger、Springfox的关系
**Swagger Core 是 OpenApi 规范(以前称为 Swagger 规范)的 Java 实现,而 Springfox 提供 Swagger 与 spring 的集成支持**。<br/>
OpenAPI、Swagger、SpringFox 之间的关联关系可以表述为:**Swagger Core 是 Open API 规范的 Java 实现,而 SpringFox 则提供了 Swagger 与 Spring 的集成支持**。<br/>
## 二、spring boot 集成 swagger 2.0
## 二、集成 Swagger 2.0
### 2.1 导入项目相关依赖
### 2.1 基本依赖
```xml
<!--swagger2-->
@ -64,25 +60,18 @@ swagger 是一个综合的开源项目,包含[swagger-core](https://github.com
</dependency>
```
### 2.2 Swagger 配置
进行 Swagger 个性化配置,并使用 @EnableSwagger2 开启 Swagger 支持。另外,虽然 Swagger 是一个非常易用的接口调试插件,但是有可能会导致接口信息泄露,所以建议在开发环境和测试环境开启,但在生产环境关闭。这里一共给出三种 Swagger 开启和关闭的切换方法:
### 2.2 进行swagger个性化配置、并用@EnableSwagger2开启Swagger支持
1. 如下面代码所示,在配置文件中增加自定义的开关参数,并在创建 Docket 时,在链式调用的 enable() 方法中传入。
2. 在 SwaggerConfig 配置类上添加 `@Profile({"dev","test"}) ` 注解,指明仅在开发环境和测试环境下激活此配置,并在打包部署时使用 spring.profiles.active 指明具体的环境。
3. 在配置文件中配置自定义的开关参数,并在 SwaggerConfig 配置类上添加 `@ConditionalOnProperty(name = "swagger.enable", havingValue = "true") `,指明配置类的生效条件。@ConditionalOnProperty 注解能够控制某个配置类是否生效。具体操作是通过 name 和 havingValue 属性来实现name 对应配置文件中的某个属性,如果该值为空,则返回 false如果值不为空则将该值与 havingValue 指定的值进行比较,如果一样则返回 true否则返回 false。如果返回值为 false则对应的配置不生效为 true 则生效。
这里需要说明的是 swagger 虽然是一个非常直观易用的接口调试插件,但是有可能导致接口信息泄露的危险,所以建议在开发环境和测试环境开启,在生产环境关闭。这里一共给出三种 Swagger 开关切换的方法:
1. 如下面代码所示,在配置文件中配置自定义的开关参数,并在创建 Docket 时候,在链式调用的 enable() 方法中传入;
2. 在 `SwaggerConfig` 配置类上添加 `@Profile({"dev","test"}) ` 注解,指明在开发环境和测试环境下激活此配置类,打包或者部署时候使用 spring.profiles.active 指明环境即可;
3. 在配置文件中配置自定义的开关参数,并在 `SwaggerConfig` 配置类上添加 `@ConditionalOnProperty(name = "swagger.enable", havingValue = "true") `,指明配置类的生效条件
注:@ConditionalOnProperty 注解说明
@ConditionalOnProperty 注解能够控制某个@configuration 修饰的配置类是否生效。具体操作是通过 name 和 havingValue 属性来实现name 对应 application.propertiesyml中的某个属性值如果该值为空则返回 false如果值不为空则将该值与 havingValue 指定的值进行比较,如果一样则返回 true否则返回 false。如果返回值为 false则该 configuration 不生效;为 true 则生效。
以下是第一种开关配置方式的使用示例:
```java
/**
* @author : heibaiying
* @description : Swagger 配置类
*/
@Configuration
@ -140,7 +129,7 @@ swagger.enable = true
### 2.3 swagger注解的使用和说明
### 2.3 Swagger 注解
```java
@Slf4j
@ -212,7 +201,7 @@ public class ProductController {
}
```
swagger 为了最大程度防止对逻辑代码的侵入,基本都是依靠注解来完成文档描述。常用注解如下:
Swagger 为了最大程度防止对逻辑代码的侵入,基本都是依靠注解来完成文档描述。常用注解如下:
| Annotation | Attribute | Target Property | Description |
| ---------------- | ------------ | ------------------------- | ------------------------------------------------------------ |
@ -225,7 +214,7 @@ swagger 为了最大程度防止对逻辑代码的侵入,基本都是依靠注
| ApiOperation | summary | Operation#summary | e.g. `@ApiOperation(value="${operation1.summary}")` |
| RequestParam | defaultValue | Parameter#defaultValue | e.g. `@RequestParam(defaultValue="${param1.defaultValue}")` |
1. `@Api`Api 用在类上,说明该类的作用;
1. `@Api`:用在类上,说明该类的作用;
2. `@ApiOperation`:用在方法上,说明方法的作用;
@ -233,9 +222,9 @@ swagger 为了最大程度防止对逻辑代码的侵入,基本都是依靠注
4. `@ApiImplicitParams`:用在方法上说明方法参数的作用;
5. `@ApiImplicitParam`:用在@ApiImplicitParams 注解中,描述每个具体参数;
5. `@ApiImplicitParam`:用在 @ApiImplicitParams 注解中,描述每个具体参数;
6. `@ApiResponses`:一组@ApiResponse 的配置;
6. `@ApiResponses`:一组 @ApiResponse 的配置;
7. `@ApiResponse`:请求返回的配置;
@ -245,23 +234,22 @@ swagger 为了最大程度防止对逻辑代码的侵入,基本都是依靠注
10. `@ApiModelProperty`:描述 model 的属性。
11. `@ApiIgnore`:可以用于类、方法、属性,代表该方法、类、属性不被 swagger 的文档所管理。
11. `@ApiIgnore`:可以用于类、方法、属性,代表该方法、类、属性不被 Swagger 的文档所管理。
### 2.4 swagger-ui 可视化接口文档
### 2.4 可视化接口文档
接口文档访问地址http://localhost:8080/swagger-ui.html ,文档主界面如下:
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/swagger-ui-index.png"/> </div>
### 2.5 接口测试
### 2.5 利用swagger-ui进行接口测试
Swagger-UI 除了提供接口可视化的功能外,还可以用于接口测试。点击对应接口的 `try it out` 按钮,然后输入对应的参数的值,最后点击下方的 `Execute` 按钮发送请求:
​点击对应接口的 `try it out` 按钮可以进行接口测试,此时可以输入对应的参数的值,然后点击下方的 `Execute` 按钮发送请求。<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/swagger-try-it.png"/> </div>
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/swagger-try-it.png"/> </div>
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/swagger-execute.png"/> </div>
post 方法可以直接修改 model 对应的 json 数据 ,然后点击下方的 `Execute` 按钮发送请求。
POST 接口可以直接修改 Model 对应的 Json 数据 ,然后点击下方的 `Execute` 按钮发送请求:
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/swagger-post-try.png"/> </div>

View File

@ -1,26 +1,22 @@
# spring boot 整合 tomcat
# Spring Boot 整合 Tomcat
<nav>
<a href="#一项目说明">一、项目说明</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#11-项目结构">1.1 项目结构</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#12-基本依赖">1.2 基本依赖</a><br/>
<a href="#二整合-Tomcat">二、整合 Tomcat</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#21-SpringBootServletInitializer">2.1 SpringBootServletInitializer</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#22-定义视图">2.2 定义视图</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#23-整合测试">2.3 整合测试</a><br/>
</nav>
## 目录<br/>
<a href="#一说明">一、说明</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#11-项目结构说明">1.1 项目结构说明</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#12-项目主要依赖">1.2 项目主要依赖</a><br/>
<a href="#二整合-tomcat">二、整合 tomcat</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#21-修改启动类继承自SpringBootServletInitializer并覆盖重写其中configure方法">2.1 修改启动类继承自SpringBootServletInitializer并覆盖重写其中configure方法</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#22-在applicationyml-中指定访问视图文件的前缀和后缀">2.2 在application.yml 中指定访问视图文件的前缀和后缀 </a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#23-新建controller和showjsp-测试整合是否成功">2.3 新建controller和show.jsp 测试整合是否成功</a><br/>
## 正文<br/>
## 一、项目说明
### 1.1 项目结构
## 一、说明
#### 1.1 项目结构说明
spring boot 整合 tomcat 后支持 jsp 的使用(内置容器默认是不支持 jsp所以项目整合后采用 jspController 跳转到 show.jsp 测试整合是否成功。
Spring Boot 默认采用内置的 Web 容器,因此打成 JAR 包后就可以直接运行。但在某的时候,你可能还是需要使用 Tomcat 来运行和管理 Web 项目,因此本用例主要介绍 Spring Boot 与 Tomcat 的整合方式。另外 Spring Boot 内置的 Web 容器默认并不支持 JSP所以可以使用跳转到 JSP 页面的方式来测试整合外部容器是否成功。
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-boot-tomcat.png"/> </div>
#### 1.2 项目主要依赖
### 1.2 基本依赖
```xml
<dependency>
@ -43,9 +39,11 @@ spring boot 整合 tomcat 后支持 jsp 的使用(内置容器默认是不支
</dependency>
```
## 二、整合 tomcat
## 二、整合 Tomcat
#### 2.1 修改启动类继承自SpringBootServletInitializer并覆盖重写其中configure方法
### 2.1 SpringBootServletInitializer
修改启动类,继承自 SpringBootServletInitializer并覆盖重写其中 configure 方法:
```java
/**
@ -69,7 +67,9 @@ public class SpringBootTomcatApplication extends SpringBootServletInitializer {
}
```
#### 2.2 在application.yml 中指定访问视图文件的前缀和后缀
### 2.2 定义视图
在 application.yml 中指定访问视图文件的前缀和后缀:
```yml
spring:
@ -79,7 +79,9 @@ spring:
suffix: .jsp
```
#### 2.3 新建controller和show.jsp 测试整合是否成功
### 2.3 整合测试
新建 controller 和 show.jsp 测试整合是否成功:
```java
@Controller

View File

@ -1,32 +1,28 @@
# spring boot websocket
## 目录<br/>
<a href="#一说明">一、说明</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#11-项目结构说明">1.1 项目结构说明</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#12-主要依赖">1.2 主要依赖</a><br/>
<a href="#二spring-boot-websocket">二、spring boot websocket</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#21-创建消息处理类ChatSocket使用ServerEndpoint声明websocket服务">2.1 创建消息处理类ChatSocket使用@ServerEndpoint声明websocket服务</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#22-配置ServerEndpointExporterServerEndpointExporter会在运行时候自动注册我们用ServerEndpoint声明的websocket服务">2.2 配置ServerEndpointExporterServerEndpointExporter会在运行时候自动注册我们用@ServerEndpoint声明的websocket服务</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#23-前端websocket的实现">2.3 前端websocket的实现</a><br/>
# Spring Boot WebSocket
<nav>
<a href="#一项目说明">一、项目说明</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#11-项目结构">1.1 项目结构</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#12-基本依赖">1.2 基本依赖</a><br/>
<a href="#二Spring-Boot-WebSocket">二、Spring Boot WebSocket</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#21-消息处理">2.1 消息处理</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#22-注册服务">2.2 注册服务</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#23-前端-WebSocket">2.3 前端 WebSocket</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#24-简单登录的实现">2.4 简单登录的实现</a><br/>
## 正文<br/>
</nav>
## 一、项目说明
### 1.1 项目结构
## 一、说明
### 1.1 项目结构说明
1. 项目模拟一个简单的群聊功能,为区分不同的聊天客户端,登录时候将临时用户名存储在 session 当中;
2. 关于 websocket 的主要配置在 websocket 文件夹下;
3. 模板引擎采用 freemaker
4. 项目以 web 的方式构建。
- 项目模拟一个简单的群聊功能,为区分不同的聊天客户端,登录时候将临时用户名存储在 session 当中;
- 关于 WebSocket 的主要配置在 websocket 文件夹下;
- 模板引擎采用 freemaker
- 项目以 Web 的方式构建。
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-boot-websocket.png"/> </div>
### 1.2 主要依赖
### 1.2 基本依赖
```xml
<dependency>
@ -46,9 +42,11 @@
## 二、spring boot websocket
## 二、Spring Boot WebSocket
#### 2.1 创建消息处理类ChatSocket使用@ServerEndpoint声明websocket服务
### 2.1 消息处理
创建消息处理类 ChatSocket使用 @ServerEndpoint 声明 websocket 服务:
```java
@ServerEndpoint(value = "/socket/{username}")
@ -94,7 +92,9 @@ public class ChatSocket {
```
#### 2.2 配置ServerEndpointExporterServerEndpointExporter会在运行时候自动注册我们用@ServerEndpoint声明的websocket服务
### 2.2 注册服务
配置 ServerEndpointExporterServerEndpointExporter 会在运行时候自动注册我们用 @ServerEndpoint 注解声明的 WebSocket 服务:
```java
@Configuration
@ -112,7 +112,7 @@ public class WebSocketConfig {
}
```
#### 2.3 前端websocket的实现
### 2.3 前端 WebSocket
```jsp
<!doctype html>
@ -157,7 +157,7 @@ public class WebSocketConfig {
```
#### 2.4 简单登录的实现
### 2.4 简单登录的实现
```java
<!doctype html>

View File

@ -1,60 +1,44 @@
# spring-boot-yml-profile
## 目录<br/>
# Spring Boot YAML
<nav>
<a href="#一项目结构">一、项目结构</a><br/>
<a href="#二常用-yaml-语法讲解">二、常用 yaml 语法讲解</a><br/>
<a href="#二YAML-语法">二、YAML 语法</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#21-基本规则">2.1 基本规则</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#22-对象的写法">2.2 对象的写法</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#23-map的写法">2.3 map的写法</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#23-数组的写法">2.3 数组的写法</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#23-Map的写法">2.3 Map的写法</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#24-数组的写法">2.4 数组的写法</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#25-单双引号">2.5 单双引号</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#26-特殊符号">2.6 特殊符号</a><br/>
<a href="#三spring-boot-与-yaml">三、spring boot 与 yaml</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#31--spring-boot-支持使用-${appname}-引用预先定义的值">3.1 spring boot 支持使用 ${app.name} 引用预先定义的值</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#32-spring-boot-支持使用-${randomxxx}-配置随机值">3.2 spring boot 支持使用 ${random.xxx} 配置随机值</a><br/>
<a href="#四@ConfigurationProperties实现属性绑定">四、@ConfigurationProperties实现属性绑定</a><br/>
<a href="#五多配置文件">五、多配置文件</a><br/>
<a href="#三Spring-Boot-与-YAML">三、Spring Boot 与 YAML</a><br/>
<a href="#四ConfigurationProperties">四、@ConfigurationProperties</a><br/>
<a href="#五多环境配置文件">五、多环境配置文件</a><br/>
<a href="#六优先级的说明">六、优先级的说明</a><br/>
## 正文<br/>
</nav>
## 一、项目结构
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-boot-yml-profile.png"/> </div>
## 二、YAML 语法
## 二、常用 yaml 语法讲解
Spring Boot 支持使用 Yaml 语法来书写配置文件,相比于 properties 文件键值对的配置格式Yaml 语法的配置更加精简,层次也更加分明。其基本规则和语法如下:
项目中的 yml 配置文件如下:
### 2.1 基本规则
```yaml
programmer:
name: xiaoming-DEV
married: false
hireDate: 2018/12/23
salary: 66666.88
random: ${random.int[1024,65536]}
skill: {java: master, jquery: proficiency}
company: [baidu,tengxun,alibaba]
school:
name: unviersity
location: shanghai
```
- 大小写敏感 。
- 使用缩进表示层级关系 。
- 缩进长度没有限制,只要元素对齐就表示这些元素属于一个层级。
- 使用#表示注释
- 字符串默认不用加单双引号,但单引号和双引号都可以使用,双引号不会对特殊字符转义。
- YAML 中提供了多种常量结构包括整数浮点数字符串NULL日期布尔时间。
#### 2.1 基本规则
### 2.2 对象的写法
1. 大小写敏感
2. 使用缩进表示层级关系
3. 缩进长度没有限制,只要元素对齐就表示这些元素属于一个层级。
4. 使用#表示注释
5. 字符串默认不用加单双引号,但单引号和双引号都可以使用,双引号不会对特殊字符转义。
6. YAML 中提供了多种常量结构包括整数浮点数字符串NULL日期布尔时间。
#### 2.2 对象的写法
支持使用键值对的格式来配置对象属性,但 `:` 符号后面需要有一个空格:
```yaml
key: value
```
#### 2.3 map的写法
### 2.3 Map的写法
```yaml
# 写法一 同一缩进的所有键值对属于一个map
@ -66,7 +50,7 @@ key:
{key1: value1, key2: value2}
```
#### 2.3 数组的写法
### 2.4 数组的写法
```yaml
# 写法一 使用一个短横线加一个空格代表一个数组项
@ -78,9 +62,9 @@ key:
[a,b,c]
```
#### 2.5 单双引号
### 2.5 单双引号
单引号和双引号都可以使用,双引号不会对特殊字符转义。
Yaml 支持单引号和双引号,但双引号不会对特殊字符转义:
```yaml
s1: '内容\n 字符串'
@ -90,22 +74,20 @@ s2: "内容\n 字符串"
{ s1: '内容\\n 字符串', s2: '内容\n 字符串' }
```
#### 2.6 特殊符号
### 2.6 特殊符号
--- YAML 可以在同一个文件中,使用---表示一个文档的开始
可以在同一个文件中包含多个 YAML 文档,并使用 `---` 进行分割
## 三、Spring Boot 与 YAML
## 三、spring boot 与 yaml
#### 3.1 spring boot 支持使用 ${app.name} 引用预先定义的值
Spring Boot 中支持使用 ${app.name} 引用预先定义的值:
```properties
appName: MyApp
appDescription: ${app.name} is a Spring Boot application
```
#### 3.2 spring boot 支持使用 ${random.xxx} 配置随机值
Spring Boot 支持使用 ${random.xxx} 配置随机值:
```properties
my.secret: ${random.value}
@ -117,7 +99,9 @@ my.number.in.range: ${random.int[1024,65536]}
## 四、@ConfigurationProperties实现属性绑定
## 四、@ConfigurationProperties
Spring Boot 支持使用 @ConfigurationProperties 注解来将 Yaml 中的配置与实体类进行绑定,示例如下:
```java
@Component
@ -139,27 +123,40 @@ public class Programmer {
}
```
Spring Boot 将环境属性绑定到@ConfigurationProperties beans 时会使用一些宽松的规则,称之为松散绑定。所以 Environment 属性名和 bean 属性名不需要精确匹配。常见的示例中有用的包括虚线分割比如context-path 绑定到 contextPath将环境属性转为大写字母比如PORT 绑定 port
```yaml
programmer:
name: xiaoming-DEV
married: false
hireDate: 2018/12/23
salary: 66666.88
random: ${random.int[1024,65536]}
skill: {java: master, jquery: proficiency}
company: [baidu,tengxun,alibaba]
school:
name: unviersity
location: shanghai
```
需要注意的是 `@Value` 是不支持松散绑定的,所以建议除非有特殊的需求,否则在 `ConfigurationProperties``value` 配置属性的时候最好都保持属性和变量的一致,以免造成不必要的勿扰。
Spring Boot 在将环境属性绑定到 `@ConfigurationProperties` beans 时会使用一些宽松的规则,称之为松散绑定。因此配置的属性名和 bean 属性名不需要精确匹配。它会自动执行一些驼峰转换或大小写转换,例如将 context-path 绑定到 contextPath或将 PORT 绑定 port 。
但需要注意的是只有 `@ConfigurationProperties` 注解才支持松散绑定,而另一个属性绑定注解 `@Value` 是不支持松散绑定的,所以除非有特殊的需求,否则建议保持类中的属性名和配置文件中的属性名完全一致。
## 五、多配置文件
## 五、多环境配置文件
多配置文件可以在同一个 yml 中使用 --- 分割为多个配置,或者遵循 application-xxx.yml 的方式命名拆分为多个文件,并在主配置文件 application.yml 中确定激活哪个配置文件,当然也可在命令行中确定,命令行的优先级大于配置文件。
可以在同一个 yml 文件中包含多个配置文件,并使用 `---` 进行分割。或者遵循 application-xxx.yml 命名方式来为不同的环境(如开发环境,生产环境,测试环境)分别生成不同的配置文件,然后再在主配置文件 application.yml 中来决定使用哪个具体的配置,或在启动时候通过命令行参数来决定,命令行的优先级大于配置文件的优先级
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/profile.png"/> </div>
```yaml
# 配置文件中激活配置
# 配置文件中激活开发环境配置
spring:
profiles:
active: dev
```
```shell
# 命令行参数激活配置
# 启动项目时候在命令行中通过参数进行激活
--spring.profiles.active=dev
```
@ -167,7 +164,7 @@ spring:
## 六、优先级的说明
Spring Boot 设计了一个非常特别的 PropertySource 顺序,以允许对属性值进行合理的覆盖,属性会以如下的顺序进行设值
Spring Boot 支持在多个地方进行配置的定义,按照配置方式的不同,属性优先级由高到低的顺序如下
1. home 目录下的 devtools 全局设置属性(~/.spring-boot-devtools.properties如果 devtools 激活)。
2. 测试用例上的@TestPropertySource 注解。
@ -187,8 +184,8 @@ Spring Boot 设计了一个非常特别的 PropertySource 顺序,以允许对
16. @Configuration 类上的@PropertySource 注解。
17. 默认属性(使用 SpringApplication.setDefaultProperties 指定)。
这里做一下说明,上文第 12,14 点没有打进 jar 包的文件指的是在启动时候通过 `spring.config.location` 参数指定的外部配置文件,外部配置文件的优先级应该是大于 jar 中的配置文件。
这里做一点说明:上文第 12 和 14 点没有打进 JAR 包的文件指的是在启动时候通过 `spring.config.location` 参数指定的外部配置文件,外部配置文件的优先级大于 JAR 中配置文件的优先级。另外,常用的优先级规则可以精简如下:
对上面的配置中常用的规则可以精简如下:
**命令行 > application-{profile}.yml > application.yml > 默认属性**
```shell
命令行 > application-{profile}.yml > application.yml > 默认属性
```

View File

@ -1,21 +1,29 @@
# spring boot + druid + mybatis + atomikos 配置多数据源 并支持分布式事务
# Spring Boot + Druid + Mybatis + Atomikos 配置多数据源 并支持分布式事务
<a href="#一综述">一、综述</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#11-项目说明">1.1 项目说明</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#12-项目结构">1.2 项目结构</a><br/>
<nav>
<a href="#一项目综述">一、项目综述</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#11-项目说明">1.1 项目说明</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#12-项目结构">1.2 项目结构</a><br/>
<a href="#二配置多数据源并支持分布式事务">二、配置多数据源并支持分布式事务</a><br/>
<a href="#三整合结果测试">三、整合结果测试</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#21--导入基本依赖">2.1 导入基本依赖</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#22-配置多数据源">2.2 配置多数据源</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#23-实现多数据源">2.3 实现多数据源</a><br/>
<a href="#三测试整合结果">三、测试整合结果</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#31--测试数据库整合结果">3.1 测试数据库整合结果</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#32-测试单数据库事务">3.2 测试单数据库事务</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#33-测试分布式事务">3.3 测试分布式事务</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#34-测试-Druid-数据源">3.4 测试 Druid 数据源</a><br/>
<a href="#四JTA与两阶段提交">四、JTA与两阶段提交</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#41-XA-与-JTA">4.1 XA 与 JTA</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#42-两阶段提交">4.2 两阶段提交</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#41-XA-与-JTA">4.1 XA 与 JTA</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#42-两阶段提交">4.2 两阶段提交</a><br/>
<a href="#五常见整合异常">五、常见整合异常</a><br/>
</nav>
## 一、综述
## 一、项目综述
### 1.1 项目说明
本用例基于 spring boot + druid + mybatis 配置多数据源,并采用 **JTA 实现分布式事务**
本用例基于 Spring Boot + Druid + Mybatis 配置多数据源,并采用 JTA 实现分布式事务
### 1.2 项目结构
@ -25,15 +33,11 @@
## 二、配置多数据源并支持分布式事务
### 2.1 导入基本依赖
除了 mybatis 、durid 等依赖外,我们依靠切面来实现动态数据源的切换,所以还需要导入 aop 依赖。
最主要的是还要导入 spring-boot-starter-jta-atomikosSpring Boot 通过[Atomkos](http://www.atomikos.com/) 或[Bitronix](http://docs.codehaus.org/display/BTM/Home) 的内嵌事务管理器支持跨多个 XA 资源的分布式 JTA 事务,当发现 JTA 环境时Spring Boot 将使用 Spring 的 JtaTransactionManager 来管理事务。自动配置的 JMSDataSource 和 JPA beans 将被升级以支持 XA 事务。
除了 Mybatis 、Durid 等基本依赖外,由于我们是依靠切面来实现动态数据源的切换,所以还需要导入 AOP 依赖。另外还需要导入 spring-boot-starter-jta-atomikosSpring Boot 通过 [Atomkos](http://www.atomikos.com/) 或 [Bitronix](http://docs.codehaus.org/display/BTM/Home) 等内嵌事务管理器来支持跨多个 XA 资源的分布式 JTA 事务,当发现 JTA 的依赖和环境时Spring Boot 将使用 Spring 的 JtaTransactionManager 来管理事务,并且自动配置的 JMSDataSource 和 JPA Beans 也会被升级以支持 XA 事务。
```xml
<!--mybatis starter-->
@ -76,12 +80,10 @@
</dependency>
```
### 2.2 在yml中配置多数据源信息
### 2.2 配置多数据源
**注意**Spring Boot 2.X 版本不再支持配置继承,多数据源的话每个数据源的所有配置都需要单独配置,否则配置不会生效。
这里我用的本地数据库 mysql 和 mysql02,配置如下:
```yml
spring:
datasource:
@ -169,11 +171,11 @@ spring:
login-password: druid
```
### 2.3 实现多数据源
#### 1. 关闭自动化配置
### 2.3 进行多数据源的配置
#### 1. 在启动类关闭springboot对数据源的自动化配置由我们手动进行多数据源的配置
在启动类关闭 Spring Boot 对数据源的自动化配置,由我们手动进行多数据源的配置:
```java
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@ -186,11 +188,13 @@ public class DruidMybatisMultiApplication {
}
```
#### 2. 创建多数据源配置类`DataSourceFactory.java`, 手动配置多数据源
#### 2. 手动配置多数据源
创建多数据源配置类 `DataSourceFactory.java`, 手动配置多数据源:
+ 这里我们创建 druid 数据源的时候,创建的是 `DruidXADataSource`,它继承自 `DruidDataSource ` 并支持 XA 分布式事务;
+ 使用 `AtomikosDataSourceBean` 包装我们创建的 `DruidXADataSource`,使得数据源能够被 JTA 事务管理器管理;
+ 这里我们使用的 sqlSessionTemplate 是我们重写的 `CustomSqlSessionTemplate`,原生的 sqlSessionTemplate 是不能实现在一个事务中实现数据源切换的。(为了不占用篇幅,我会在后文再给出详细的原因分析)
+ 这里我们使用的 SqlSessionTemplate 是我们重写的 `CustomSqlSessionTemplate`,原生的 SqlSessionTemplate 并不支持在同一个事务中切换数据源。(为了不占用篇幅,我会在后文再给出详细的原因分析)
```java
/**
@ -312,9 +316,9 @@ public class DataSourceFactory {
}
```
#### 3. 自定义sqlSessionTemplate的主要实现逻辑
#### 3. 自定义 SqlSessionTemplate
这里主要覆盖重写了 sqlSessionTemplate 的 getSqlSessionFactory从 ThreadLocal 去获取实际使用的数据源AOP 切面将实际使用的数据源存入 ThreadLocal
这里主要覆盖重写了 SqlSessionTemplate 的 getSqlSessionFactory从 ThreadLocal 去获取实际使用的数据源( AOP 切面将实际使用的数据源存入 ThreadLocal
```java
/***
@ -373,11 +377,11 @@ private class SqlSessionInterceptor implements InvocationHandler {
}
```
#### 4. 使用AOP动态切换数据源将当前使用的数据源名称保存到线程隔离的ThreadLocal中
#### 4. AOP 动态切换数据源
这里我们直接对 dao 层接口进行切面,如果第一个参数指明需要使用哪一个数据源,就使用对应的数据源,如果没有指定,就使用默认的数据源。
使用 AOP 动态切换数据源,将当前使用的数据源名称保存到线程隔离的 ThreadLocal 中 。这里我们直接对 dao 层接口进行切面,如果第一个参数指明需要使用哪一个数据源,就使用对应的数据源,如果没有指定,就使用默认的数据源。
注:使用切面来切换数据源是一种实现思路,而具体如何定义切入点可以按照自己的实际情况来定,你可以使用第一个参数指明数据源,也可以自定义注解来指定数据源,这个按照自己的实际使用方便来实现即可。
使用切面来切换数据源是一种实现思路,而具体如何定义切入点可以按照自己的实际情况来定,你可以使用第一个参数指明数据源,也可以自定义注解来指定数据源,这个按照自己的实际使用方便来实现即可。
```java
@Aspect
@ -466,12 +470,11 @@ public class XATransactionManagerConfig {
## 三、整合结果测试
## 三、测试整合结果
这里我一共给了三种情况的测试接口,如下:
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/springboot-druid-mybatis-multi-test.png"/> </div>
### 3.1 测试数据库整合结果
这里我在 mysql 和 mysql02 的表中分别插入了一条数据:
@ -479,22 +482,18 @@ public class XATransactionManagerConfig {
mysql 数据库:
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/mysql01.png"/> </div>
mysql02 数据库:
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/mysql02.png"/> </div>
**前端查询结果**
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/mysql0102.png"/> </div>
### 3.2 测试单数据库事务
这里因为没有复杂的业务逻辑,我直接将@Transactional 加载 controller 层,实际中最好加到 service 层
这里因为没有复杂的业务逻辑,我直接将 @Transactional 加在 Controller 层,实际中最好加到 Service 层:
```java
/**
@ -565,28 +564,23 @@ public class XATransactionController {
}
```
### 3.4 测试druid数据源是否整合成功
### 3.4 测试 Druid 数据源
访问 http://localhost:8080/druid/index.html ,可以在数据源监控页面看到两个数据源已配置成功,同时配置都与我们在 yml 配置文件中的一致。
访问 http://localhost:8080/druid/index.html ,可以在数据源监控页面看到两个数据源已配置成功,同时参数也与我们在 yml 中配置的完全一致。
数据源 1
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/druid-mysql01.png"/> </div>
数据源 2
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/durud-mysql02.png"/> </div>
url 监控情况:
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/durid-mysql-weburl.png"/> </div>
## 四、JTA与两阶段提交
解释一下本用例中涉及到的相关概念。
@ -601,8 +595,6 @@ XA 是由 X/Open 组织提出的分布式事务的规范。XA 规范主要定义
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/XA.gif"/> </div>
### 4.2 两阶段提交
分布式事务必须满足传统事务的特性,即原子性,一致性,分离性和持久性。但是分布式事务处理过程中,某些节点 (Server) 可能发生故障,或 者由于网络发生故障而无法访问到某些节点。为了防止分布式系统部分失败时产生数据的不一致性。在分布式事务的控制中采用了两阶段提交协议Two- Phase Commit Protocol。即事务的提交分为两个阶段
@ -612,12 +604,11 @@ XA 是由 X/Open 组织提出的分布式事务的规范。XA 规范主要定义
两阶段提交用来协调参与一个更新中的多个服务器的活动,以防止分布式系统部分失败时产生数据的不一致性。例如,如果一个更新操作要求位于三个不同结点上的记录被改变,且其中只要有一个结点失败,另外两个结点必须检测到这个失败并取消它们所做的改变。为了支持两阶段提交,一个分布式更新事务中涉及到的服务器必须能够相互通信。一般来说一个服务器会被指定为"控制"或"提交"服务器并监控来自其它服务器的信息。
在分布式更新期间,各服务器首先标志它们已经完成(但未提交)指定给它们的分布式事务的那一部分,并准备提交(以使它们的更新部分成为永久性的)。这是 两阶段提交的第一阶段。如果有一结点不能响应,那么控制服务器要指示其它结点撤消分布式事务的各个部分的影响。如果所有结点都回答准备好提交,控制服务器 则指示它们提交并等待它们的响应。等待确认信息阶段是第二阶段。在接收到可以提交指示后,每个服务器提交分布式事务中属于自己的那一部分,并给控制服务器 发回提交完成信息。
在分布式更新期间,各服务器首先标志它们已经完成(但未提交)指定给它们的分布式事务的那一部分,并准备提交(以使它们的更新部分成为永久性的)。这是 两阶段提交的第一阶段。如果有一结点不能响应,那么控制服务器要指示其它结点撤消分布式事务的各个部分的影响。如果所有结点都回答准备好提交,控制服务器则指示它们提交并等待它们的响应。等待确认信息阶段是第二阶段。在接收到可以提交指示后,每个服务器提交分布式事务中属于自己的那一部分,并给控制服务器 发回提交完成信息。
在一个分布式事务中,必须有一个场地的 Server 作为协调者 (coordinator),它能向 其它场地的 Server 发出请求,并对它们的回答作出响应,由它来控制一个分布式事务的提交或撤消。该分布式事务中涉及到的其它场地的 Server 称为参与者 (Participant)。
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/commit.png"/> </div>
事务两阶段提交的过程如下:
**第一阶段**
@ -644,7 +635,7 @@ XA 是由 X/Open 组织提出的分布式事务的规范。XA 规范主要定义
<br>
本小结的表述引用自博客[浅谈分布式事务](https://www.cnblogs.com/baiwa/p/5328722.html)
本小结的表述引用自博客[浅谈分布式事务](https://www.cnblogs.com/baiwa/p/5328722.html)
@ -652,19 +643,18 @@ XA 是由 X/Open 组织提出的分布式事务的规范。XA 规范主要定义
### 5.1 事务下多数据源无法切换
这里是主要是对上文提到为什么不重写 sqlSessionTemplate 会导致在事务下数据源切换失败的补充,我们先看看 sqlSessionTemplate 源码中关于该类的定义:
这里是主要是对上文提到为什么不重写 SqlSessionTemplate 会导致在事务下数据源切换失败的补充,我们先看看 sqlSessionTemplate 源码中关于该类的定义:
> sqlSessionTemplate 与 Spring 事务管理一起使用,以确保使用的实际 SqlSession 是与当前 Spring 事务关联的,此外它还管理会话生命周期,包括根据 Spring 事务配置根据需要关闭,提交或回滚会话
> sqlSessionTemplate 与 Spring 事务管理一起使用,以确保使用的实际 SqlSession 是与当前 Spring 事务关联的,此外它还管理会话生命周期,包括根据 Spring 事务配置根据需要关闭,提交或回滚会话
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/sqlSessionTemplate.png"/> </div>
这里最主要的是说明 SqlSession 是与当前是 Spring 事务是关联的。
这里最主要的是说明 sqlSession 是与当前是 spring 事务是关联的。
#### 1. SqlSession与事务关联导致问题
#### 1. sqlSession与事务关联导致问题
对于 Mybatis 来说,是默认开启一级缓存的,一级缓存是 Session 级别的,对于同一个 Session 如果是相同的查询语句并且查询参数都相同,第二次的查询就直接从一级缓存中获取。
对于 mybatis 来说,是默认开启一级缓存的,一级缓存是 session 级别的,对于同一个 session 如果是相同的查询语句并且查询参数都相同,第二次的查询就直接从一级缓存中获取。
这也就是说,对于如下的情况,由于 sqlSession 是与事务绑定的,如果使用原生 sqlSessionTemplate则第一次查询和第二次查询都是用的同一个 sqlSession那么第二个查询数据库 2 的查询语句根本不会执行,会直接从一级缓存中获取查询结果。两次查询得到都是第一次查询的结果。
这也就是说,对于如下的情况,由于 SqlSession 是与事务绑定的,如果使用原生 SqlSessionTemplate则第一次查询和第二次查询都是用的同一个 SqlSession那么第二个查询 数据库2 的查询语句根本不会执行,会直接从一级缓存中获取查询结果。两次查询得到都是第一次查询的结果。
```java
@GetMapping("ts/db/programmers")
@ -678,11 +668,11 @@ public List<Programmer> getAllProgrammers() {
#### 2. 连接的复用导致无法切换数据源
#### 2. 连接的复用导致无法切换数据源
先说一下为什么会出现连接的复用:
我们可以在 spring 的源码中看到 spring 在通过 `DataSourceUtils` 类中去获取新的连接 `doGetConnection` 的时候,会通过 `TransactionSynchronizationManager.getResource(dataSource)` 方法去判断当前数据源是否有可用的连接,如果有就直接返回,如果没有就通过 `fetchConnection` 方法去获取。
我们可以在 Spring 的源码中看到 Spring 在通过 `DataSourceUtils` 类中去获取新的连接 `doGetConnection` 的时候,会通过 `TransactionSynchronizationManager.getResource(dataSource)` 方法去判断当前数据源是否有可用的连接,如果有就直接返回,如果没有就通过 `fetchConnection` 方法去获取。
```java
public static Connection doGetConnection(DataSource dataSource) throws SQLException {
@ -737,28 +727,20 @@ public static Connection doGetConnection(DataSource dataSource) throws SQLExcept
这里主要的问题是 `TransactionSynchronizationManager.getResource(dataSource)` 中 dataSource 参数是在哪里进行注入的,这里可以沿着调用堆栈往上寻找,可以看到是在这个参数是 `SpringManagedTransaction` 类中获取连接的时候传入的。
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/opneConnection.png"/> </div>
`SpringManagedTransaction` 这类中的 dataSource 是如何得到赋值的,这里可以进入这个类中查看,只有在创建这个类的时候通过构造器为 dataSource 赋值,那么是哪个方法创建了 `SpringManagedTransaction`?
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/springManagerTransaction.png"/> </div>
在构造器上打一个断点,沿着调用的堆栈往上寻找可以看到是 `DefaultSqlSessionFactory` 在创建 `SpringManagedTransaction` 中传入的,**这个数据源就是创建 sqlSession 的 `sqlSessionFactory` 中数据源**。
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/DefaultSqlSessionFactory.png"/> </div>
**这里说明连接的复用是与我们创建 sqlSession 时候传入的 sqlSessionFactory 是否是同一个有关**。
**这里说明连接的复用是与我们创建 SqlSession 时候传入的 SqlSessionFactory 是否是同一个有关**。
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/getsqlSession.png"/> </div>
所以我们才重写了 sqlSessionTemplate 中的 `getSqlSession` 方法,获取 sqlSession 时候传入正在使用的数据源对应的 `sqlSessionFactory`,这样即便在同一个的事务中,由于传入的 `sqlSessionFactory` 中不同,就不会出现连接复用。
所以我们才重写了 SqlSessionTemplate 中的 `getSqlSession` 方法,获取 SqlSession 时候传入正在使用的数据源对应的 `SqlSessionFactory`,这样即便在同一个的事务中,由于传入的 `SqlSessionFactory` 中不同,就不会出现连接复用。
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/customSqlSessionTemplate.png"/> </div>
关于 mybati-spring 的更多事务处理机制,推荐阅读博客[mybatis-spring 事务处理机制分析](https://my.oschina.net/fifadxj/blog/785621)
关于 Mybati-Spring 的更多事务处理机制,推荐阅读博客:[mybatis-spring 事务处理机制分析](https://my.oschina.net/fifadxj/blog/785621)
@ -779,7 +761,7 @@ private SqlSessionFactory createSqlSessionFactory(DataSource dataSource) throws
}
```
上面这段代码没有任何编译问题,导致这个错误不容易发现,但是在调用 sql 时候就会出现异常。原因是 `factoryBean.getObject()` 方法被调用时就已经创建了 SqlSessionFactory并且 SqlSessionFactory 只会被创建一次。此时还没有指定 sql 文件的位置,导致 mybatis 无法将接口与 xml 中的 sql 语句进行绑定,所以出现 BindingExceptionInvalid 绑定异常。
上面这段代码没有任何编译问题,导致这个错误不容易发现,但是在调用 SQL 时候就会出现异常。原因是 `factoryBean.getObject()` 方法被调用时就已经创建了 SqlSessionFactory并且 SqlSessionFactory 只会被创建一次。此时还没有指定 SQL 文件的位置,导致 Mybatis 无法将接口与 XML 中的 SQL 语句进行绑定,所以出现 BindingExceptionInvalid 绑定异常。
```java
@Override
@ -792,12 +774,11 @@ private SqlSessionFactory createSqlSessionFactory(DataSource dataSource) throws
}
```
正常绑定的情况下,我们是可以在 sqlSessionFactory 中查看到绑定好的查询接口:
正常绑定的情况下,我们是可以在 SqlSessionFactory 中查看到绑定好的查询接口:
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/sqlSessionFactory.png"/> </div>
<br>
## 参考资料
## 参考资料
+ [浅谈分布式事务](https://www.cnblogs.com/baiwa/p/5328722.html)