所有图片使用github图床
@ -6,9 +6,6 @@ tags=["java", "spring"]
|
|||||||
category="java"
|
category="java"
|
||||||
serie="spring学习"
|
serie="spring学习"
|
||||||
---
|
---
|
||||||
[id]:2018-08-12_1
|
|
||||||
[type]:javaee
|
|
||||||
[tag]:java,spring
|
|
||||||
|
|
||||||
  spring 是为了解决企业级应用开发的复杂性而创建的,spring 最根本的使命是:简化 Java 开发。为降低开发复杂性有以下四种关键策略。
|
  spring 是为了解决企业级应用开发的复杂性而创建的,spring 最根本的使命是:简化 Java 开发。为降低开发复杂性有以下四种关键策略。
|
||||||
|
|
||||||
@ -119,7 +116,7 @@ scope可选值:
|
|||||||
#### 8.装配集合
|
#### 8.装配集合
|
||||||
|
|
||||||
| 集合元素 | 用途 |
|
| 集合元素 | 用途 |
|
||||||
| ---------------- | ------------------------------ |
|
| --------- | -------------------------------- |
|
||||||
| \<list\> | 装配 list 类型,允许重复 |
|
| \<list\> | 装配 list 类型,允许重复 |
|
||||||
| \<set\> | set,不能重复 |
|
| \<set\> | set,不能重复 |
|
||||||
| \<map\> | map 类型 |
|
| \<map\> | map 类型 |
|
||||||
@ -159,7 +156,7 @@ scope可选值:
|
|||||||
entry 元素由一个 key,一个 value 组成,分别有两种形式。
|
entry 元素由一个 key,一个 value 组成,分别有两种形式。
|
||||||
|
|
||||||
| key | 键为 String |
|
| key | 键为 String |
|
||||||
| :-------- | -------------- |
|
| :-------- | ---------------- |
|
||||||
| key-ref | 键为 Bean 的引用 |
|
| key-ref | 键为 Bean 的引用 |
|
||||||
| value | 值为 String |
|
| value | 值为 String |
|
||||||
| value-ref | 值为 Bean 的引用 |
|
| value-ref | 值为 Bean 的引用 |
|
||||||
@ -179,4 +176,3 @@ scope可选值:
|
|||||||
```xml
|
```xml
|
||||||
<property name="name"><null/></property>
|
<property name="name"><null/></property>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -6,18 +6,19 @@ tags=["java", "spring"]
|
|||||||
category="java"
|
category="java"
|
||||||
serie="spring学习"
|
serie="spring学习"
|
||||||
---
|
---
|
||||||
|
|
||||||
## 一、自动装配
|
## 一、自动装配
|
||||||
|
|
||||||
### 1、四种类型的自动装配
|
### 1、四种类型的自动装配
|
||||||
|
|
||||||
| 类型 | 解释 | xml 配置 |
|
| 类型 | 解释 | xml 配置 |
|
||||||
| ---------- | ------------------------------------ | ---------------------------------------------- |
|
| ---------- | -------------------------------------- | ---------------------------------------------- |
|
||||||
| byName | 根据 Bean 的 name 或者 id | \<bean id="bean" class="…" autowire="byName"/> |
|
| byName | 根据 Bean 的 name 或者 id | \<bean id="bean" class="…" autowire="byName"/> |
|
||||||
| ByType | 根据 Bean 类型自动装配 | \<bean id="bean" class="…" autowire="byType"/> |
|
| ByType | 根据 Bean 类型自动装配 | \<bean id="bean" class="…" autowire="byType"/> |
|
||||||
| contructor | 根据 Bean 的构造器入参具有相同类型 | 同上 |
|
| contructor | 根据 Bean 的构造器入参具有相同类型 | 同上 |
|
||||||
| Autodetect | 首先使用 contructor,失败再尝试 byType | 同上 |
|
| Autodetect | 首先使用 contructor,失败再尝试 byType | 同上 |
|
||||||
|
|
||||||
  byType在出现多个匹配项时不会自动选择一个然是报错,为避免报错,有两种办法:1.使用\<bean>元素的primary属性,设置为首选Bean,但所有bean的默认primary都是true,因此我们需要将所有非首选Bean设置为false;2.将Bean的`autowire-candidate`熟悉设置为**false **,取消 这个Bean的候选资格,这个Bean便不会自动注入了。
|
  byType 在出现多个匹配项时不会自动选择一个然是报错,为避免报错,有两种办法:1.使用\<bean>元素的 primary 属性,设置为首选 Bean,但所有 bean 的默认 primary 都是 true,因此我们需要将所有非首选 Bean 设置为**false**;2.将 Bean 的`autowire-candidate`熟悉设置为**false**,取消 这个 Bean 的候选资格,这个 Bean 便不会自动注入了。
|
||||||
|
|
||||||
  contructor 自动装配和 byType 有一样的局限性,当发现多个 Bean 匹配某个构造器入参时,Spring 不会尝试选择其中一个;此外,如果一个类有多个构造器都满足自动装配的条件,Spring 也不会猜测哪个更合适使用。
|
  contructor 自动装配和 byType 有一样的局限性,当发现多个 Bean 匹配某个构造器入参时,Spring 不会尝试选择其中一个;此外,如果一个类有多个构造器都满足自动装配的条件,Spring 也不会猜测哪个更合适使用。
|
||||||
|
|
||||||
@ -161,7 +162,7 @@ private String name;
|
|||||||
开启后支持如下注解:
|
开启后支持如下注解:
|
||||||
|
|
||||||
| 注解 | 解释 |
|
| 注解 | 解释 |
|
||||||
| ----------- | ------------------------------------ |
|
| ----------- | -------------------------------------- |
|
||||||
| @Component | 通用的构造型注解,标识类为 Spring 组件 |
|
| @Component | 通用的构造型注解,标识类为 Spring 组件 |
|
||||||
| @Controller | 标识该类定义为 Spring MVC controller |
|
| @Controller | 标识该类定义为 Spring MVC controller |
|
||||||
| @Repository | 标识该类定义为数据仓库 |
|
| @Repository | 标识该类定义为数据仓库 |
|
||||||
@ -171,7 +172,7 @@ private String name;
|
|||||||
|
|
||||||
### 1、过滤组建扫描
|
### 1、过滤组建扫描
|
||||||
|
|
||||||
  通过为<context:component-scan >配置<context:include-filter>和<context:exclude-filter>子元素,我们可以随意调整扫描行为。下面的配置自动注册所有的TestInterface实现类:
