衷于栖
  • 衷于栖
  • 首页
  • 归档
  • 关于

Image
Profile Picture

衷于栖

自由开发者

分类目录

三维技术4 介绍2 应用1 异常1 技术笔记17 游戏2 源码解读3 管理5 读书笔记3 车联网3 转载11 随笔3

热门标签

  • GIT
  • 工作流指南
  • docker
  • SCRUM
  • JT808
  • 百度地图
  • 狼人杀
  • 模型数据结构
  • 敏捷
  • 扩展
  • 学习WEBGL系列
  • 可维护
  • GlTF
  • CentOS
  • 高德地图
  • 集中式
  • 郭麒麟
  • 郭德纲
  • 进阶
  • 路由节点编辑器

微信订阅

Image

友情链接

王海达博客 Steve Yegge Debug 客栈 Codelei's Blog 笛卡尔积 Java九点半课堂 薛定喵君

【SpringBoot】不完整笔记

2020-04-25     技术笔记


这个笔记不完整。

@Transactional 事物隔离级别

  • Atomic(原子性)
  • Consistency(一致性)
  • Isolation(隔离性)
  • Durability(持久性)

隔离级别

  • 未提交读:允许一个事务读取另一个事物未提交的数据(可能引发脏读、不可重复读、幻读)
  • 读写提交:一个事物只能读取另外一个事物已经提交的数据,不能读取未提交的数据(可能引发不可重复读、幻读)
  • 可重复读:客服读写提交中的不可重复读现象(可能引发幻读)
  • 串行化:要求所有的SQL按照顺序执行,保证了数据的一致性

使用隔离级别

1
2
3
4
@Transactional(isolation = Isolation.SERIALIZABLE) // 串行化
public int insertUser(){
// ...
}

redis配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<!-- 不适用 lettuce 客户端 -->
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>

<!-- 使用 jedis 客户端 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
  • 使用 jedis 客户端需要自定义Bean RedisConnectionFactory
  • 为了查询 redis 显示字符串, 需要自定义Bean RedisTemplate, 并设置字符串序列化方式

RedisTemplate操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Autowired
private ReidsTemplate rt;

// 地理位置操作接口
rt.opsForGeo();
// 散列操作接口
rt.opsForHash();
// 基数操作接口
rt.opsForHyperLogLog();
// 列表操作接口
rt.opsForList();
// 集合操作接口
rt.opsForSet();
// 字符串操作接口
rt.opsForValue();
// 有序集合操作接口
rt.opsForZSet();

// ## 绑定操作 - 用于连续处理 key 键对应值
rt.boundGeoOps("key");
// ... 其他方法不再赘述

Redis事物操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
redisTemplate.opsForValue().set("key1", "value1");

List list = (List)redisTemplate.execute((RedisOperations operations) -> {
// 设置要监控key1
operations.watch("key1");
// 开启事务,在exec命令执行前,全部都只是进入队列
operations.multi();
operations.opsForValue().set("key2", "value2");
// operations.opsForValue().increment("key1", 1);// ①
// 获取值将为null,因为redis只是把命令放入队列
Object value2 = operations.opsForValue().get("key2");
System.out.println("命令在队列,所以value为null【"+ value2 +"】");
operations.opsForValue().set("key3", "value3");
Object value3 = operations.opsForValue().get("key3");
System.out.println("命令在队列,所以value为null【"+ value3 +"】");
// 执行exec命令,将先判别key1是否在监控后被修改过,如果是则不执行事务,否则就执行事务
return operations.exec();// ②
});
System.out.println(list);

Redis流水线

1
2
3
4
5
6
7
8
9
10
11
12
13
Long start = System.currentTimeMillis();
List list = (List)redisTemplate.executePipelined((RedisOperations operations) -> {
for (int i=1; i<=100000; i++) {
operations.opsForValue().set("pipeline_" + i, "value_" + i);
String value = (String) operations.opsForValue().get("pipeline_" + i);
if (i == 100000) {
System.out.println("命令只是进入队列,所以值为空【" + value +"】");
}
}
return null;
});
Long end = System.currentTimeMillis();
System.out.println("耗时:" + (end - start) + "毫秒。");

Redis发布订阅

  • 实现 MessageListener 消息监听器
  • 创建Bean RedisMessageListenerContainer
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

@Autowired
private ThreadPoolTaskScheduler taskScheduler;
@Autowired
private RedisConnectionFactory connectionFactory;

@Bean
public ThreadPoolTaskScheduler initTaskScheduler() {
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
taskScheduler.setPoolSize(20);
return taskScheduler;
}

