切换默认shell到wsl

This commit is contained in:
2023-01-10 21:59:13 +08:00
parent 1d6198e9d8
commit be40280c8c
33 changed files with 5387 additions and 5387 deletions

View File

@@ -1,238 +1,238 @@
- [Spring Boot Async](#spring-boot-async)
- [Spring Executor和Scheduler的自动配置](#spring-executor和scheduler的自动配置)
- [Task Execution and Scheduling](#task-execution-and-scheduling)
- [Task Execution Abstraction](#task-execution-abstraction)
- [TaskExecutor接口的实现种类](#taskexecutor接口的实现种类)
- [TaskExecutor的使用](#taskexecutor的使用)
- [Spring TaskScheduler Abstraction](#spring-taskscheduler-abstraction)
- [Trigger接口](#trigger接口)
- [Trigger实现类](#trigger实现类)
- [TaskScheduler实现类](#taskscheduler实现类)
- [对任务调度和异步执行的注解支持](#对任务调度和异步执行的注解支持)
- [启用Scheduling注解](#启用scheduling注解)
- [@Scheduled注解](#scheduled注解)
- [@Async注解](#async注解)
- [@Async方法的异常处理](#async方法的异常处理)
- [Cron表达式](#cron表达式)
- [Macros](#macros宏)
# Spring Boot Async
## Spring Executor和Scheduler的自动配置
当当前上下文中没有Executor类型的bean对象时spring boot会自动配置一个ThreadPoolTaskExecutor类型的bean对象并且将该bean对象和异步task执行@EnableAsync和spring mvc异步请求处理关联在一起。
该默认创建的ThreadPoolTaskExecutor默认使用8个核心线程并且线程数量可以根据负载动态的增加或者减少。
可以通过如下方式对ThreadPoolTaskExecutor进行配置
```properties
# 该线程池最多含有16个线程
spring.task.execution.pool.max-size=16
# 有有界队列存放task上限为100
spring.task.execution.pool.queue-capacity=100
# 当线程空闲10s默认60s时会进行回收
spring.task.execution.pool.keep-alive=10s
# 设置核心线程数量
spring.task.execution.pool.core-size=8
```
如果使用@EnableScheduling一个ThreadPoolTaskScheduler也可以被配置。该线程池默认使用一个线程但是也可以动态设置
```properties
spring.task.scheduling.thread-name-prefix=scheduling-
spring.task.scheduling.pool.size=2
```
## Task Execution and Scheduling
Spring通过TaskExecutor和TaskScheduler接口为task的异步执行和调度提供了抽象。
### Task Execution Abstraction
Executor对应的是JDK中线程池的概念。在Spring中TaskExecutor接口和java.util.concurrent.Executor接口相同该接口中只有一个execute方法execute(Runnable task))接受一个task。
### TaskExecutor接口的实现种类
Spring中包含许多预制的TaskExecutor实现类该实现类如下
- SyncTaskExecutor:该实现类不会执行异步的调用所有任务的执行都会发生在调用该executor的线程中。通常使用在不需要多线程的场景
- SimpleAsyncTaskExecutor该实现类不会复用任何的线程相反的对于每次调用该executor都会使用一个全新的线程。但是该实现类的确支持对并发数量的限制该executor会阻塞任何超过并发数量限制的调用直到slot被释放为止。SimpleAsyncTaskExecutor并不支持池化技术
- ConcurrentTaskExecutor该实现类是java.util.concurrent.Executor实例的adapter其可以将java.util.concurrent.Executor实例的配置参数以bean properties的形式暴露。当ThreadPoolTaskExecutor的灵活性无法满足需求时可以使用ConcurrentTaskExecutor
- ThreadPoolTaskExecutor该实现类型是最广泛被使用的。该实现类可以通过bean properties来配置java.util.concurrent.ThreadPoolExecutor实例并且将该实例wrap在TaskExecutor实例中。当想要使用另一种java.util.concurrent.Executor时可以使用ConcurrentTaskExecutor。
- DefaultManagedTaskExecutor该实现使用了通过JNDI获取的ManagedExecutorService
### TaskExecutor的使用
在springboot中当使用@EnableAsync时可以通过配置ThreadPoolExecutor的bean properties来配置线程池的核心线程数和最大线程数等属性。
```properties
# 该线程池最多含有16个线程
spring.task.execution.pool.max-size=16
# 有有界队列存放task上限为100
spring.task.execution.pool.queue-capacity=100
# 当线程空闲10s默认60s时会进行回收
spring.task.execution.pool.keep-alive=10s
# 设置核心线程数量
spring.task.execution.pool.core-size=8
```
## Spring TaskScheduler Abstraction
为了在特定的时间点执行taskSpring引入了TaskScheduler接口接口定义如下
```java
public interface TaskScheduler {
ScheduledFuture schedule(Runnable task, Trigger trigger);
ScheduledFuture schedule(Runnable task, Instant startTime);
ScheduledFuture scheduleAtFixedRate(Runnable task, Instant startTime, Duration period);
ScheduledFuture scheduleAtFixedRate(Runnable task, Duration period);
ScheduledFuture scheduleWithFixedDelay(Runnable task, Instant startTime, Duration delay);
ScheduledFuture scheduleWithFixedDelay(Runnable task, Duration delay);
```
> scheduleAtFixedRate和scheduleAtFixedDelay区别
> - fixed rate表示两个task执行开始时间的间隔
> - fixed delay表示上一个task结束时间和下一个task开始时间的间隔
>
> 实例如下:
> - fixed rateTTWWWTTTWWT...(开始时间间隔为5)
> - fixed delayTTWWWWWTTTTWWWWWTTTTTTTWWWWWT...(上次结束和下次开始之间的间隔为5)
>
> **通常TaskScheduler默认情况下是单线程执行的故而fixed rate执行时如果一个Task执行时间超过period时在当前task执行完成之前下一个task并不会开始执行。下一个task会等待当前task执行完成之后立马执行。**
### Trigger接口
Trigger接口的核心理念是下次执行事件由上次执行的结果决定。上次执行的结果存储在TriggerContext中。
Trigger接口如下
```java
public interface Trigger {
Date nextExecutionTime(TriggerContext triggerContext);
}
```
TriggerContext接口如下其具有默认的实现类SimpleTriggerContext
```java
public interface TriggerContext {
Date lastScheduledExecutionTime();
Date lastActualExecutionTime();
Date lastCompletionTime();
}
```
### Trigger实现类
Spring为Trigger提供了两个实现类其中CronTrigger允许task的调度按照cron expression来执行类似linux中的crond
```java
scheduler.schedule(task, new CronTrigger("0 15 9-17 * * MON-FRI"));
```
Spring的另一个Trigger实现是PeriodicTrigger其接受一个固定的period期间一个可选的初始delay值并接收一个boolean值标识该period是fixed-rate还是fixed-delay。
### TaskScheduler实现类
如果不需要外部的线程管理可以使用spring提供的ThreadPoolTaskScheduler其会将任务委托给ScheduledExecutorService来提供bean-properties形式的配置。
## 对任务调度和异步执行的注解支持
Spring同时对任务调度和异步方法的执行提供注解支持。
### 启用Scheduling注解
想要启用@Async和@Scheduled注解,必须将@EnableAsync注解和@EnableScheduling注解添加到一个@Configuration类上
```java
@Configuration
@EnableAsync
@EnableScheduling
public class AppConfig {
}
```
> **@Async注解的实现是通过proxy模式来实现的故而如果在类内部调用位于同一个类中的@Async方法那么代理拦截会失效此时调用的@Async方法将会同步执行而非异步执行**
> @Async可以接收一个value值用于指定目标的执行器Executor或TaskExecutor的beanName
### @Scheduled注解
在将@Scheduled注解标注到方法时可以为其指定一个trigger的元数据使用示例如下
```java
@Scheduled(fixedDelay = 5000)
public void doSomething() {
// something that should run periodically
}
```
> 默认情况下fixedDelay、fixedRate、initialDelay的时间单位都是ms可以指定timeUnit来指定其他的时间单位
> ```java
> @Scheduled(fixedDelay = 5, timeUnit = TimeUnit.SECONDS)
> public void doSomething() {
> // something that should run periodically
> }
> ```
可以为@Scheduled注解使用cron表达式
```java
@Scheduled(cron="*/5 * * * * MON-FRI")
public void doSomething() {
// something that should run on weekdays only
}
```
### @Async注解
通过为方法指定@Async注解可以让该方法异步执行该方法的执行通过TaskExecutor。
```java
@Async
void doSomething() {
// this will be run asynchronously
}
```
可以为@Async标注的方法指定参数和返回值但是异步方法的返回值只能为void或是Future类型。
在该异步方法的调用方调用返回Future实例的get方法之前调用方仍然能够执行其他操作异步方法的执行位于TaskExecutor的线程中。
```java
@Async
Future<String> returnSomething(int i) {
// this will be run asynchronously
}
```
不能将@Async注解和生命周期回调(例如@PostConstruct进行混用如果想要异步的初始化bean对象需要按照如下方法
```java
public class SampleBeanImpl implements SampleBean {
@Async
void doSomething() {
// ...
}
}
public class SampleBeanInitializer {
private final SampleBean bean;
public SampleBeanInitializer(SampleBean bean) {
this.bean = bean;
}
@PostConstruct
public void initialize() {
bean.doSomething();
}
}
```
### @Async方法的异常处理
@Async方法的返回类型是Future类型时处理async方法执行时抛出的异常非常简单当在Future对象上调用get方法时异常会被抛出。**但当@Async方法的返回类型是void时执行时抛出的异常既无法被捕获也无法被传输。可以指定一个AsyncUncaughtExceptionHandler来处理此类异常。**
```java
public class MyAsyncUncaughtExceptionHandler implements AsyncUncaughtExceptionHandler {
@Override
public void handleUncaughtException(Throwable ex, Method method, Object... params) {
// handle exception
}
}
```
### Cron表达式
在Spring中cron表达式格式如下
\* \* \* \* \* \*
其代表为s,min,hour,day of month/\*(1~31)\*/,month/\*(1~12)\*/,day of week/\*(0~7,0 or 7 is sun)\*/)
> 规则如下:
> - 所有字段都可以用(*)来匹配所有值
> - 逗号(,)可以用来分隔同一字段中多个值
> - 分号(-可以用来指定范围指定的范围左右都包含eg1-5代表[1,5]
> - 在范围(或是*)后跟随下划线(/)代表间隔,如在分钟字段指定*/20代表该小时内每过20min
> - 对于月份或者day of week可以使用英文名的前三个字母来代替大小写不敏感
> - 在day of month或day of week字段中可以包含L字母
> - 在day of month字段L代表该月的最后一天在该字段还可以为L指定一个负的偏移量如L-n代表该月的倒数第n+1天
> - 在day of week字段L代表该周的最后一天L前还可以前缀月份的数字或是月份的前三个字母dL或DDDL如7L或sunL代表该月份的最后一个星期日),代该月份的最后一个day of week
> - day of month字段可以指定为nW代表离day of month为n最近的一个工作日如果n为周六则该该字段代表的值为周五的day of month如果n为周六则该字段代表下周一的day of month如果n为1其位于周六其也代表下周一的day of month1W代表该月的第一个工作日
> - 如果day of month的值为LW则代表该月的最后一个工作日
> - day of week字段还能指定为d#n或DDD#n的形式代表该月的的第几个d in week例如SUN#2代表当前月的第二个星期日
#### Macros
Cron表达式可读性不太好可以使用如下预定义的宏
| Macro | meaning |
|:-:|:-:|
| @yearly (or @annually) | once a year (0 0 0 1 1 *) |
| @monthly | once a month (0 0 0 1 * *) |
| @weekly | once a week (0 0 0 * * 0) |
| @daily (or @midnight) | once a day (0 0 0 * * *), or |
| @hourly | once an hour, (0 0 * * * *) |
- [Spring Boot Async](#spring-boot-async)
- [Spring Executor和Scheduler的自动配置](#spring-executor和scheduler的自动配置)
- [Task Execution and Scheduling](#task-execution-and-scheduling)
- [Task Execution Abstraction](#task-execution-abstraction)
- [TaskExecutor接口的实现种类](#taskexecutor接口的实现种类)
- [TaskExecutor的使用](#taskexecutor的使用)
- [Spring TaskScheduler Abstraction](#spring-taskscheduler-abstraction)
- [Trigger接口](#trigger接口)
- [Trigger实现类](#trigger实现类)
- [TaskScheduler实现类](#taskscheduler实现类)
- [对任务调度和异步执行的注解支持](#对任务调度和异步执行的注解支持)
- [启用Scheduling注解](#启用scheduling注解)
- [@Scheduled注解](#scheduled注解)
- [@Async注解](#async注解)
- [@Async方法的异常处理](#async方法的异常处理)
- [Cron表达式](#cron表达式)
- [Macros](#macros宏)
# Spring Boot Async
## Spring Executor和Scheduler的自动配置
当当前上下文中没有Executor类型的bean对象时spring boot会自动配置一个ThreadPoolTaskExecutor类型的bean对象并且将该bean对象和异步task执行@EnableAsync和spring mvc异步请求处理关联在一起。
该默认创建的ThreadPoolTaskExecutor默认使用8个核心线程并且线程数量可以根据负载动态的增加或者减少。
可以通过如下方式对ThreadPoolTaskExecutor进行配置
```properties
# 该线程池最多含有16个线程
spring.task.execution.pool.max-size=16
# 有有界队列存放task上限为100
spring.task.execution.pool.queue-capacity=100
# 当线程空闲10s默认60s时会进行回收
spring.task.execution.pool.keep-alive=10s
# 设置核心线程数量
spring.task.execution.pool.core-size=8
```
如果使用@EnableScheduling一个ThreadPoolTaskScheduler也可以被配置。该线程池默认使用一个线程但是也可以动态设置
```properties
spring.task.scheduling.thread-name-prefix=scheduling-
spring.task.scheduling.pool.size=2
```
## Task Execution and Scheduling
Spring通过TaskExecutor和TaskScheduler接口为task的异步执行和调度提供了抽象。
### Task Execution Abstraction
Executor对应的是JDK中线程池的概念。在Spring中TaskExecutor接口和java.util.concurrent.Executor接口相同该接口中只有一个execute方法execute(Runnable task))接受一个task。
### TaskExecutor接口的实现种类
Spring中包含许多预制的TaskExecutor实现类该实现类如下
- SyncTaskExecutor:该实现类不会执行异步的调用所有任务的执行都会发生在调用该executor的线程中。通常使用在不需要多线程的场景
- SimpleAsyncTaskExecutor该实现类不会复用任何的线程相反的对于每次调用该executor都会使用一个全新的线程。但是该实现类的确支持对并发数量的限制该executor会阻塞任何超过并发数量限制的调用直到slot被释放为止。SimpleAsyncTaskExecutor并不支持池化技术
- ConcurrentTaskExecutor该实现类是java.util.concurrent.Executor实例的adapter其可以将java.util.concurrent.Executor实例的配置参数以bean properties的形式暴露。当ThreadPoolTaskExecutor的灵活性无法满足需求时可以使用ConcurrentTaskExecutor
- ThreadPoolTaskExecutor该实现类型是最广泛被使用的。该实现类可以通过bean properties来配置java.util.concurrent.ThreadPoolExecutor实例并且将该实例wrap在TaskExecutor实例中。当想要使用另一种java.util.concurrent.Executor时可以使用ConcurrentTaskExecutor。
- DefaultManagedTaskExecutor该实现使用了通过JNDI获取的ManagedExecutorService
### TaskExecutor的使用
在springboot中当使用@EnableAsync时可以通过配置ThreadPoolExecutor的bean properties来配置线程池的核心线程数和最大线程数等属性。
```properties
# 该线程池最多含有16个线程
spring.task.execution.pool.max-size=16
# 有有界队列存放task上限为100
spring.task.execution.pool.queue-capacity=100
# 当线程空闲10s默认60s时会进行回收
spring.task.execution.pool.keep-alive=10s
# 设置核心线程数量
spring.task.execution.pool.core-size=8
```
## Spring TaskScheduler Abstraction
为了在特定的时间点执行taskSpring引入了TaskScheduler接口接口定义如下
```java
public interface TaskScheduler {
ScheduledFuture schedule(Runnable task, Trigger trigger);
ScheduledFuture schedule(Runnable task, Instant startTime);
ScheduledFuture scheduleAtFixedRate(Runnable task, Instant startTime, Duration period);
ScheduledFuture scheduleAtFixedRate(Runnable task, Duration period);
ScheduledFuture scheduleWithFixedDelay(Runnable task, Instant startTime, Duration delay);
ScheduledFuture scheduleWithFixedDelay(Runnable task, Duration delay);
```
> scheduleAtFixedRate和scheduleAtFixedDelay区别
> - fixed rate表示两个task执行开始时间的间隔
> - fixed delay表示上一个task结束时间和下一个task开始时间的间隔
>
> 实例如下:
> - fixed rateTTWWWTTTWWT...(开始时间间隔为5)
> - fixed delayTTWWWWWTTTTWWWWWTTTTTTTWWWWWT...(上次结束和下次开始之间的间隔为5)
>
> **通常TaskScheduler默认情况下是单线程执行的故而fixed rate执行时如果一个Task执行时间超过period时在当前task执行完成之前下一个task并不会开始执行。下一个task会等待当前task执行完成之后立马执行。**
### Trigger接口
Trigger接口的核心理念是下次执行事件由上次执行的结果决定。上次执行的结果存储在TriggerContext中。
Trigger接口如下
```java
public interface Trigger {
Date nextExecutionTime(TriggerContext triggerContext);
}
```
TriggerContext接口如下其具有默认的实现类SimpleTriggerContext
```java
public interface TriggerContext {
Date lastScheduledExecutionTime();
Date lastActualExecutionTime();
Date lastCompletionTime();
}
```
### Trigger实现类
Spring为Trigger提供了两个实现类其中CronTrigger允许task的调度按照cron expression来执行类似linux中的crond
```java
scheduler.schedule(task, new CronTrigger("0 15 9-17 * * MON-FRI"));
```
Spring的另一个Trigger实现是PeriodicTrigger其接受一个固定的period期间一个可选的初始delay值并接收一个boolean值标识该period是fixed-rate还是fixed-delay。
### TaskScheduler实现类
如果不需要外部的线程管理可以使用spring提供的ThreadPoolTaskScheduler其会将任务委托给ScheduledExecutorService来提供bean-properties形式的配置。
## 对任务调度和异步执行的注解支持
Spring同时对任务调度和异步方法的执行提供注解支持。
### 启用Scheduling注解
想要启用@Async和@Scheduled注解,必须将@EnableAsync注解和@EnableScheduling注解添加到一个@Configuration类上
```java
@Configuration
@EnableAsync
@EnableScheduling
public class AppConfig {
}
```
> **@Async注解的实现是通过proxy模式来实现的故而如果在类内部调用位于同一个类中的@Async方法那么代理拦截会失效此时调用的@Async方法将会同步执行而非异步执行**
> @Async可以接收一个value值用于指定目标的执行器Executor或TaskExecutor的beanName
### @Scheduled注解
在将@Scheduled注解标注到方法时可以为其指定一个trigger的元数据使用示例如下
```java
@Scheduled(fixedDelay = 5000)
public void doSomething() {
// something that should run periodically
}
```
> 默认情况下fixedDelay、fixedRate、initialDelay的时间单位都是ms可以指定timeUnit来指定其他的时间单位
> ```java
> @Scheduled(fixedDelay = 5, timeUnit = TimeUnit.SECONDS)
> public void doSomething() {
> // something that should run periodically
> }
> ```
可以为@Scheduled注解使用cron表达式
```java
@Scheduled(cron="*/5 * * * * MON-FRI")
public void doSomething() {
// something that should run on weekdays only
}
```
### @Async注解
通过为方法指定@Async注解可以让该方法异步执行该方法的执行通过TaskExecutor。
```java
@Async
void doSomething() {
// this will be run asynchronously
}
```
可以为@Async标注的方法指定参数和返回值但是异步方法的返回值只能为void或是Future类型。
在该异步方法的调用方调用返回Future实例的get方法之前调用方仍然能够执行其他操作异步方法的执行位于TaskExecutor的线程中。
```java
@Async
Future<String> returnSomething(int i) {
// this will be run asynchronously
}
```
不能将@Async注解和生命周期回调(例如@PostConstruct进行混用如果想要异步的初始化bean对象需要按照如下方法
```java
public class SampleBeanImpl implements SampleBean {
@Async
void doSomething() {
// ...
}
}
public class SampleBeanInitializer {
private final SampleBean bean;
public SampleBeanInitializer(SampleBean bean) {
this.bean = bean;
}
@PostConstruct
public void initialize() {
bean.doSomething();
}
}
```
### @Async方法的异常处理
@Async方法的返回类型是Future类型时处理async方法执行时抛出的异常非常简单当在Future对象上调用get方法时异常会被抛出。**但当@Async方法的返回类型是void时执行时抛出的异常既无法被捕获也无法被传输。可以指定一个AsyncUncaughtExceptionHandler来处理此类异常。**
```java
public class MyAsyncUncaughtExceptionHandler implements AsyncUncaughtExceptionHandler {
@Override
public void handleUncaughtException(Throwable ex, Method method, Object... params) {
// handle exception
}
}
```
### Cron表达式
在Spring中cron表达式格式如下
\* \* \* \* \* \*
其代表为s,min,hour,day of month/\*(1~31)\*/,month/\*(1~12)\*/,day of week/\*(0~7,0 or 7 is sun)\*/)
> 规则如下:
> - 所有字段都可以用(*)来匹配所有值
> - 逗号(,)可以用来分隔同一字段中多个值
> - 分号(-可以用来指定范围指定的范围左右都包含eg1-5代表[1,5]
> - 在范围(或是*)后跟随下划线(/)代表间隔,如在分钟字段指定*/20代表该小时内每过20min
> - 对于月份或者day of week可以使用英文名的前三个字母来代替大小写不敏感
> - 在day of month或day of week字段中可以包含L字母
> - 在day of month字段L代表该月的最后一天在该字段还可以为L指定一个负的偏移量如L-n代表该月的倒数第n+1天
> - 在day of week字段L代表该周的最后一天L前还可以前缀月份的数字或是月份的前三个字母dL或DDDL如7L或sunL代表该月份的最后一个星期日),代该月份的最后一个day of week
> - day of month字段可以指定为nW代表离day of month为n最近的一个工作日如果n为周六则该该字段代表的值为周五的day of month如果n为周六则该字段代表下周一的day of month如果n为1其位于周六其也代表下周一的day of month1W代表该月的第一个工作日
> - 如果day of month的值为LW则代表该月的最后一个工作日
> - day of week字段还能指定为d#n或DDD#n的形式代表该月的的第几个d in week例如SUN#2代表当前月的第二个星期日
#### Macros
Cron表达式可读性不太好可以使用如下预定义的宏
| Macro | meaning |
|:-:|:-:|
| @yearly (or @annually) | once a year (0 0 0 1 1 *) |
| @monthly | once a month (0 0 0 1 * *) |
| @weekly | once a week (0 0 0 * * 0) |
| @daily (or @midnight) | once a day (0 0 0 * * *), or |
| @hourly | once an hour, (0 0 * * * *) |

View File

@@ -1,53 +1,53 @@
# Spring Data Redis
- ## Spring Data Redis
- 在Spring框架中与Redis进行通信既提供了低层次的api与字节数据进行交互也提供了高度抽象的api供用户使用
- Redis Connection支持通过连接器和Redis服务端进行低层次的交互
- RedisTemplate则是向用户提供了高层次api与Rdis服务端进行交互
- ## 连接Redis
- 为了通过IOC容器连接Redis需要使用统一的Spring Redis API。对于任何库提供的Redis Connector都会统一向外提供一致的Spring Redis API。
- Spring Redis API通过RedisConnection和RedisConnectionFactory接口进行工作并且从Redis处获取连接
- ## RedisConnection和RedisConnectionFactory
- RdisConnection用于提供和Redis后端的交互。RedisConnection接口会自动将底层Connector库异常转化为统一的Spring DAO异常因而在使用ReidsConnection的过程中如果切换底层链接库并不需要代码的改动。
- RedisConnection时通过RedisConnectionFactory来获取的
- ## RedisTemplate
- RedisTemplate是线程安全的可以在多个线程中被并发安全的使用
- RedisTemplate使用java底层的序列化机制在通过RedisTemplate读取或者写入数据时会通过Java的序列化机制将对象序列化/反序列化。
- RedisTemplate要求key是非空的但是可以接受空的value值
- 当想要使用RedisTemplate的某个视图时可以将RedisTemplate对象注入给该名为xxxOperations的视图。
```java
@Service
public class RedisTemplateOperations {
// 直接注入
@Autowired
private RedisTemplate<String,String> redisTemplate;
// 将RedisTemplate转换成其某一个视图之后再注入
@Resource(name="redisTemplate")
private ListOperations<String,String> opsForList;
}
```
- ## StringRedisTemplate
- 在Redis操作中key和Value通常都是String类型。故而Spring Data Redis提供了操作StringRedisTemplate类
- StringRedisTemplate是RedisTemplate的子类并且在应用启动时IOC容器中会注入redisTemplate和stringRedisTemplate两个对象
- 相比较于RedisTemplateStringRedisTemplate底层使用StringRedisSerializer来进行序列化其序列化的key和value都是可读的
- ## 序列化Serializer选择
- 除了先前提到的jdk默认的序列化机制和StringRedisSerializerSpring Data Redis还提供了其他Serializer
- 例如可以选择将key和value化为json字符串格式可以选用Jackson2JsonSerializer或者GenericJackson2JsonSerializer
> 相对于Jackson2JsonSerializerGenericJackson2JsonSerializer在序列化对象为json串时添加了对象的java类型信息故而在将json串反序列化并且转换为原有类型时不会抛出异常
```java
/**
* 如果想要自定义redisTemplate的序列化方式可以添加如下配置类
* RedisTemplate支持分别自定义key/value/hashkey/hashvalue的序列化方式
* RedisTemplate也支持设置defaultSerializer当key/value/hashkey/hashvalue的Serializer没有显式指定时会应用defaultSerializer
**/
@Configuration
public class SerializerConfig {
@Bean(name="redisTemplate")
RedisTemplate<Object,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.setDefaultSerializer(new GenericJackson2JsonRedisSerializer());
return redisTemplate;
}
}
# Spring Data Redis
- ## Spring Data Redis
- 在Spring框架中与Redis进行通信既提供了低层次的api与字节数据进行交互也提供了高度抽象的api供用户使用
- Redis Connection支持通过连接器和Redis服务端进行低层次的交互
- RedisTemplate则是向用户提供了高层次api与Rdis服务端进行交互
- ## 连接Redis
- 为了通过IOC容器连接Redis需要使用统一的Spring Redis API。对于任何库提供的Redis Connector都会统一向外提供一致的Spring Redis API。
- Spring Redis API通过RedisConnection和RedisConnectionFactory接口进行工作并且从Redis处获取连接
- ## RedisConnection和RedisConnectionFactory
- RdisConnection用于提供和Redis后端的交互。RedisConnection接口会自动将底层Connector库异常转化为统一的Spring DAO异常因而在使用ReidsConnection的过程中如果切换底层链接库并不需要代码的改动。
- RedisConnection时通过RedisConnectionFactory来获取的
- ## RedisTemplate
- RedisTemplate是线程安全的可以在多个线程中被并发安全的使用
- RedisTemplate使用java底层的序列化机制在通过RedisTemplate读取或者写入数据时会通过Java的序列化机制将对象序列化/反序列化。
- RedisTemplate要求key是非空的但是可以接受空的value值
- 当想要使用RedisTemplate的某个视图时可以将RedisTemplate对象注入给该名为xxxOperations的视图。
```java
@Service
public class RedisTemplateOperations {
// 直接注入
@Autowired
private RedisTemplate<String,String> redisTemplate;
// 将RedisTemplate转换成其某一个视图之后再注入
@Resource(name="redisTemplate")
private ListOperations<String,String> opsForList;
}
```
- ## StringRedisTemplate
- 在Redis操作中key和Value通常都是String类型。故而Spring Data Redis提供了操作StringRedisTemplate类
- StringRedisTemplate是RedisTemplate的子类并且在应用启动时IOC容器中会注入redisTemplate和stringRedisTemplate两个对象
- 相比较于RedisTemplateStringRedisTemplate底层使用StringRedisSerializer来进行序列化其序列化的key和value都是可读的
- ## 序列化Serializer选择
- 除了先前提到的jdk默认的序列化机制和StringRedisSerializerSpring Data Redis还提供了其他Serializer
- 例如可以选择将key和value化为json字符串格式可以选用Jackson2JsonSerializer或者GenericJackson2JsonSerializer
> 相对于Jackson2JsonSerializerGenericJackson2JsonSerializer在序列化对象为json串时添加了对象的java类型信息故而在将json串反序列化并且转换为原有类型时不会抛出异常
```java
/**
* 如果想要自定义redisTemplate的序列化方式可以添加如下配置类
* RedisTemplate支持分别自定义key/value/hashkey/hashvalue的序列化方式
* RedisTemplate也支持设置defaultSerializer当key/value/hashkey/hashvalue的Serializer没有显式指定时会应用defaultSerializer
**/
@Configuration
public class SerializerConfig {
@Bean(name="redisTemplate")
RedisTemplate<Object,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.setDefaultSerializer(new GenericJackson2JsonRedisSerializer());
return redisTemplate;
}
}
```

View File

@@ -1,9 +1,9 @@
# Spring Data
- ## Spring Boot中选择连接池的算法
- HikariCP的表现和并发性都很好如果HikariCP可以被获取选择HikariCP
- 如果HikariCP不能获取选用Tomcat Datasource
- 如果Tomcat Datasource也不能获取选用DBCP2
- 如果上述都无法获取选用Oracle UCP
- Spring Boot使用自定义连接池
- 可以通过显式指定自定义的连接池种类来绕过该算法通过指定spring.datasource.type来自定义连接池
# Spring Data
- ## Spring Boot中选择连接池的算法
- HikariCP的表现和并发性都很好如果HikariCP可以被获取选择HikariCP
- 如果HikariCP不能获取选用Tomcat Datasource
- 如果Tomcat Datasource也不能获取选用DBCP2
- 如果上述都无法获取选用Oracle UCP
- Spring Boot使用自定义连接池
- 可以通过显式指定自定义的连接池种类来绕过该算法通过指定spring.datasource.type来自定义连接池
- 可以通过DatasourceBuilder来定义额外的datasource。如果定义了自己的datasouce bean那么自动装配将不会发生。

View File

@@ -1,49 +1,49 @@
# Spring单元测试
## SpringBootTest
在SpringBoot中提供了@SpringBootTest注解。当需要SpringBoot特性时可以通过使用@SpringBootTest注解来作为@ContextConfiguration的替代@SprngBootTest创建ApplicationContext该context在test中被使用。
## @AfterAll
该注解标明的方法会在所有Test执行完成之后再执行
> ### @AfterAll注解特性
> - @AfterAll注解的方法必须含有void类型返回值
> - @AfterAll注解标注方法不能为private
> - 默认情况下,@AfterAll注解的方法必须是static修饰的
> ### 在非static方法中标注@AfterAll
> 在非static方法上标注@AfterAll需要在class上标注@TestInstance(TestInstance.Lifecycle.PER_CLASS)。
> 因为默认情况下TestInstance的默认生命周期是PER_METHOD
> ```JAVA
> @TestInstance(TestInstance.Lifecycle.PER_CLASS)
> public class BeforeAndAfterAnnotationsUnitTest {
>
> String input;
> Long result;
> @BeforeAll
> public void setup() {
> input = "77";
> }
>
> @AfterAll
> public void teardown() {
> input = null;
> result = null;
> }
>
> @Test
> public void whenConvertStringToLong_thenResultShouldBeLong() {
> result = Long.valueOf(input);
> Assertions.assertEquals(77l, result);
> }
> }
> ```
## @AfterEach
该注解标明的方法,在每次@Test标注方法执行完成之后都会被执行
> ### @AfterEach特性
> - 标注方法返回值为空
> - 标注方法不为private
> - 标注方法不是static
## @BeforeAll
类似@AfterAll
## @BeforeEach
# Spring单元测试
## SpringBootTest
在SpringBoot中提供了@SpringBootTest注解。当需要SpringBoot特性时可以通过使用@SpringBootTest注解来作为@ContextConfiguration的替代@SprngBootTest创建ApplicationContext该context在test中被使用。
## @AfterAll
该注解标明的方法会在所有Test执行完成之后再执行
> ### @AfterAll注解特性
> - @AfterAll注解的方法必须含有void类型返回值
> - @AfterAll注解标注方法不能为private
> - 默认情况下,@AfterAll注解的方法必须是static修饰的
> ### 在非static方法中标注@AfterAll
> 在非static方法上标注@AfterAll需要在class上标注@TestInstance(TestInstance.Lifecycle.PER_CLASS)。
> 因为默认情况下TestInstance的默认生命周期是PER_METHOD
> ```JAVA
> @TestInstance(TestInstance.Lifecycle.PER_CLASS)
> public class BeforeAndAfterAnnotationsUnitTest {
>
> String input;
> Long result;
> @BeforeAll
> public void setup() {
> input = "77";
> }
>
> @AfterAll
> public void teardown() {
> input = null;
> result = null;
> }
>
> @Test
> public void whenConvertStringToLong_thenResultShouldBeLong() {
> result = Long.valueOf(input);
> Assertions.assertEquals(77l, result);
> }
> }
> ```
## @AfterEach
该注解标明的方法,在每次@Test标注方法执行完成之后都会被执行
> ### @AfterEach特性
> - 标注方法返回值为空
> - 标注方法不为private
> - 标注方法不是static
## @BeforeAll
类似@AfterAll
## @BeforeEach
类似@AfterEach

View File

@@ -1,71 +1,71 @@
# Spring Boot JSON
## Spring Boot JSON简介
在Spring Boot中为JSON提供了三个集成的内置库Gson、Jackson、JSON-B。
> 其中Jackson是Spring Boot推荐并且默认的JSON库。
Spring Boot项目为Jackson提供了自动装配并且Jackson是spring-boot-starter-json启动器的一部分。当Jackson依赖在classpath下时ObjectMapper的bean对象会自动的被配置。
## 自定义序列化器和反序列化器
如果使用Jackson进行json数据的序列化和反序列化你可能需要实现自己的序列化类和反序列化类。可以通过@JsonComponent注解来定义自己的JsonSerializer, JsonDeserializer,JsonObjectSerializer,JsonObjectDeserializer
```java
@JsonComponent
public class MyJsonComponent {
public static class Serializer extends JsonSerializer<MyObject> {
@Override
public void serialize(MyObject value, JsonGenerator jgen, SerializerProvider serializers) throws IOException {
jgen.writeStartObject();
jgen.writeStringField("name", value.getName());
jgen.writeNumberField("age", value.getAge());
jgen.writeEndObject();
}
}
public static class Deserializer extends JsonDeserializer<MyObject> {
@Override
public MyObject deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException {
ObjectCodec codec = jsonParser.getCodec();
JsonNode tree = codec.readTree(jsonParser);
String name = tree.get("name").textValue();
int age = tree.get("age").intValue();
return new MyObject(name, age);
}
}
}
@JsonComponent
public class MyJsonComponent {
public static class Serializer extends JsonObjectSerializer<MyObject> {
@Override
protected void serializeObject(MyObject value, JsonGenerator jgen, SerializerProvider provider)
throws IOException {
jgen.writeStringField("name", value.getName());
jgen.writeNumberField("age", value.getAge());
}
}
public static class Deserializer extends JsonObjectDeserializer<MyObject> {
@Override
protected MyObject deserializeObject(JsonParser jsonParser, DeserializationContext context, ObjectCodec codec,
JsonNode tree) throws IOException {
String name = nullSafeValue(tree.get("name"), String.class);
int age = nullSafeValue(tree.get("age"), Integer.class);
return new MyObject(name, age);
}
}
}
```
## Jackson使用
Jackson使用ObjectMapper来将json转化为java对象或者将java对象转化为json。
### ObjectMapper处理json域字段和java类域字段的映射关系
# Spring Boot JSON
## Spring Boot JSON简介
在Spring Boot中为JSON提供了三个集成的内置库Gson、Jackson、JSON-B。
> 其中Jackson是Spring Boot推荐并且默认的JSON库。
Spring Boot项目为Jackson提供了自动装配并且Jackson是spring-boot-starter-json启动器的一部分。当Jackson依赖在classpath下时ObjectMapper的bean对象会自动的被配置。
## 自定义序列化器和反序列化器
如果使用Jackson进行json数据的序列化和反序列化你可能需要实现自己的序列化类和反序列化类。可以通过@JsonComponent注解来定义自己的JsonSerializer, JsonDeserializer,JsonObjectSerializer,JsonObjectDeserializer
```java
@JsonComponent
public class MyJsonComponent {
public static class Serializer extends JsonSerializer<MyObject> {
@Override
public void serialize(MyObject value, JsonGenerator jgen, SerializerProvider serializers) throws IOException {
jgen.writeStartObject();
jgen.writeStringField("name", value.getName());
jgen.writeNumberField("age", value.getAge());
jgen.writeEndObject();
}
}
public static class Deserializer extends JsonDeserializer<MyObject> {
@Override
public MyObject deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException {
ObjectCodec codec = jsonParser.getCodec();
JsonNode tree = codec.readTree(jsonParser);
String name = tree.get("name").textValue();
int age = tree.get("age").intValue();
return new MyObject(name, age);
}
}
}
@JsonComponent
public class MyJsonComponent {
public static class Serializer extends JsonObjectSerializer<MyObject> {
@Override
protected void serializeObject(MyObject value, JsonGenerator jgen, SerializerProvider provider)
throws IOException {
jgen.writeStringField("name", value.getName());
jgen.writeNumberField("age", value.getAge());
}
}
public static class Deserializer extends JsonObjectDeserializer<MyObject> {
@Override
protected MyObject deserializeObject(JsonParser jsonParser, DeserializationContext context, ObjectCodec codec,
JsonNode tree) throws IOException {
String name = nullSafeValue(tree.get("name"), String.class);
int age = nullSafeValue(tree.get("age"), Integer.class);
return new MyObject(name, age);
}
}
}
```
## Jackson使用
Jackson使用ObjectMapper来将json转化为java对象或者将java对象转化为json。
### ObjectMapper处理json域字段和java类域字段的映射关系