|
  通过为\<context:component-scan>配置<context:include-filter>和<context:exclude-filter>子元素,我们可以随意调整扫描行为。下面的配置自动注册所有的 TestInterface 实现类:
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<context:component-scan base-package="com.fxb.springtest">
|
<context:component-scan base-package="com.fxb.springtest">
|
||||||
@ -183,7 +184,7 @@ private String name;
|
|||||||
其中的 type 和 expression 属性一起协作来定义组件扫描策略。type 有以下值可选择:
|
其中的 type 和 expression 属性一起协作来定义组件扫描策略。type 有以下值可选择:
|
||||||
|
|
||||||
| 过滤器类型 | 描述 |
|
| 过滤器类型 | 描述 |
|
||||||
| ---------- | ------------------------------------------------------------ |
|
| ---------- | ---------------------------------------------------------------------------------------- |
|
||||||
| annotation | 过滤器扫描使用指定注解所标注的类。通过 expression 属性指定要扫描的注解 |
|
| annotation | 过滤器扫描使用指定注解所标注的类。通过 expression 属性指定要扫描的注解 |
|
||||||
| assignable | 过滤器扫描派生于 expression 属性所指定类型的那些类 |
|
| assignable | 过滤器扫描派生于 expression 属性所指定类型的那些类 |
|
||||||
| aspectj | 过滤器扫描于 expression 属性所指定的 AspectJ 表达式所匹配的那些类 |
|
| aspectj | 过滤器扫描于 expression 属性所指定的 AspectJ 表达式所匹配的那些类 |
|
||||||
|
@ -7,7 +7,6 @@ category="java"
|
|||||||
serie="spring学习"
|
serie="spring学习"
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
  Spring 的基础是 IOC 和 AOP,前面两节对 IOC 和 DI 做了简单总结,这里再对 AOP 进行一个学习总结,Spring 基础就算有一个初步了解了。
|
  Spring 的基础是 IOC 和 AOP,前面两节对 IOC 和 DI 做了简单总结,这里再对 AOP 进行一个学习总结,Spring 基础就算有一个初步了解了。