@Bean
public RedisMessageListenerContainer initRedisContainer() {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
// Redis连接工厂
container.setConnectionFactory(connectionFactory);
// 设置运行任务池
container.setTaskExecutor(taskScheduler);
// 定义监听渠道,名称为topic1
Topic topic = new ChannelTopic("topic1");
// 使用监听器监听Redis的消息
// redisMsgListener 是自定义的消息监听器
container.addMessageListener(redisMsgListener, topic);
return container;
}

Redis使用Lua脚本

  • 使用 DefaultRedisScript 创建脚本实例
  • 使用 redisTemplate.execute 方法执行脚本实例
  • Redis 2.6 以后支持了 Lua
  • 脚本执行具备原子性

Redis缓存

1
2
3
4
5
6
7
8
9
spring:
cache:
type: REDIS
cache-names: test
redis:
cache-null-values: true
# key-prefix:
time-to-live: 0ms
# use-key-prefix: true
  • 相关注解: @EnableCaching, @CachePut, @Cacheable, @CacheEvict.

MongoDB配置

1
2
3
4
5
<!-- mongodb -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
1
2
3
4
5
6
7
8
spring:
data:
mongodb:
database: test
host: localhost
port: 27017
password: 123456
username: 123456

使用 @Document @Id @Field 等定义POJO

MongoDB持久化接口

  • 使用 MongoTemplate 进行
  • 使用 MongoRepository 进行, 需要单独使用 @EnableMongoRepository 注解
  • 基础方法不够用, 可以使用自定义查询注解 @Query 或者实现 <接口名>Impl(这种命名时约定方式,可以通过注解EnableMongoRepository修改配置) 类即可
  • 使用WebFlux可以改成 ReactiveMongoRepository

异步调用

  • 相关注解 @EnableAsync @Async
  • 相关接口 AsyncConfigurer

异步消息AMQ

1
2
3
4
5
6
7
8
9
10
<!--依赖于starter,这样可以使用自动配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
<!--依赖于连接池,这样就可以启用JMS连接池-->
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-pool</artifactId>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
spring:
jms:
pub-sub-domain: true # 是否使用发布订阅模式,默认为false,即用的是点对点的模式
template:
default-destination: activemq.default.destination # 默认目的地址
activemq:
packages:
trust-all: true # 信任所有包
broker-url: tcp://localhost:61616 # ActiveMQ地址
user: admin # 用户名
password: admin # 密码
pool:
enabled: true # 是否启用连接池
max-connections: 50 # 连接池最大连接数配置
  • 通过 @JmsListener 进行配置监听消息
  • 直接使用 JmsTemplate 发送消息

使用AMQP(RabbitMQ)

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
12
13
spring:
rabbitmq:
host: localhost # RabbitMQ 服务器地址
port: 5672 # RabbitMQ 端口
username: admin # RabbitMQ 用户
password: admin # RabbitMQ 密码
publisher-confirms: true # 是否确认发送的消息已经被消费

# 并非整体配置
# rabbitmq:
# queue:
# msg: spring-boot-queue-msg # RabbitMQ 的消息队列名称,由它发送字符串
# user: spring-boot-queue-user # RabbitMQ 的消息队列名称,由它发送用户对象
  • 使用 RabbitTemplate 进行发送消息操作
  • 使用 @RabbitListener 进行消息监听

定时任务

  • 相关注解 @Scheduled(可以配合 @Async 使用) @@EnableScheduling

WebSocket

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
  • 需要自定义Bean ServerEndpointExporter
  • 配置注解 @ServerEndpoint @OnOpen @OnClose @OnMessage @OnError

STOMP

为了解决 webSocket 的兼容性问题

  • 使用注解 @EnableWebSocketMessageBroker 启动STOMP
  • 使用接口配置 WebSocketMessageBrokerConfigurer

热部署

1
2
3
4
5
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
12
13
spring:
devtools:
lovereload:
enabled: true # 是否启用一个livereload.com 兼容的服务器
port: 35729 # 端口livereload.com服务器端口
restart:
enabled: true # 是否启用自动重启功能
additional-exclude: # 在原来的基础上新增不重启服务的文件夹目录
additional-paths: # 在原来的基础上新增重启服务的文件夹目录
exclude: META-INF/maven/**,META-INF/resources/**,resources/**,static/**,public/**,templates/**,**/*Test.class,**/*Tests.class,git.properties # 不重启服务的文件夹配置
poll-interval: 1000 # 设置对路径变化进行监测的时间间隔(以毫秒为单位)
quiet-period: 400 # 在没有改变任何classpath的情况下,在重启被触发前的静默时长(以毫秒计)
trigger-file: # 设置触发文件,当需要实际触发重启检查时,则需要修改这个文件

使用 shift+ctrl+alt+"/" (IDEA中的快捷键) 选择"Registry" 然后勾选 compiler.automake.allow.when.app.running

#SpringBoot

Copyright © 2021 zhoyq.com. All rights reserved.

京ICP备 17068495号-1