|
||||||
|
|
||||||
## 一.面向切面编程
|
## 一.面向切面编程
|
||||||
@ -16,13 +15,13 @@ serie="spring学习"
|
|||||||
|
|
||||||
横切关注点可以被描述为影响应用多处的功能,切面能够帮助我们模块化横切关注点。下图直观呈现了横切关注点的概念:
|
横切关注点可以被描述为影响应用多处的功能,切面能够帮助我们模块化横切关注点。下图直观呈现了横切关注点的概念:
|
||||||
|
|
||||||
![横切关注点](./picFolder/切面示例.png)
|
![横切关注点](https://raw.githubusercontent.com/FleyX/files/master/blogImg/%E9%9D%A2%E5%90%91%E5%88%87%E9%9D%A2%E7%9A%84spring/20190107100126.png)
|
||||||
|
|
||||||
途中CourseService,StudentService,MiscService都需要类似安全、事务这样的辅助功能,这些辅助功能就被称为横切关注点。
|
图中 CourseService,StudentService,MiscService 都需要类似安全、事务这样的辅助功能,这些辅助功能就被称为横切关注点。
|
||||||
|
|
||||||
  **继承**和**委托**是最常见的实现重用通用功能的面向对象技术。但是如果在整个程序中使用相同的基类继承往往会导致一个脆弱的对象体系;而使用委托可能需要对委托对象进行复杂的调用。
|
  **继承**和**委托**是最常见的实现重用通用功能的面向对象技术。但是如果在整个程序中使用相同的基类继承往往会导致一个脆弱的对象体系;而使用委托可能需要对委托对象进行复杂的调用。
|
||||||
|
|
||||||
切面提供了取代继承和委托的另一种选择,而且更加清晰简洁。在面向切面编程时,我们任然在一个地方定义通用功能,但是我们可以通过声明的方式定义这个功能以何种方式在何处应用,而无需修改受影响的类,受影响类完全感受不到切面的存在。
|
  切面提供了取代继承和委托的另一种选择,而且更加清晰简洁。在面向切面编程时,我们任然在一个地方定义通用功能,但是我们可以通过声明的方式定义这个功能以何种方式在何处应用,而无需修改受影响的类,受影响类完全感受不到切面的存在。
|
||||||
|
|
||||||
## 二.AOP 常用术语
|
## 二.AOP 常用术语
|
||||||
|
|
||||||
@ -73,7 +72,7 @@ serie="spring学习"
|
|||||||
  在 SpringAOP 中,需要使用 AspectJ 的切点表达式语言来定义切点。Spring 只支持 AspectJ 的部分切点指示器,如下表所示:
|
  在 SpringAOP 中,需要使用 AspectJ 的切点表达式语言来定义切点。Spring 只支持 AspectJ 的部分切点指示器,如下表所示:
|
||||||
|
|
||||||
| AspectJ 指示器 | 描述 |
|
| AspectJ 指示器 | 描述 |
|
||||||
| ------------- | ------------------------------------------------------------ |
|
| -------------- | --------------------------------------------------------------------------------------------- |
|
||||||
| arg() | 限制连接点匹配参数为指定类型的执行方法 |
|
| arg() | 限制连接点匹配参数为指定类型的执行方法 |
|
||||||
| @args() | 限制连接点匹配参数由指定注解标注的执行方法 |
|
| @args() | 限制连接点匹配参数由指定注解标注的执行方法 |
|
||||||
| execution() | 用于匹配是连接点的执行方法 |
|
| execution() | 用于匹配是连接点的执行方法 |
|
||||||
@ -97,9 +96,9 @@ serie="spring学习"
|
|||||||
execution(* com.test.Hello.sayHello(..))
|
execution(* com.test.Hello.sayHello(..))
|
||||||
```
|
```
|
||||||
|
|
||||||
方法表达式以*** **号开始,说明不管方法返回值的类型。然后指定全限定类名和方法名。对于方法参数列表,我们使用(**)标识切点选择任意的sayHello()方法,无论方法入参是什么。
|
方法表达式以**\* **号开始,说明不管方法返回值的类型。然后指定全限定类名和方法名。对于方法参数列表,我们使用(\*\*)标识切点选择任意的 sayHello()方法,无论方法入参是什么。
|
||||||
|
|
||||||
  同时我们可以使用&&(and),||(or),!(not)来连接指示器,如下所示:
|
  同时我们可以使用 (and),||(or),!(not)来连接指示器,如下所示:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
execution(* com.test.Hello.sayHello(..)) and !bean(xiaobu)
|
execution(* com.test.Hello.sayHello(..)) and !bean(xiaobu)
|
||||||
@ -110,7 +109,7 @@ execution(* com.test.Hello.sayHello(..)) and !bean(xiaobu)
|
|||||||
  在经典 Spring AOP 中使用 ProxyFactoryBean 非常复杂,因此提供了申明式切面的选择,在 Spring 的 AOP 配置命名空间中有如下配置元素:
|
  在经典 Spring AOP 中使用 ProxyFactoryBean 非常复杂,因此提供了申明式切面的选择,在 Spring 的 AOP 配置命名空间中有如下配置元素:
|
||||||
|
|
||||||
| AOP 配置元素 | 描述 |
|
| AOP 配置元素 | 描述 |
|
||||||
| ------------------------------ | ----------------------------------------------------------- |
|
| ------------------------------ | -------------------------------------------------------------- |
|
||||||
| <aop:advisor > | 定义 AOP 通知器 |
|
| <aop:advisor > | 定义 AOP 通知器 |
|
||||||
| <aop:after > | 定义 AOP 后置通知(无论被通知方法是否执行成功) |
|
| <aop:after > | 定义 AOP 后置通知(无论被通知方法是否执行成功) |
|
||||||
| <aop:after-returning > | 定义 AOP after-returning 通知 |
|
| <aop:after-returning > | 定义 AOP after-returning 通知 |
|
||||||
@ -119,7 +118,7 @@ execution(* com.test.Hello.sayHello(..)) and !bean(xiaobu)
|
|||||||
| <aop:aspect > | 定义切面 |
|
| <aop:aspect > | 定义切面 |
|
||||||
| <aop:aspectj-autoproxy > | 启用@AspectJ 注解驱动的切面 |
|
| <aop:aspectj-autoproxy > | 启用@AspectJ 注解驱动的切面 |
|
||||||
| <aop:before > | 定义 AOP 前置通知 |
|
| <aop:before > | 定义 AOP 前置通知 |
|
||||||
| <aop:config > | 顶层的AOP配置元素。大多数的<aop:* >元素必须包含在其中 |
|
| <aop:config > | 顶层的 AOP 配置元素。大多数的<aop:\* >元素必须包含在其中 |
|
||||||
| <aop:declare-parents > | 为被通知的对象引入额外的接口,并透明的实现 |
|
| <aop:declare-parents > | 为被通知的对象引入额外的接口,并透明的实现 |
|
||||||
| <aop:pointcut > | 定义切点 |
|
| <aop:pointcut > | 定义切点 |
|
||||||
|
|
||||||
@ -176,8 +175,6 @@ public class Audience{
|
|||||||
</aop:config>
|
</aop:config>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#### b、注解实现
|
#### b、注解实现
|
||||||
|
|
||||||
直接在 Audience 类上加注解(Aspect 注解并不能被 spring 自动发现并注册,要么写到 xml 中,要么使用@Aspectj 注解或者加一个@Component 注解),如下所示:
|
直接在 Audience 类上加注解(Aspect 注解并不能被 spring 自动发现并注册,要么写到 xml 中,要么使用@Aspectj 注解或者加一个@Component 注解),如下所示:
|
||||||
@ -221,7 +218,7 @@ public class Audience{
|
|||||||
|
|
||||||
  既然可以用 AOP 为对象拥有的方法添加新功能,那为什么不能为对象增加新的方法呢?利用被称为**引入**的 AOP 概念,切面可以为 Spring Bean 添加新的方法,示例图如下:
|
  既然可以用 AOP 为对象拥有的方法添加新功能,那为什么不能为对象增加新的方法呢?利用被称为**引入**的 AOP 概念,切面可以为 Spring Bean 添加新的方法,示例图如下:
|
||||||
|
|
||||||
![引入](./picFolder/引入新功能.png)
|
![引入](https://raw.githubusercontent.com/FleyX/files/master/blogImg/%E9%9D%A2%E5%90%91%E5%88%87%E9%9D%A2%E7%9A%84spring/20190107100233.png)
|
||||||
|
|
||||||
当引入接口的方法被调用时,代理将此调用委托给实现了新接口的某个其他对象。实际上,Bean 的实现被拆分到了多个类。
|
当引入接口的方法被调用时,代理将此调用委托给实现了新接口的某个其他对象。实际上,Bean 的实现被拆分到了多个类。
|
||||||
|
|
||||||
@ -246,4 +243,3 @@ public class Audience{
|
|||||||
```
|
```
|
||||||
|
|
||||||
同 xml 实现一样,注解也由三部分组成:1、value 属性相当于 tpes-matching 属性,标识被增强的类;2、defaultImpl 等同于 default-imple,指定接口的实现类;3、有@DeclareParents 注解所标注的 static 属性指定了将被引入的接口。
|
同 xml 实现一样,注解也由三部分组成:1、value 属性相当于 tpes-matching 属性,标识被增强的类;2、defaultImpl 等同于 default-imple,指定接口的实现类;3、有@DeclareParents 注解所标注的 static 属性指定了将被引入的接口。
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 41 KiB |
Before Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 45 KiB |
Before Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 15 KiB |
@ -11,13 +11,13 @@ serie="spring boot学习"
|
|||||||
|
|
||||||
### 1.选择 spring initializr
|
### 1.选择 spring initializr
|
||||||
|
|
||||||
![1532967570728](./picFolder/1532967570728.png)
|
![选择spring initializr](https://raw.githubusercontent.com/FleyX/files/master/blogImg/springboot%E6%90%AD%E5%BB%BA/20190107100435.png)
|
||||||
|
|
||||||
next
|
next
|
||||||
|
|
||||||
#### 2.设置参数
|
#### 2.设置参数
|
||||||
|
|
||||||
![1532967772110](./picFolder/1532967772110.png)
|
![设置参数](https://raw.githubusercontent.com/FleyX/files/master/blogImg/springboot%E6%90%AD%E5%BB%BA/20190107100509.png)
|
||||||
|
|
||||||
next
|
next
|
||||||
|
|
||||||
@ -25,13 +25,13 @@ next
|
|||||||
|
|
||||||
  在这里选择 spring boot 版本和 web 依赖(忽略 sql 的依赖,如有需要[点击这里](f),单独将 mybatis 的整合),后面也可手动编辑 pom 文件修改增加删除依赖
|
  在这里选择 spring boot 版本和 web 依赖(忽略 sql 的依赖,如有需要[点击这里](f),单独将 mybatis 的整合),后面也可手动编辑 pom 文件修改增加删除依赖
|
||||||
|
|
||||||
![1532967938985](./picFolder/1532967938985.png)
|
![依赖选择](https://raw.githubusercontent.com/FleyX/files/master/blogImg/springboot%E6%90%AD%E5%BB%BA/20190107100609.png)
|
||||||
|
|
||||||
这里我们选择 web 搭建一个简单的 REST 风格 demo。然后 next。
|
这里我们选择 web 搭建一个简单的 REST 风格 demo。然后 next。
|
||||||
|
|
||||||
#### 4.设置项目存放地址
|
#### 4.设置项目存放地址
|
||||||
|
|
||||||
![1532968024509](./picFolder/1532968024509.png)
|
![设置项目存放地址](https://raw.githubusercontent.com/FleyX/files/master/blogImg/springboot%E6%90%AD%E5%BB%BA/20190107100653.png)
|
||||||
|
|
||||||
这样就成功构建了一个 springboot 项目。
|
这样就成功构建了一个 springboot 项目。
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ next
|
|||||||
|
|
||||||
  现在新建一个 controller 包,包下新建一个 HelloController,创建之后项目目录结构如下:
|
  现在新建一个 controller 包,包下新建一个 HelloController,创建之后项目目录结构如下:
|
||||||
|
|
||||||
![1532969025023](./picFolder/1532969025023.png)
|
![项目目录结构](https://raw.githubusercontent.com/FleyX/files/master/blogImg/springboot%E6%90%AD%E5%BB%BA/20190107100803.png)
|
||||||
|
|
||||||
HelloController 代码如下:
|
HelloController 代码如下:
|
||||||
|
|
||||||
@ -54,4 +54,4 @@ public class HelloController{
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
然后运行项目,访问 localhost:8080/home/hello 即可看到 hello 字符串。
|
然后运行项目,访问 [localhost:8080/home/hello](localhost:8080/home/hello) 即可看到 hello 字符串。
|
||||||
|
Before Width: | Height: | Size: 81 KiB |
Before Width: | Height: | Size: 54 KiB |
@ -7,7 +7,7 @@ category="java"
|
|||||||
serie="spring boot学习"
|
serie="spring boot学习"
|
||||||
---
|
---
|
||||||
|
|
||||||
**说明 springboot 版本 2.0.3<br/>项目地址:[点击跳转](https://github.com/FleyX/demo-project/tree/master/springboot_spirngsecurity_demo)**
|
**说明 springboot 版本 2.0.3<br/>源码地址:[点击跳转](https://github.com/FleyX/demo-project/tree/master/springboot_spirngsecurity_demo)**
|
||||||
|
|
||||||
## 一、 介绍
|
## 一、 介绍
|
||||||
|
|
||||||
@ -77,7 +77,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
|||||||
|
|
||||||
#### 2、 个性化登录,security 中的登录如下:
|
#### 2、 个性化登录,security 中的登录如下:
|
||||||
|
|
||||||
![登录过程](./picFolder/pic1.png)
|
![登录过程](https://raw.githubusercontent.com/FleyX/files/master/blogImg/springsecurity/20190107101026.png)
|
||||||
|
|
||||||
- security 需要一个 user 的实体类实现`UserDetails`接口,该实体类最后与系统中用户的实体类分开,代码如下:
|
- security 需要一个 user 的实体类实现`UserDetails`接口,该实体类最后与系统中用户的实体类分开,代码如下:
|
||||||
|
|
||||||
|
@ -6,15 +6,13 @@ tags=["java", "spring","springboot","spring-security","security"]
|
|||||||
category="java"
|
category="java"
|
||||||
serie="spring boot学习"
|
serie="spring boot学习"
|
||||||
---
|
---
|
||||||
[id]:2018-08-21
|
|
||||||
[type]:javaee
|
|
||||||
[tag]:java,spring,springsecurity,scurity
|
|
||||||
|
|
||||||
  紧接着上一篇,上一篇中登录验证都由 security 帮助我们完成了,如果我们想要增加一个验证码登录或者其它的自定义校验就没办法了,因此这一篇讲解如何实现这个功能。
|
  紧接着上一篇,上一篇中登录验证都由 security 帮助我们完成了,如果我们想要增加一个验证码登录或者其它的自定义校验就没办法了,因此这一篇讲解如何实现这个功能。
|
||||||
|
|
||||||
##一、 实现自定义登录校验类
|
##一、 实现自定义登录校验类
|
||||||
|
|
||||||
  继承 UsernamePasswordAuthenticationFilter 类来拓展登录校验,代码如下:
|
  继承 UsernamePasswordAuthenticationFilter 类来拓展登录校验,代码如下:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public class MyUsernamePasswordAuthentication extends UsernamePasswordAuthenticationFilter{
|
public class MyUsernamePasswordAuthentication extends UsernamePasswordAuthenticationFilter{
|
||||||
|
|
||||||
@ -39,6 +37,7 @@ public class MyUsernamePasswordAuthentication extends UsernamePasswordAuthentica
|
|||||||
|
|
||||||
##二、 将自定义登录配置到 security 中
|
##二、 将自定义登录配置到 security 中
|
||||||
  编写自定义登录过滤器后,configure Bean 修改为如下:
|
  编写自定义登录过滤器后,configure Bean 修改为如下:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
@Override
|
@Override
|
||||||
protected void configure(HttpSecurity http) throws Exception {
|
protected void configure(HttpSecurity http) throws Exception {
|
||||||
@ -84,7 +83,9 @@ public class MyUsernamePasswordAuthentication extends UsernamePasswordAuthentica
|
|||||||
.logoutSuccessHandler(myLogoutSuccessHandle);
|
.logoutSuccessHandler(myLogoutSuccessHandle);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
然后再编写 Bean,代码如下:
|
然后再编写 Bean,代码如下:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
@Bean
|
@Bean
|
||||||
public MyUsernamePasswordAuthentication myUsernamePasswordAuthentication(){
|
public MyUsernamePasswordAuthentication myUsernamePasswordAuthentication(){
|
||||||
@ -98,4 +99,5 @@ public MyUsernamePasswordAuthentication myUsernamePasswordAuthentication(){
|
|||||||
return myUsernamePasswordAuthentication;
|
return myUsernamePasswordAuthentication;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
完成。
|
完成。
|
@ -8,7 +8,8 @@ serie="spring boot学习"
|
|||||||
---
|
---
|
||||||
|
|
||||||
  这篇讲解如何自定义鉴权过程,实现根据数据库查询出的 url 和 method 是否匹配当前请求的 url 和 method 来决定有没有权限。security 鉴权过程如下:
|
  这篇讲解如何自定义鉴权过程,实现根据数据库查询出的 url 和 method 是否匹配当前请求的 url 和 method 来决定有没有权限。security 鉴权过程如下:
|
||||||
![鉴权流程](./picFolder/pic2.png)
|
|
||||||
|
![鉴权流程](https://raw.githubusercontent.com/FleyX/files/master/blogImg/springsecurity/20190107101130.png)
|
||||||
|
|
||||||
## 一、 重写 metadataSource 类
|
## 一、 重写 metadataSource 类
|
||||||
|
|
||||||
@ -173,6 +174,7 @@ public class MyAccessDecisionManager implements AccessDecisionManager{
|
|||||||
```
|
```
|
||||||
|
|
||||||
## 三、 编写 MyFilterSecurityInterceptor 类
|
## 三、 编写 MyFilterSecurityInterceptor 类
|
||||||
|
|
||||||
  该类继承 AbstractSecurityInterceptor 类,实现 Filter 接口,代码如下:
|
  该类继承 AbstractSecurityInterceptor 类,实现 Filter 接口,代码如下:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 87 KiB |
Before Width: | Height: | Size: 62 KiB |
Before Width: | Height: | Size: 117 KiB |
@ -98,9 +98,9 @@ serie="spring boot学习"
|
|||||||
|
|
||||||
然后依照上面的 pom 文件,补齐缺少的依赖。接着创建包 entity,service 和 mybatis 映射文件夹 mapper,创建。为了方便配置将 application.properties 改成 application.yml。由于我们时 REST 接口,故不需要 static 和 templates 目录。修改完毕后的项目结构如下:
|
然后依照上面的 pom 文件,补齐缺少的依赖。接着创建包 entity,service 和 mybatis 映射文件夹 mapper,创建。为了方便配置将 application.properties 改成 application.yml。由于我们时 REST 接口,故不需要 static 和 templates 目录。修改完毕后的项目结构如下:
|
||||||
|
|
||||||
![项目结构](./picFolder/pic1.png)
|
![项目结构](https://raw.githubusercontent.com/FleyX/files/master/blogImg/%E6%95%B0%E6%8D%AE%E5%BA%93/20190107101305.png)
|
||||||
|
|
||||||
修改启动类,增加`@MapperScan("com.example.mybatistest.dao")`,以自动扫描 dao 目录,避免每个 dao 都手动加`@Mapper`注解。代码如下:
|
  修改启动类,增加`@MapperScan("com.example.mybatistest.dao")`,以自动扫描 dao 目录,避免每个 dao 都手动加`@Mapper`注解。代码如下:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
@ -331,15 +331,15 @@ public class UserController {
|
|||||||
|
|
||||||
- 插入数据:
|
- 插入数据:
|
||||||
|
|
||||||
![插入](./picFolder/pic2.png)
|
![插入](https://raw.githubusercontent.com/FleyX/files/master/blogImg/%E6%95%B0%E6%8D%AE%E5%BA%93/20190107101358.png)
|
||||||
|
|
||||||
- 查询数据
|
- 查询数据
|
||||||
|
|
||||||
![查询](./picFolder/pic3.png)
|
![查询](https://raw.githubusercontent.com/FleyX/files/master/blogImg/%E6%95%B0%E6%8D%AE%E5%BA%93/20190107101412.png)
|
||||||
|
|
||||||
- 分页查询
|
- 分页查询
|
||||||
|
|
||||||
![分页查询](./picFolder/pic4.png)
|
![分页查询](https://raw.githubusercontent.com/FleyX/files/master/blogImg/%E6%95%B0%E6%8D%AE%E5%BA%93/20190107101608.png)
|
||||||
|
|
||||||
## 4.注解编写 sql
|
## 4.注解编写 sql
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 7.5 KiB |
Before Width: | Height: | Size: 82 KiB |
Before Width: | Height: | Size: 37 KiB |
@ -37,7 +37,8 @@ spring:
|
|||||||
### 2. 创建生产者消费者
|
### 2. 创建生产者消费者
|
||||||
|
|
||||||
  springboot 中 activeMQ 的默认配置为**生产-消费者模式**,还有一种模式为**发布-订阅模式**后面再讲。项目目录如下:
|
  springboot 中 activeMQ 的默认配置为**生产-消费者模式**,还有一种模式为**发布-订阅模式**后面再讲。项目目录如下:
|
||||||
![项目目录](./picFolder/pic1.png)
|
|
||||||
|
![项目目录](https://raw.githubusercontent.com/FleyX/files/master/blogImg/%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97/20190107101724.png)
|
||||||
|
|
||||||
  首先编写配置类 Config.java,代码如下
|
  首先编写配置类 Config.java,代码如下
|
||||||
|
|
||||||
@ -57,7 +58,8 @@ public class Config {
|
|||||||
```
|
```
|
||||||
|
|
||||||
上面的代码建立了两个消息队列 queue1,queue2,分别由 queue1 和 queue2 这两个 Bean 注入到 Spring 容器中。程序运行后会在 activeMQ 的管理页面->queue 中看到如下:
|
上面的代码建立了两个消息队列 queue1,queue2,分别由 queue1 和 queue2 这两个 Bean 注入到 Spring 容器中。程序运行后会在 activeMQ 的管理页面->queue 中看到如下:
|
||||||
![队列](./picFolder/pic2.png)
|
|
||||||
|
![队列](https://raw.githubusercontent.com/FleyX/files/master/blogImg/%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97/20190107101745.png)
|
||||||
|
|
||||||
  生产者 Producer.java 代码如下:
|
  生产者 Producer.java 代码如下:
|
||||||
|
|
||||||
@ -132,5 +134,7 @@ public class Comsumer {
|
|||||||
```
|
```
|
||||||
|
|
||||||
消息都成功被消费者消费,从打印结果也可看出生产者消费者的一个特点:一个消息只会被一个消费者消费。同时在管理页面中可以看到:
|
消息都成功被消费者消费,从打印结果也可看出生产者消费者的一个特点:一个消息只会被一个消费者消费。同时在管理页面中可以看到:
|
||||||
![运行结果](./picFolder/pic3.png)
|
|
||||||
|
![运行结果](https://raw.githubusercontent.com/FleyX/files/master/blogImg/%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97/20190107101808.png)
|
||||||
|
|
||||||
每个消息队列有两个消费者,队列进入了三个消息,出了三个消息,说明消息都被消费掉了,如果注释掉消费者代码,再次运行,然后发送消息就会发现 MessagesEnqueued 数量大于 MessagesDequeued,然后再让消费者上线会立即消费掉队列中的消息。
|
每个消息队列有两个消费者,队列进入了三个消息,出了三个消息,说明消息都被消费掉了,如果注释掉消费者代码,再次运行,然后发送消息就会发现 MessagesEnqueued 数量大于 MessagesDequeued,然后再让消费者上线会立即消费掉队列中的消息。
|
||||||
|
@ -6,14 +6,10 @@ tags=["java", "spring","springboot","消息队列","activeMQ"]
|
|||||||
category="java"
|
category="java"
|
||||||
serie="spring boot学习"
|
serie="spring boot学习"
|
||||||
---
|
---
|
||||||
[id]:2018-09-06
|
|
||||||
[type]:javaee
|
|
||||||
[tag]:java,spring,activemq
|
|
||||||
|
|
||||||
|
|
||||||
  单个 MQ 节点总是不可靠的,一旦该节点出现故障,MQ 服务就不可用了,势必会产生较大的损失。这里记录 activeMQ 如何开启主从备份,一旦 master(主节点故障),slave(从节点)立即提供服务,实现原理是运行多个 MQ 使用同一个持久化数据源,这里以 jdbc 数据源为例。同一时间只有一个节点(节点 A)能够抢到数据库的表锁,其他节点进入阻塞状态,一旦 A 发生错误崩溃,其他节点就会重新获取表锁,获取到锁的节点成为 master,其他节点为 slave,如果节点 A 重新启动,也将成为 slave。
|
  单个 MQ 节点总是不可靠的,一旦该节点出现故障,MQ 服务就不可用了,势必会产生较大的损失。这里记录 activeMQ 如何开启主从备份,一旦 master(主节点故障),slave(从节点)立即提供服务,实现原理是运行多个 MQ 使用同一个持久化数据源,这里以 jdbc 数据源为例。同一时间只有一个节点(节点 A)能够抢到数据库的表锁,其他节点进入阻塞状态,一旦 A 发生错误崩溃,其他节点就会重新获取表锁,获取到锁的节点成为 master,其他节点为 slave,如果节点 A 重新启动,也将成为 slave。
|
||||||
|
|
||||||
主从备份解决了单节点故障的问题,但是同一时间提供服务的只有一个master,显然是不能面对数据量的增长,所以需要一种横向拓展的集群方式来解决面临的问题。
|
  主从备份解决了单节点故障的问题,但是同一时间提供服务的只有一个 master,显然是不能面对数据量的增长,所以需要一种横向拓展的集群方式来解决面临的问题。
|
||||||
|
|
||||||
### 一、activeMQ 设置
|
### 一、activeMQ 设置
|
||||||
|
|
||||||
@ -65,9 +61,7 @@ serie="spring boot学习"
|
|||||||
</transportConnectors>
|
</transportConnectors>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
* 设置 jdbc 数据库
|
||||||
|
|
||||||
- 设置jdbc数据库
|
|
||||||
|
|
||||||
mysql 数据库中创建 activemq 库,在`broker`标签的下面也就是根标签`beans`的下一级创建一个 bean 节点,内容如下:
|
mysql 数据库中创建 activemq 库,在`broker`标签的下面也就是根标签`beans`的下一级创建一个 bean 节点,内容如下:
|
||||||
|
|
||||||
@ -81,7 +75,7 @@ serie="spring boot学习"
|
|||||||
</bean>
|
</bean>
|
||||||
```
|
```
|
||||||
|
|
||||||
- 设置数据源
|
* 设置数据源
|
||||||
|
|
||||||
首先修改 broker 节点,设置 name 和 persistent(默认为 true),也可不做修改,修改后如下:
|
首先修改 broker 节点,设置 name 和 persistent(默认为 true),也可不做修改,修改后如下:
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 44 KiB |
@ -42,7 +42,7 @@ serie="spring boot学习"
|
|||||||
|
|
||||||
然后重启数据库,使用`show master status;`语句查看主库状态,如下所示:
|
然后重启数据库,使用`show master status;`语句查看主库状态,如下所示:
|
||||||
|
|
||||||
![主库状态](./picFolder/pic1.png)
|
![主库状态](https://raw.githubusercontent.com/FleyX/files/master/blogImg/%E8%AF%BB%E5%86%99%E5%88%86%E7%A6%BB/20190107101953.png)
|
||||||
|
|
||||||
- 从库配置
|
- 从库配置
|
||||||
|
|
||||||
@ -68,7 +68,7 @@ serie="spring boot学习"
|
|||||||
|
|
||||||
接着运行`start slave;`开启备份,正常情况如下图所示:Slave_IO_Running 和 Slave_SQL_Running 都为 yes。
|
接着运行`start slave;`开启备份,正常情况如下图所示:Slave_IO_Running 和 Slave_SQL_Running 都为 yes。
|
||||||
|
|
||||||
![1536223020742](./picFolder/pic2.png)
|
![状态](https://raw.githubusercontent.com/FleyX/files/master/blogImg/%E8%AF%BB%E5%86%99%E5%88%86%E7%A6%BB/20190107102024.png)
|
||||||
|
|
||||||
可以用这个步骤开启多个从库。
|
可以用这个步骤开启多个从库。
|
||||||
|
|
||||||
@ -315,6 +315,6 @@ public class ReadOnlyInterceptor implements Ordered {
|
|||||||
|
|
||||||
  编写好代码来试试结果如何,下面是运行截图:
|
  编写好代码来试试结果如何,下面是运行截图:
|
||||||
|
|
||||||
![1536312274474](./picFolder/pic3.png)
|
![测试结果](https://raw.githubusercontent.com/FleyX/files/master/blogImg/%E8%AF%BB%E5%86%99%E5%88%86%E7%A6%BB/20190107102056.png)
|
||||||
|
|
||||||
  断断续续写了好几天终于是写完了,,,如果有帮助到你,,欢迎 star 哦,,这里是完整代码地址:[点击跳转](https://github.com/FleyX/demo-project/tree/master/dxfl)
|
  断断续续写了好几天终于是写完了,,,如果有帮助到你,,欢迎 star 哦,,这里是完整代码地址:[点击跳转](https://github.com/FleyX/demo-project/tree/master/dxfl)
|
||||||
|
@ -10,7 +10,9 @@ serie="springCloud实战"
|
|||||||
## 一、前言
|
## 一、前言
|
||||||
|
|
||||||
  在开发普通的 web 应用中,我们通常是将配置项写在单独的配置文件中,比如`application.yml`,`application.properties`,但是在微服务架构中,可能会出现数百个微服务,如果每个微服务将配置文件写在自身的配置文件中,会导致配置文件的管理非常复杂。因此集中式的配置管理是非常有必要的,每个服务启动时从集中式的存储库中读取需要的配置信息。其模型如下:
|
  在开发普通的 web 应用中,我们通常是将配置项写在单独的配置文件中,比如`application.yml`,`application.properties`,但是在微服务架构中,可能会出现数百个微服务,如果每个微服务将配置文件写在自身的配置文件中,会导致配置文件的管理非常复杂。因此集中式的配置管理是非常有必要的,每个服务启动时从集中式的存储库中读取需要的配置信息。其模型如下:
|
||||||
![配置管理概念架构](./picFolder/配置管理概念架构.png)
|
|
||||||
|
![配置管理概念架构](https://raw.githubusercontent.com/FleyX/files/master/blogImg/springcloud%E5%AE%9E%E6%88%98/20190107102213.png)
|
||||||
|
|
||||||
简单来说就是如下几点:
|
简单来说就是如下几点:
|
||||||
|
|
||||||
1. 启动一个微服务实例时向配置管理服务请求获取其所在环境的特定配置文件
|
1. 启动一个微服务实例时向配置管理服务请求获取其所在环境的特定配置文件
|
||||||
|
@ -17,7 +17,8 @@ serie="springCloud实战"
|
|||||||
4. 健康监测:服务如何将它的健康信息传回给服务发现代理?
|
4. 健康监测:服务如何将它的健康信息传回给服务发现代理?
|
||||||
|
|
||||||
下图展示了这 4 个概念的流程,以及在服务发现模式实现中通常发生的情况:
|
下图展示了这 4 个概念的流程,以及在服务发现模式实现中通常发生的情况:
|
||||||
![服务发现架构](./picFolder/服务发现架构.png)
|
|
||||||
|
![服务发现架构](https://raw.githubusercontent.com/FleyX/files/master/blogImg/springcloud%E5%AE%9E%E6%88%98/20190107102247.png)
|
||||||
|
|
||||||
  通常服务实例都只向一个服务发现实例注册,服务发现实例之间再通过数据传输,让每个服务实例注册到所有的服务发现实例中。
|
  通常服务实例都只向一个服务发现实例注册,服务发现实例之间再通过数据传输,让每个服务实例注册到所有的服务发现实例中。
|
||||||
  服务在向服务发现实例注册后,这个服务就能被服务消费者调用了。服务消费者可以使用多种模型来"发现"服务。
|
  服务在向服务发现实例注册后,这个服务就能被服务消费者调用了。服务消费者可以使用多种模型来"发现"服务。
|
||||||
@ -26,6 +27,7 @@ serie="springCloud实战"
|
|||||||
2. 更健壮的方法是使用所谓的客户端负载均衡。
|
2. 更健壮的方法是使用所谓的客户端负载均衡。
|
||||||
|
|
||||||
  如下图所示:
|
  如下图所示:
|
||||||
|
|
||||||
![客户端负载均衡](./picFolder/客户端负载均衡模型.png
|
![客户端负载均衡](./picFolder/客户端负载均衡模型.png
|
||||||
  在这个模型中,当服务消费者需要调用一个服务时:
|
  在这个模型中,当服务消费者需要调用一个服务时:
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ serie="springCloud实战"
|
|||||||
|
|
||||||
  下图展示了这些模式是如何运用到微服务中的:
|
  下图展示了这些模式是如何运用到微服务中的:
|
||||||
|
|
||||||
![客户端弹性模式架构](./picFolder/客户端弹性模式架构.png)
|
![客户端弹性模式架构](https://raw.githubusercontent.com/FleyX/files/master/blogImg/springcloud%E5%AE%9E%E6%88%98/20190107102342.png)
|
||||||
|
|
||||||
# 三、spring cloud 中使用
|
# 三、spring cloud 中使用
|
||||||
|
|
||||||
|
20
java/springcloud实战/4.springCloud之Zuul服务路由.md
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
id="2019-01-03-19-19"
|
||||||
|
title="springCloud学习4(Zuul服务路由)"
|
||||||
|
headWord="像微服务这样的分布式架构中,需要确保跨多个服务调用的关键行为(如安全、日志记录、用户跟踪等)能够正常运行,这就需要一个服务网关来统一处理。"
|
||||||
|
tags=["spring-boot", "spring-cloud","netflix-zuul","service-gateway"]
|
||||||
|
category="java"
|
||||||
|
serie="springCloud实战"
|
||||||
|
---
|
||||||
|
|
||||||
|
<span id="personBlogId" value="2019-01-03-19-19"/>
|
||||||
|
|
||||||
|
# 一、背景
|
||||||
|
|
||||||
|
  微服务架构将一个应用拆分为很多个微小应用,这样会导致之前不是问题的问题出现,比如:
|
||||||
|
|
||||||
|
1. 安全问题如何实现?
|
||||||
|
2. 日志记录如何实现?
|
||||||
|
3. 用户跟踪如何实现?
|
||||||
|
|
||||||
|
上面的问题在传统的单机应用很容易解决,只需要当作一个功能实现即可。但是在微服务中就行不通了,让每个服务都实现一份上述功能,那是相当不现实的,费时,费力还容易出问题。为了解决这个问题,需要将这些横切关注点(分布式系统级别的横切关注点和 spring 中的基本一个意思)抽象成一个独立的且作为应用程序中所有微服务调用的过滤器和路由器的服务。这样的服务被称为————**服务网管(service gateway)**,服务客户端不再直接调用服务。取而代之的是,服务网关作为单个策略执行点(Policy Enforcement Point,PEP) , 所有调用都通过服务网管进行路由,然后被送到目的地, asd发生的 ,, ,,,阿斯蒂芬😊
|
Before Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 55 KiB |
Before Width: | Height: | Size: 64 KiB |
Before Width: | Height: | Size: 20 KiB |
@ -19,7 +19,7 @@ npm i -g typescript
|
|||||||
|
|
||||||
  以 test 项目为例,在 test 目录下执行`tsc --init`,会在项目目录下产生一个`tsconfig.json`的配置文件,每项配置都有说明,如下图所示:
|
  以 test 项目为例,在 test 目录下执行`tsc --init`,会在项目目录下产生一个`tsconfig.json`的配置文件,每项配置都有说明,如下图所示:
|
||||||
|
|
||||||
![tscofnig文件部分截图](./picFolder/tsconfig界面.png)
|
![tscofnig文件部分截图](https://raw.githubusercontent.com/FleyX/files/master/blogImg/%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE/20190107102602.png)
|
||||||
|
|
||||||
主要用到的配置项如下:
|
主要用到的配置项如下:
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ npm i -g typescript
|
|||||||
|
|
||||||
  首先添加 launch.json,如图所示:
|
  首先添加 launch.json,如图所示:
|
||||||
|
|
||||||
![添加配置](./picFolder/添加配置.png)
|
![添加配置](https://raw.githubusercontent.com/FleyX/files/master/blogImg/%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE/20190107102624.png)
|
||||||
|
|
||||||
选中 node 环境,然后将要调试的文件改为输出目录中对应的 js 文件,修改 program 属性:
|
选中 node 环境,然后将要调试的文件改为输出目录中对应的 js 文件,修改 program 属性:
|
||||||
|
|
||||||
@ -111,6 +111,6 @@ npm i -g typescript
|
|||||||
|
|
||||||
最后调试页面启动调试,选择代码真实运行的进程,如下图所示:
|
最后调试页面启动调试,选择代码真实运行的进程,如下图所示:
|
||||||
|
|
||||||
![vscode符加进程](./picFolder/vscode附加进程.png)
|
![vscode符加进程](https://raw.githubusercontent.com/FleyX/files/master/blogImg/%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE/20190107102641.png)
|
||||||
|
|
||||||
  大功告成。。
|
  大功告成。。
|
||||||
|
@ -9,9 +9,11 @@ serie="踩坑"
|
|||||||
|
|
||||||
  项目组最近加了一个新功能到代码中,使用 flyway 记录数据库版本变更,该工具会记录每次数据库结构的修改并生成 sql 文件存在指定目录上(当然必须用它来变更数据库,外部的变更它是无法感知的),然后每次启动时 flyway 会检查使用的数据库和当前项目代码中的 sql 变更版本是否一致,一致正常启动,不一致中如果是数据库落后将会更新数据库(这样能够保证代码在任何地方运行数据库都是一致的),否则就报错了。数据库中有一张表记录版本信息,如下图:
|
  项目组最近加了一个新功能到代码中,使用 flyway 记录数据库版本变更,该工具会记录每次数据库结构的修改并生成 sql 文件存在指定目录上(当然必须用它来变更数据库,外部的变更它是无法感知的),然后每次启动时 flyway 会检查使用的数据库和当前项目代码中的 sql 变更版本是否一致,一致正常启动,不一致中如果是数据库落后将会更新数据库(这样能够保证代码在任何地方运行数据库都是一致的),否则就报错了。数据库中有一张表记录版本信息,如下图:
|
||||||
|
|
||||||
![版本记录](./picFolder/版本记录.PNG),同时本地代码中也有一个文件夹保存每次操作的 sql 语句,如下图:
|
![版本记录](https://raw.githubusercontent.com/FleyX/files/master/blogImg/%E5%85%B6%E4%BB%96%E5%90%84%E7%A7%8D/20190107102736.PNG)
|
||||||
|
|
||||||
![版本sql](./picFolder/版本sql.PNG)
|
同时本地代码中也有一个文件夹保存每次操作的 sql 语句,如下图:
|
||||||
|
|
||||||
|
![版本sql](https://raw.githubusercontent.com/FleyX/files/master/blogImg/%E5%85%B6%E4%BB%96%E5%90%84%E7%A7%8D/20190107102748.PNG)
|
||||||
|
|
||||||
通过对比 checksum 值来判断当前 sql 语句和生成数据库的执行语句是否一致,checksum 值由 CRC32 计算后处理得出。
|
通过对比 checksum 值来判断当前 sql 语句和生成数据库的执行语句是否一致,checksum 值由 CRC32 计算后处理得出。
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 8.8 KiB |
@ -15,7 +15,7 @@ serie="分布式事务"
|
|||||||
|
|
||||||
### 1.数据库事务
|
### 1.数据库事务
|
||||||
|
|
||||||
我们都知道数据库事务的四个特性:原子性、一致性、隔离性和持久性,数据库事务由数据库软件自身来完成。假如数据库在提交事务的时候突然断电,数据库可以在日志记录中找到上一次事务操作然后根据当前数据库的情况进行undo回滚或者是redo前滚(基于某时刻的完整备份然后执行从该时刻到崩溃时间所有增删改查操作,使数据库恢复到崩溃前的状态)。在分布式环境中可能遇到的问题就更多了,例如机器宕机、网络异常、消息乱序、数据错误、存储数据丢失等等,数据库自身并没有比较好的解决方案(下文会提到一种数据库支持的解决方法)。
|
  我们都知道数据库事务的四个特性:原子性、一致性、隔离性和持久性,数据库事务由数据库软件自身来完成。假如数据库在提交事务的时候突然断电,数据库可以在日志记录中找到上一次事务操作然后根据当前数据库的情况进行 undo 回滚或者是 redo 前滚(基于某时刻的完整备份然后执行从该时刻到崩溃时间所有增删改查操作,使数据库恢复到崩溃前的状态)。在分布式环境中可能遇到的问题就更多了,例如机器宕机、网络异常、消息乱序、数据错误、存储数据丢失等等,数据库自身并没有比较好的解决方案(下文会提到一种数据库支持的解决方法)。
|
||||||
|
|
||||||
### 2.分布式理论
|
### 2.分布式理论
|
||||||
|
|
||||||
@ -81,4 +81,3 @@ BASE理论是对CAP中的一致性和可用性进行一个权衡的结果,理
|
|||||||
**优点**:一种非常经典的实现,避免了分布式事务,实现了最终一致性。
|
**优点**:一种非常经典的实现,避免了分布式事务,实现了最终一致性。
|
||||||
|
|
||||||
**缺点**:消息表耦合到了业务系统中。
|
**缺点**:消息表耦合到了业务系统中。
|
||||||
|
|
||||||
|
@ -6,23 +6,20 @@ tags=["vmware","nat","ping","ubuntu"]
|
|||||||
category="java"
|
category="java"
|
||||||
serie="正则匹配"
|
serie="正则匹配"
|
||||||
---
|
---
|
||||||
[id]:2018-08-04
|
|
||||||
[type]:软件
|
|
||||||
[tag]:vmware,vps,nat,ubuntu
|
|
||||||
|
|
||||||
## 1、wmware 设置
|
## 1、wmware 设置
|
||||||
|
|
||||||
  这篇记录下 nat 网络模式下虚拟机与主机的相互 ping 通。首先使用 wmware 建立一个 ubuntu 虚拟机,网络模式选择 nat 模式。然后点击虚拟网络编辑:
|
  这篇记录下 nat 网络模式下虚拟机与主机的相互 ping 通。首先使用 wmware 建立一个 ubuntu 虚拟机,网络模式选择 nat 模式。然后点击虚拟网络编辑:
|
||||||
|
|
||||||
![1536153781962](./picFolder/pic1.png)
|
![虚拟机网络编辑](https://raw.githubusercontent.com/FleyX/files/master/blogImg/%E7%BD%91%E7%BB%9C/20190107102915.png)
|
||||||
|
|
||||||
接下来点击 nat 设置:
|
接下来点击 nat 设置:
|
||||||
|
|
||||||
![1536153954193](./picFolder/pic2.png)
|
![nat设置](https://raw.githubusercontent.com/FleyX/files/master/blogImg/%E7%BD%91%E7%BB%9C/20190107102934.png)
|
||||||
|
|
||||||
看到如下:
|
看到如下:
|
||||||
|
|
||||||
![pic3](./picFolder/pic3.png)
|
![pic](https://raw.githubusercontent.com/FleyX/files/master/blogImg/%E7%BD%91%E7%BB%9C/20190107102951.png)
|
||||||
|
|
||||||
上面红框是关键,记录这个值,下面虚拟机设置静态 ip 要用到。
|
上面红框是关键,记录这个值,下面虚拟机设置静态 ip 要用到。
|
||||||
|
|
||||||
@ -30,7 +27,7 @@ serie="正则匹配"
|
|||||||
|
|
||||||
  打开网络适配器页面,选择 VMnet,右键->属性->Internet 协议版本 4(TCP/IPV4)->属性,设置 ip 地址为上面上面网关地址最后一个数改成 1,比如 192.168.128.2 就要设置为 192.168.128.1,同时设置子网掩码为 255.255.255.0,默认网关不要填。我的如下:
|
  打开网络适配器页面,选择 VMnet,右键->属性->Internet 协议版本 4(TCP/IPV4)->属性,设置 ip 地址为上面上面网关地址最后一个数改成 1,比如 192.168.128.2 就要设置为 192.168.128.1,同时设置子网掩码为 255.255.255.0,默认网关不要填。我的如下:
|
||||||
|
|
||||||
![pic4](./picFolder/pic4.png)
|
![pic4](https://raw.githubusercontent.com/FleyX/files/master/blogImg/%E7%BD%91%E7%BB%9C/20190107103024.png)
|
||||||
|
|
||||||
**如果想让虚拟机能够访问主机需要关闭主机的防火墙**
|
**如果想让虚拟机能够访问主机需要关闭主机的防火墙**
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 83 KiB |
Before Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 67 KiB |