一、spring boot集成redis
1、pom.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>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>org.chenhui.study</groupId>
<artifactId>spring-boot-redis</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-boot-redis</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--
spring-boot-starter-data-redis 2.1.1使用的是lettuce客户端 ,
虽然比较习惯jedis客户端,但是spring选择了lettuce客户端,那说明lettuce一定有他的优势吧。
当然如果你依旧想选择jedis作为客户端,那你可以选择这种配置
-->
<!--
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
1.5的版本默认采用的连接池技术是jedis 2.0以上版本默认连接池是lettuce, 在这里采用jedis,所以需要排除lettuce的jar
<exclusions>
<exclusion>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</exclusion>
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>
添加jedis客户端
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- spring2.0集成redis需要加上 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2、properties.yml文件
#spring redis相关配置 org.springframework.boot.autoconfigure.data.redis.RedisProperties
spring:
redis:
host: 127.0.0.1
database: 0
port: 6379
password: 123456
timeout:
seconds: 5
3、实体类
package org.chenhui.study.springbootredis.entity;
import java.io.Serializable;
public class User implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private Long id;
private String name;
public User() {
super();
}
public User(Long id, String name) {
super();
this.id = id;
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + "]";
}
}
4、测试类
package org.chenhui.study.springbootredis;
import org.chenhui.study.springbootredis.entity.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBootRedisApplicationTests {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Test
public void contextLoads() {
User user = new User(2l, "张san");
redisTemplate.opsForValue().set("user", user);
User user1 = (User) redisTemplate.opsForValue().get("user");
System.out.println(user1);
}
}
5、启动
16:16:21.111 [main] DEBUG org.springframework.test.context.junit4.SpringJUnit4ClassRunner - SpringJUnit4ClassRunner constructor called with [class org.chenhui.study.springbootredis.SpringBootRedisApplicationTests]
16:16:21.118 [main] DEBUG org.springframework.test.context.BootstrapUtils - Instantiating CacheAwareContextLoaderDelegate from class [org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate]
16:16:21.126 [main] DEBUG org.springframework.test.context.BootstrapUtils - Instantiating BootstrapContext using constructor [public org.springframework.test.context.support.DefaultBootstrapContext(java.lang.Class,org.springframework.test.context.CacheAwareContextLoaderDelegate)]
16:16:21.141 [main] DEBUG org.springframework.test.context.BootstrapUtils - Instantiating TestContextBootstrapper for test class [org.chenhui.study.springbootredis.SpringBootRedisApplicationTests] from class [org.springframework.boot.test.context.SpringBootTestContextBootstrapper]
16:16:21.152 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Neither @ContextConfiguration nor @ContextHierarchy found for test class [org.chenhui.study.springbootredis.SpringBootRedisApplicationTests], using SpringBootContextLoader
16:16:21.157 [main] DEBUG org.springframework.test.context.support.AbstractContextLoader - Did not detect default resource location for test class [org.chenhui.study.springbootredis.SpringBootRedisApplicationTests]: class path resource [org/chenhui/study/springbootredis/SpringBootRedisApplicationTests-context.xml] does not exist
16:16:21.158 [main] DEBUG org.springframework.test.context.support.AbstractContextLoader - Did not detect default resource location for test class [org.chenhui.study.springbootredis.SpringBootRedisApplicationTests]: class path resource [org/chenhui/study/springbootredis/SpringBootRedisApplicationTestsContext.groovy] does not exist
16:16:21.158 [main] INFO org.springframework.test.context.support.AbstractContextLoader - Could not detect default resource locations for test class [org.chenhui.study.springbootredis.SpringBootRedisApplicationTests]: no resource found for suffixes {-context.xml, Context.groovy}.
16:16:21.159 [main] INFO org.springframework.test.context.support.AnnotationConfigContextLoaderUtils - Could not detect default configuration classes for test class [org.chenhui.study.springbootredis.SpringBootRedisApplicationTests]: SpringBootRedisApplicationTests does not declare any static, non-private, non-final, nested classes annotated with @Configuration.
16:16:21.195 [main] DEBUG org.springframework.test.context.support.ActiveProfilesUtils - Could not find an 'annotation declaring class' for annotation type [org.springframework.test.context.ActiveProfiles] and class [org.chenhui.study.springbootredis.SpringBootRedisApplicationTests]
16:16:21.258 [main] DEBUG org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider - Identified candidate component class: file [D:\ChromeDownload\spring-boot-lsyq\spring-boot-redis\target\classes\org\chenhui\study\springbootredis\SpringBootRedisApplication.class]
16:16:21.259 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Found @SpringBootConfiguration org.chenhui.study.springbootredis.SpringBootRedisApplication for test class org.chenhui.study.springbootredis.SpringBootRedisApplicationTests
16:16:21.352 [main] DEBUG org.springframework.boot.test.context.SpringBootTestContextBootstrapper - @TestExecutionListeners is not present for class [org.chenhui.study.springbootredis.SpringBootRedisApplicationTests]: using defaults.
16:16:21.353 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener, org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener, org.springframework.boot.test.autoconfigure.restdocs.RestDocsTestExecutionListener, org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerResetTestExecutionListener, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrintOnlyOnFailureTestExecutionListener, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverTestExecutionListener, org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener]
16:16:21.361 [main] DEBUG org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Skipping candidate TestExecutionListener [org.springframework.test.context.web.ServletTestExecutionListener] due to a missing dependency. Specify custom listener classes or make the default listener classes and their required dependencies available. Offending class: [javax/servlet/ServletContext]
16:16:21.369 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Using TestExecutionListeners: [org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener@1cbbffcd, org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener@27ce24aa, org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@481a996b, org.springframework.test.context.support.DirtiesContextTestExecutionListener@3d51f06e, org.springframework.test.context.transaction.TransactionalTestExecutionListener@7ed7259e, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener@28eaa59a, org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener@3427b02d, org.springframework.boot.test.autoconfigure.restdocs.RestDocsTestExecutionListener@647e447, org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerResetTestExecutionListener@41fbdac4, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrintOnlyOnFailureTestExecutionListener@3c407114, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverTestExecutionListener@35ef1869]
16:16:21.373 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved @ProfileValueSourceConfiguration [null] for test class [org.chenhui.study.springbootredis.SpringBootRedisApplicationTests]
16:16:21.374 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved ProfileValueSource type [class org.springframework.test.annotation.SystemProfileValueSource] for class [org.chenhui.study.springbootredis.SpringBootRedisApplicationTests]
16:16:21.375 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved @ProfileValueSourceConfiguration [null] for test class [org.chenhui.study.springbootredis.SpringBootRedisApplicationTests]
16:16:21.375 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved ProfileValueSource type [class org.springframework.test.annotation.SystemProfileValueSource] for class [org.chenhui.study.springbootredis.SpringBootRedisApplicationTests]
16:16:21.384 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved @ProfileValueSourceConfiguration [null] for test class [org.chenhui.study.springbootredis.SpringBootRedisApplicationTests]
16:16:21.385 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved ProfileValueSource type [class org.springframework.test.annotation.SystemProfileValueSource] for class [org.chenhui.study.springbootredis.SpringBootRedisApplicationTests]
16:16:21.386 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved @ProfileValueSourceConfiguration [null] for test class [org.chenhui.study.springbootredis.SpringBootRedisApplicationTests]
16:16:21.386 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved ProfileValueSource type [class org.springframework.test.annotation.SystemProfileValueSource] for class [org.chenhui.study.springbootredis.SpringBootRedisApplicationTests]
16:16:21.388 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved @ProfileValueSourceConfiguration [null] for test class [org.chenhui.study.springbootredis.SpringBootRedisApplicationTests]
16:16:21.389 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved ProfileValueSource type [class org.springframework.test.annotation.SystemProfileValueSource] for class [org.chenhui.study.springbootredis.SpringBootRedisApplicationTests]
16:16:21.393 [main] DEBUG org.springframework.test.context.support.AbstractDirtiesContextTestExecutionListener - Before test class: context [DefaultTestContext@4d9e68d0 testClass = SpringBootRedisApplicationTests, testInstance = [null], testMethod = [null], testException = [null], mergedContextConfiguration = [MergedContextConfiguration@42e99e4a testClass = SpringBootRedisApplicationTests, locations = '{}', classes = '{class org.chenhui.study.springbootredis.SpringBootRedisApplication}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@1d29cf23, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@53f65459, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@528931cf, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@307f6b8c], contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map[[empty]]], class annotated with @DirtiesContext [false] with mode [null].
16:16:21.395 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved @ProfileValueSourceConfiguration [null] for test class [org.chenhui.study.springbootredis.SpringBootRedisApplicationTests]
16:16:21.395 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved ProfileValueSource type [class org.springframework.test.annotation.SystemProfileValueSource] for class [org.chenhui.study.springbootredis.SpringBootRedisApplicationTests]
16:16:21.400 [main] DEBUG org.springframework.test.context.support.DependencyInjectionTestExecutionListener - Performing dependency injection for test context [[DefaultTestContext@4d9e68d0 testClass = SpringBootRedisApplicationTests, testInstance = org.chenhui.study.springbootredis.SpringBootRedisApplicationTests@694abbdc, testMethod = [null], testException = [null], mergedContextConfiguration = [MergedContextConfiguration@42e99e4a testClass = SpringBootRedisApplicationTests, locations = '{}', classes = '{class org.chenhui.study.springbootredis.SpringBootRedisApplication}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@1d29cf23, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@53f65459, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@528931cf, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@307f6b8c], contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map[[empty]]]].
16:16:21.426 [main] DEBUG org.springframework.test.context.support.TestPropertySourceUtils - Adding inlined properties to environment: {spring.jmx.enabled=false, org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true, server.port=-1}
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.1.1.RELEASE)
2018-12-18 16:16:21.670 INFO 73152 --- [ main] o.c.s.s.SpringBootRedisApplicationTests : Starting SpringBootRedisApplicationTests on Jason with PID 73152 (started by jj in D:\ChromeDownload\spring-boot-lsyq\spring-boot-redis)
2018-12-18 16:16:21.671 INFO 73152 --- [ main] o.c.s.s.SpringBootRedisApplicationTests : No active profile set, falling back to default profiles: default
2018-12-18 16:16:22.017 INFO 73152 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode!
2018-12-18 16:16:22.020 INFO 73152 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data repositories in DEFAULT mode.
2018-12-18 16:16:22.056 INFO 73152 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 19ms. Found 0 repository interfaces.
2018-12-18 16:16:22.818 INFO 73152 --- [ main] o.c.s.s.SpringBootRedisApplicationTests : Started SpringBootRedisApplicationTests in 1.389 seconds (JVM running for 2.085)
============================
CONDITIONS EVALUATION REPORT
============================
Positive matches:
-----------------
GenericCacheConfiguration matched:
- Cache org.springframework.boot.autoconfigure.cache.GenericCacheConfiguration automatic cache type (CacheCondition)
LettuceConnectionConfiguration matched:
- @ConditionalOnClass found required class 'io.lettuce.core.RedisClient' (OnClassCondition)
LettuceConnectionConfiguration#lettuceClientResources matched:
- @ConditionalOnMissingBean (types: io.lettuce.core.resource.ClientResources; SearchStrategy: all) did not find any beans (OnBeanCondition)
LettuceConnectionConfiguration#redisConnectionFactory matched:
- @ConditionalOnMissingBean (types: org.springframework.data.redis.connection.RedisConnectionFactory; SearchStrategy: all) did not find any beans (OnBeanCondition)
NoOpCacheConfiguration matched:
- Cache org.springframework.boot.autoconfigure.cache.NoOpCacheConfiguration automatic cache type (CacheCondition)
PersistenceExceptionTranslationAutoConfiguration matched:
- @ConditionalOnClass found required class 'org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor' (OnClassCondition)
PersistenceExceptionTranslationAutoConfiguration#persistenceExceptionTranslationPostProcessor matched:
- @ConditionalOnProperty (spring.dao.exceptiontranslation.enabled) matched (OnPropertyCondition)
- @ConditionalOnMissingBean (types: org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor; SearchStrategy: all) did not find any beans (OnBeanCondition)
PropertyPlaceholderAutoConfiguration#propertySourcesPlaceholderConfigurer matched:
- @ConditionalOnMissingBean (types: org.springframework.context.support.PropertySourcesPlaceholderConfigurer; SearchStrategy: current) did not find any beans (OnBeanCondition)
ReactorCoreAutoConfiguration matched:
- @ConditionalOnClass found required classes 'reactor.core.publisher.Mono', 'reactor.core.publisher.Flux' (OnClassCondition)
RedisAutoConfiguration matched:
- @ConditionalOnClass found required class 'org.springframework.data.redis.core.RedisOperations' (OnClassCondition)
RedisAutoConfiguration#redisTemplate matched:
- @ConditionalOnMissingBean (names: redisTemplate; SearchStrategy: all) did not find any beans (OnBeanCondition)
RedisAutoConfiguration#stringRedisTemplate matched:
- @ConditionalOnMissingBean (types: org.springframework.data.redis.core.StringRedisTemplate; SearchStrategy: all) did not find any beans (OnBeanCondition)
RedisCacheConfiguration matched:
- @ConditionalOnClass found required class 'org.springframework.data.redis.connection.RedisConnectionFactory' (OnClassCondition)
- Cache org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration automatic cache type (CacheCondition)
RedisReactiveAutoConfiguration matched:
- @ConditionalOnClass found required classes 'org.springframework.data.redis.connection.ReactiveRedisConnectionFactory', 'org.springframework.data.redis.core.ReactiveRedisTemplate', 'reactor.core.publisher.Flux' (OnClassCondition)
RedisReactiveAutoConfiguration#reactiveRedisTemplate matched:
- @ConditionalOnBean (types: org.springframework.data.redis.connection.ReactiveRedisConnectionFactory; SearchStrategy: all) found bean 'redisConnectionFactory'; @ConditionalOnMissingBean (names: reactiveRedisTemplate; SearchStrategy: all) did not find any beans (OnBeanCondition)
RedisRepositoriesAutoConfiguration matched:
- @ConditionalOnClass found required class 'org.springframework.data.redis.repository.configuration.EnableRedisRepositories' (OnClassCondition)
- @ConditionalOnProperty (spring.data.redis.repositories.enabled=true) matched (OnPropertyCondition)
- @ConditionalOnBean (types: org.springframework.data.redis.connection.RedisConnectionFactory; SearchStrategy: all) found bean 'redisConnectionFactory'; @ConditionalOnMissingBean (types: org.springframework.data.redis.repository.support.RedisRepositoryFactoryBean; SearchStrategy: all) did not find any beans (OnBeanCondition)
SimpleCacheConfiguration matched:
- Cache org.springframework.boot.autoconfigure.cache.SimpleCacheConfiguration automatic cache type (CacheCondition)
TaskExecutionAutoConfiguration matched:
- @ConditionalOnClass found required class 'org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor' (OnClassCondition)
TaskExecutionAutoConfiguration#applicationTaskExecutor matched:
- @ConditionalOnMissingBean (types: java.util.concurrent.Executor; SearchStrategy: all) did not find any beans (OnBeanCondition)
TaskExecutionAutoConfiguration#taskExecutorBuilder matched:
- @ConditionalOnMissingBean (types: org.springframework.boot.task.TaskExecutorBuilder; SearchStrategy: all) did not find any beans (OnBeanCondition)
TaskSchedulingAutoConfiguration matched:
- @ConditionalOnClass found required class 'org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler' (OnClassCondition)
TaskSchedulingAutoConfiguration#taskSchedulerBuilder matched:
- @ConditionalOnMissingBean (types: org.springframework.boot.task.TaskSchedulerBuilder; SearchStrategy: all) did not find any beans (OnBeanCondition)
TransactionAutoConfiguration matched:
- @ConditionalOnClass found required class 'org.springframework.transaction.PlatformTransactionManager' (OnClassCondition)
TransactionAutoConfiguration#platformTransactionManagerCustomizers matched:
- @ConditionalOnMissingBean (types: org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizers; SearchStrategy: all) did not find any beans (OnBeanCondition)
Negative matches:
-----------------
ActiveMQAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'javax.jms.ConnectionFactory' (OnClassCondition)
AopAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.aspectj.lang.annotation.Aspect' (OnClassCondition)
ArtemisAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'javax.jms.ConnectionFactory' (OnClassCondition)
BatchAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.batch.core.launch.JobLauncher' (OnClassCondition)
CacheAutoConfiguration:
Did not match:
- @ConditionalOnBean (types: org.springframework.cache.interceptor.CacheAspectSupport; SearchStrategy: all) did not find any beans of type org.springframework.cache.interceptor.CacheAspectSupport (OnBeanCondition)
Matched:
- @ConditionalOnClass found required class 'org.springframework.cache.CacheManager' (OnClassCondition)
CacheAutoConfiguration.CacheManagerJpaDependencyConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean' (OnClassCondition)
- Ancestor org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration did not match (ConditionEvaluationReport.AncestorsMatchedCondition)
CaffeineCacheConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'com.github.benmanes.caffeine.cache.Caffeine' (OnClassCondition)
CassandraAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'com.datastax.driver.core.Cluster' (OnClassCondition)
CassandraDataAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'com.datastax.driver.core.Cluster' (OnClassCondition)
CassandraReactiveDataAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'com.datastax.driver.core.Cluster' (OnClassCondition)
CassandraReactiveRepositoriesAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.data.cassandra.ReactiveSession' (OnClassCondition)
CassandraRepositoriesAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'com.datastax.driver.core.Session' (OnClassCondition)
ClientHttpConnectorAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.web.reactive.function.client.WebClient' (OnClassCondition)
CloudServiceConnectorsAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.cloud.config.java.CloudScanConfiguration' (OnClassCondition)
CodecsAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.http.codec.CodecConfigurer' (OnClassCondition)
CouchbaseAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'com.couchbase.client.java.Cluster' (OnClassCondition)
CouchbaseCacheConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes 'com.couchbase.client.java.Bucket', 'com.couchbase.client.spring.cache.CouchbaseCacheManager' (OnClassCondition)
CouchbaseDataAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'com.couchbase.client.java.Bucket' (OnClassCondition)
CouchbaseReactiveDataAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'com.couchbase.client.java.Bucket' (OnClassCondition)
CouchbaseReactiveRepositoriesAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'com.couchbase.client.java.Bucket' (OnClassCondition)
CouchbaseRepositoriesAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'com.couchbase.client.java.Bucket' (OnClassCondition)
DataSourceAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType' (OnClassCondition)
DataSourceTransactionManagerAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.jdbc.core.JdbcTemplate' (OnClassCondition)
DispatcherServletAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.web.servlet.DispatcherServlet' (OnClassCondition)
EhCacheCacheConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'net.sf.ehcache.Cache' (OnClassCondition)
ElasticsearchAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.elasticsearch.client.Client' (OnClassCondition)
ElasticsearchDataAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.elasticsearch.client.Client' (OnClassCondition)
ElasticsearchRepositoriesAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.elasticsearch.client.Client' (OnClassCondition)
EmbeddedLdapAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'com.unboundid.ldap.listener.InMemoryDirectoryServer' (OnClassCondition)
EmbeddedMongoAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'com.mongodb.MongoClient' (OnClassCondition)
EmbeddedWebServerFactoryCustomizerAutoConfiguration:
Did not match:
- @ConditionalOnWebApplication did not find reactive or servlet web application classes (OnWebApplicationCondition)
ErrorMvcAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'javax.servlet.Servlet' (OnClassCondition)
ErrorWebFluxAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.web.reactive.config.WebFluxConfigurer' (OnClassCondition)
FlywayAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.flywaydb.core.Flyway' (OnClassCondition)
FreeMarkerAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'freemarker.template.Configuration' (OnClassCondition)
GroovyTemplateAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'groovy.text.markup.MarkupTemplateEngine' (OnClassCondition)
GsonAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'com.google.gson.Gson' (OnClassCondition)
H2ConsoleAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.h2.server.web.WebServlet' (OnClassCondition)
HazelcastAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'com.hazelcast.core.HazelcastInstance' (OnClassCondition)
HazelcastCacheConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes 'com.hazelcast.core.HazelcastInstance', 'com.hazelcast.spring.cache.HazelcastCacheManager' (OnClassCondition)
HazelcastJpaDependencyAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'com.hazelcast.core.HazelcastInstance' (OnClassCondition)
HibernateJpaAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'javax.persistence.EntityManager' (OnClassCondition)
HttpEncodingAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.web.filter.CharacterEncodingFilter' (OnClassCondition)
HttpHandlerAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.http.server.reactive.HttpHandler' (OnClassCondition)
HttpMessageConvertersAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.http.converter.HttpMessageConverter' (OnClassCondition)
HypermediaAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.hateoas.Resource' (OnClassCondition)
InfinispanCacheConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.infinispan.spring.provider.SpringEmbeddedCacheManager' (OnClassCondition)
InfluxDbAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.influxdb.InfluxDB' (OnClassCondition)
IntegrationAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.integration.config.EnableIntegration' (OnClassCondition)
JCacheCacheConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'javax.cache.Caching' (OnClassCondition)
JacksonAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'com.fasterxml.jackson.databind.ObjectMapper' (OnClassCondition)
JdbcRepositoriesAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.data.jdbc.repository.config.JdbcConfiguration' (OnClassCondition)
JdbcTemplateAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.jdbc.core.JdbcTemplate' (OnClassCondition)
JedisConnectionConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'redis.clients.jedis.Jedis' (OnClassCondition)
JerseyAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'javax.servlet.ServletRegistration' (OnClassCondition)
JestAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'io.searchbox.client.JestClient' (OnClassCondition)
JmsAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'javax.jms.Message' (OnClassCondition)
JmxAutoConfiguration:
Did not match:
- @ConditionalOnProperty (spring.jmx.enabled=true) found different value in property 'enabled' (OnPropertyCondition)
Matched:
- @ConditionalOnClass found required class 'org.springframework.jmx.export.MBeanExporter' (OnClassCondition)
JndiConnectionFactoryAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.jms.core.JmsTemplate' (OnClassCondition)
JndiDataSourceAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType' (OnClassCondition)
JooqAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.jooq.DSLContext' (OnClassCondition)
JpaRepositoriesAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.data.jpa.repository.JpaRepository' (OnClassCondition)
JsonbAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'javax.json.bind.Jsonb' (OnClassCondition)
JtaAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'javax.transaction.Transaction' (OnClassCondition)
KafkaAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.kafka.core.KafkaTemplate' (OnClassCondition)
LdapAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.ldap.core.ContextSource' (OnClassCondition)
LdapRepositoriesAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.data.ldap.repository.LdapRepository' (OnClassCondition)
LiquibaseAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'liquibase.change.DatabaseChange' (OnClassCondition)
MailSenderAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'javax.mail.internet.MimeMessage' (OnClassCondition)
MailSenderValidatorAutoConfiguration:
Did not match:
- @ConditionalOnProperty (spring.mail.test-connection) did not find property 'test-connection' (OnPropertyCondition)
MessageSourceAutoConfiguration:
Did not match:
- ResourceBundle did not find bundle with basename messages (MessageSourceAutoConfiguration.ResourceBundleCondition)
MongoAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'com.mongodb.MongoClient' (OnClassCondition)
MongoDataAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'com.mongodb.client.MongoClient' (OnClassCondition)
MongoReactiveAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'com.mongodb.reactivestreams.client.MongoClient' (OnClassCondition)
MongoReactiveDataAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'com.mongodb.reactivestreams.client.MongoClient' (OnClassCondition)
MongoReactiveRepositoriesAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'com.mongodb.reactivestreams.client.MongoClient' (OnClassCondition)
MongoRepositoriesAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'com.mongodb.MongoClient' (OnClassCondition)
MultipartAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'javax.servlet.MultipartConfigElement' (OnClassCondition)
MustacheAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'com.samskivert.mustache.Mustache' (OnClassCondition)
Neo4jDataAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.neo4j.ogm.session.SessionFactory' (OnClassCondition)
Neo4jRepositoriesAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.neo4j.ogm.session.Neo4jSession' (OnClassCondition)
OAuth2ClientAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.security.config.annotation.web.configuration.EnableWebSecurity' (OnClassCondition)
OAuth2ResourceServerAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken' (OnClassCondition)
ProjectInfoAutoConfiguration#buildProperties:
Did not match:
- @ConditionalOnResource did not find resource '${spring.info.build.location:classpath:META-INF/build-info.properties}' (OnResourceCondition)
ProjectInfoAutoConfiguration#gitProperties:
Did not match:
- GitResource did not find git info at classpath:git.properties (ProjectInfoAutoConfiguration.GitResourceAvailableCondition)
QuartzAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.quartz.Scheduler' (OnClassCondition)
RabbitAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'com.rabbitmq.client.Channel' (OnClassCondition)
ReactiveOAuth2ClientAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity' (OnClassCondition)
ReactiveOAuth2ResourceServerAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity' (OnClassCondition)
ReactiveSecurityAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity' (OnClassCondition)
ReactiveUserDetailsServiceAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.security.authentication.ReactiveAuthenticationManager' (OnClassCondition)
ReactiveWebServerFactoryAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.http.ReactiveHttpInputMessage' (OnClassCondition)
RepositoryRestMvcAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration' (OnClassCondition)
RestClientAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.elasticsearch.client.RestClient' (OnClassCondition)
RestTemplateAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.web.client.RestTemplate' (OnClassCondition)
SecurityAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.security.authentication.DefaultAuthenticationEventPublisher' (OnClassCondition)
SecurityFilterAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.security.config.http.SessionCreationPolicy' (OnClassCondition)
SecurityRequestMatcherProviderAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.security.web.util.matcher.RequestMatcher' (OnClassCondition)
SendGridAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'com.sendgrid.SendGrid' (OnClassCondition)
ServletWebServerFactoryAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'javax.servlet.ServletRequest' (OnClassCondition)
SessionAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.session.Session' (OnClassCondition)
SolrAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.apache.solr.client.solrj.impl.CloudSolrClient' (OnClassCondition)
SolrRepositoriesAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.apache.solr.client.solrj.SolrClient' (OnClassCondition)
SpringApplicationAdminJmxAutoConfiguration:
Did not match:
- @ConditionalOnProperty (spring.application.admin.enabled=true) did not find property 'enabled' (OnPropertyCondition)
SpringDataWebAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.data.web.PageableHandlerMethodArgumentResolver' (OnClassCondition)
TaskSchedulingAutoConfiguration#taskScheduler:
Did not match:
- @ConditionalOnBean (names: org.springframework.context.annotation.internalScheduledAnnotationProcessor; SearchStrategy: all) did not find any beans named org.springframework.context.annotation.internalScheduledAnnotationProcessor (OnBeanCondition)
ThymeleafAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.thymeleaf.templatemode.TemplateMode' (OnClassCondition)
TransactionAutoConfiguration.EnableTransactionManagementConfiguration:
Did not match:
- @ConditionalOnBean (types: org.springframework.transaction.PlatformTransactionManager; SearchStrategy: all) did not find any beans of type org.springframework.transaction.PlatformTransactionManager (OnBeanCondition)
TransactionAutoConfiguration.EnableTransactionManagementConfiguration.CglibAutoProxyConfiguration:
Did not match:
- Ancestor org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration$EnableTransactionManagementConfiguration did not match (ConditionEvaluationReport.AncestorsMatchedCondition)
Matched:
- @ConditionalOnProperty (spring.aop.proxy-target-class=true) matched (OnPropertyCondition)
TransactionAutoConfiguration.EnableTransactionManagementConfiguration.JdkDynamicAutoProxyConfiguration:
Did not match:
- @ConditionalOnProperty (spring.aop.proxy-target-class=false) did not find property 'proxy-target-class' (OnPropertyCondition)
- Ancestor org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration$EnableTransactionManagementConfiguration did not match (ConditionEvaluationReport.AncestorsMatchedCondition)
TransactionAutoConfiguration.TransactionTemplateConfiguration:
Did not match:
- @ConditionalOnSingleCandidate (types: org.springframework.transaction.PlatformTransactionManager; SearchStrategy: all) did not find any beans (OnBeanCondition)
UserDetailsServiceAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.security.authentication.AuthenticationManager' (OnClassCondition)
ValidationAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'javax.validation.executable.ExecutableValidator' (OnClassCondition)
WebClientAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.web.reactive.function.client.WebClient' (OnClassCondition)
WebFluxAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.web.reactive.config.WebFluxConfigurer' (OnClassCondition)
WebMvcAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'javax.servlet.Servlet' (OnClassCondition)
WebServiceTemplateAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.ws.client.core.WebServiceTemplate' (OnClassCondition)
WebServicesAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.ws.transport.http.MessageDispatcherServlet' (OnClassCondition)
WebSocketMessagingAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer' (OnClassCondition)
WebSocketReactiveAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'javax.servlet.Servlet' (OnClassCondition)
WebSocketServletAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'javax.servlet.Servlet' (OnClassCondition)
XADataSourceAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'javax.transaction.TransactionManager' (OnClassCondition)
Exclusions:
-----------
None
Unconditional classes:
----------------------
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration
2018-12-18 16:16:22.853 ERROR 73152 --- [ main] o.s.test.context.TestContextManager : Caught exception while allowing TestExecutionListener [org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@481a996b] to prepare test instance [org.chenhui.study.springbootredis.SpringBootRedisApplicationTests@694abbdc]
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.chenhui.study.springbootredis.SpringBootRedisApplicationTests': Unsatisfied dependency expressed through field 'redisTemplate'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.data.redis.core.RedisTemplate<java.lang.String, java.lang.Object>' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:596) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:374) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1378) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireBeanProperties(AbstractAutowireCapableBeanFactory.java:396) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:119) ~[spring-test-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) ~[spring-test-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) ~[spring-boot-test-autoconfigure-2.1.1.RELEASE.jar:2.1.1.RELEASE]
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:246) ~[spring-test-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:227) [spring-test-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:289) [spring-test-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) [junit-4.12.jar:4.12]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:291) [spring-test-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:246) [spring-test-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97) [spring-test-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) [junit-4.12.jar:4.12]
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) [spring-test-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) [spring-test-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.junit.runners.ParentRunner.run(ParentRunner.java:363) [junit-4.12.jar:4.12]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190) [spring-test-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) [.cp/:na]
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) [.cp/:na]
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) [.cp/:na]
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675) [.cp/:na]
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) [.cp/:na]
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192) [.cp/:na]
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.data.redis.core.RedisTemplate<java.lang.String, java.lang.Object>' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1644) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1203) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1164) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:593) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
... 29 common frames omitted
启动失败。
我们查看报错信息:No qualifying bean of type 'org.springframework.data.redis.core.RedisTemplate<java.lang.String, java.lang.Object>' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
大致意思是说我们的RedisTemplate模板不是唯一的。
我们这里没有对RedisTemplate进行任何配置。
我们进入RedisTemplate源码看看spring boot的默认配置是怎样的
/*
* Copyright 2011-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.redis.core;
import java.io.Closeable;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.redis.RedisSystemException;
import org.springframework.data.redis.connection.DataType;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisKeyCommands;
import org.springframework.data.redis.connection.RedisServerCommands;
import org.springframework.data.redis.connection.RedisTxCommands;
import org.springframework.data.redis.connection.RedisZSetCommands.Tuple;
import org.springframework.data.redis.connection.SortParameters;
import org.springframework.data.redis.core.ZSetOperations.TypedTuple;
import org.springframework.data.redis.core.query.QueryUtils;
import org.springframework.data.redis.core.query.SortQuery;
import org.springframework.data.redis.core.script.DefaultScriptExecutor;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.data.redis.core.script.ScriptExecutor;
import org.springframework.data.redis.core.types.RedisClientInfo;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationUtils;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.lang.Nullable;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;
/**
* Helper class that simplifies Redis data access code.
* <p/>
* Performs automatic serialization/deserialization between the given objects and the underlying binary data in the
* Redis store. By default, it uses Java serialization for its objects (through {@link JdkSerializationRedisSerializer}
* ). For String intensive operations consider the dedicated {@link StringRedisTemplate}.
* <p/>
* The central method is execute, supporting Redis access code implementing the {@link RedisCallback} interface. It
* provides {@link RedisConnection} handling such that neither the {@link RedisCallback} implementation nor the calling
* code needs to explicitly care about retrieving/closing Redis connections, or handling Connection lifecycle
* exceptions. For typical single step actions, there are various convenience methods.
* <p/>
* Once configured, this class is thread-safe.
* <p/>
* Note that while the template is generified, it is up to the serializers/deserializers to properly convert the given
* Objects to and from binary data.
* <p/>
* <b>This is the central class in Redis support</b>.
*
* @author Costin Leau
* @author Christoph Strobl
* @author Ninad Divadkar
* @author Anqing Shao
* @author Mark Paluch
* @param <K> the Redis key type against which the template works (usually a String)
* @param <V> the Redis value type against which the template works
* @see StringRedisTemplate
*/
public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperations<K, V>, BeanClassLoaderAware {
private boolean enableTransactionSupport = false;
private boolean exposeConnection = false;
private boolean initialized = false;
private boolean enableDefaultSerializer = true;
private @Nullable RedisSerializer<?> defaultSerializer;
private @Nullable ClassLoader classLoader;
@SuppressWarnings("rawtypes") private @Nullable RedisSerializer keySerializer = null;
@SuppressWarnings("rawtypes") private @Nullable RedisSerializer valueSerializer = null;
@SuppressWarnings("rawtypes") private @Nullable RedisSerializer hashKeySerializer = null;
@SuppressWarnings("rawtypes") private @Nullable RedisSerializer hashValueSerializer = null;
private RedisSerializer<String> stringSerializer = RedisSerializer.string();
private @Nullable ScriptExecutor<K> scriptExecutor;
// cache singleton objects (where possible)
private @Nullable ValueOperations<K, V> valueOps;
private @Nullable ListOperations<K, V> listOps;
private @Nullable SetOperations<K, V> setOps;
private @Nullable ZSetOperations<K, V> zSetOps;
private @Nullable GeoOperations<K, V> geoOps;
private @Nullable HyperLogLogOperations<K, V> hllOps;
/**
* Constructs a new <code>RedisTemplate</code> instance.
*/
public RedisTemplate() {}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisAccessor#afterPropertiesSet()
*/
@Override
public void afterPropertiesSet() {
super.afterPropertiesSet();
boolean defaultUsed = false;
if (defaultSerializer == null) {
defaultSerializer = new JdkSerializationRedisSerializer(
classLoader != null ? classLoader : this.getClass().getClassLoader());
}
if (enableDefaultSerializer) {
if (keySerializer == null) {
keySerializer = defaultSerializer;
defaultUsed = true;
}
if (valueSerializer == null) {
valueSerializer = defaultSerializer;
defaultUsed = true;
}
if (hashKeySerializer == null) {
hashKeySerializer = defaultSerializer;
defaultUsed = true;
}
if (hashValueSerializer == null) {
hashValueSerializer = defaultSerializer;
defaultUsed = true;
}
}
if (enableDefaultSerializer && defaultUsed) {
Assert.notNull(defaultSerializer, "default serializer null and not all serializers initialized");
}
if (scriptExecutor == null) {
this.scriptExecutor = new DefaultScriptExecutor<>(this);
}
initialized = true;
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#execute(org.springframework.data.redis.core.RedisCallback)
*/
@Override
@Nullable
public <T> T execute(RedisCallback<T> action) {
return execute(action, isExposeConnection());
}
/**
* Executes the given action object within a connection, which can be exposed or not.
*
* @param <T> return type
* @param action callback object that specifies the Redis action
* @param exposeConnection whether to enforce exposure of the native Redis Connection to callback code
* @return object returned by the action
*/
@Nullable
public <T> T execute(RedisCallback<T> action, boolean exposeConnection) {
return execute(action, exposeConnection, false);
}
/**
* Executes the given action object within a connection that can be exposed or not. Additionally, the connection can
* be pipelined. Note the results of the pipeline are discarded (making it suitable for write-only scenarios).
*
* @param <T> return type
* @param action callback object to execute
* @param exposeConnection whether to enforce exposure of the native Redis Connection to callback code
* @param pipeline whether to pipeline or not the connection for the execution
* @return object returned by the action
*/
@Nullable
public <T> T execute(RedisCallback<T> action, boolean exposeConnection, boolean pipeline) {
Assert.isTrue(initialized, "template not initialized; call afterPropertiesSet() before using it");
Assert.notNull(action, "Callback object must not be null");
RedisConnectionFactory factory = getRequiredConnectionFactory();
RedisConnection conn = null;
try {
if (enableTransactionSupport) {
// only bind resources in case of potential transaction synchronization
conn = RedisConnectionUtils.bindConnection(factory, enableTransactionSupport);
} else {
conn = RedisConnectionUtils.getConnection(factory);
}
boolean existingConnection = TransactionSynchronizationManager.hasResource(factory);
RedisConnection connToUse = preProcessConnection(conn, existingConnection);
boolean pipelineStatus = connToUse.isPipelined();
if (pipeline && !pipelineStatus) {
connToUse.openPipeline();
}
RedisConnection connToExpose = (exposeConnection ? connToUse : createRedisConnectionProxy(connToUse));
T result = action.doInRedis(connToExpose);
// close pipeline
if (pipeline && !pipelineStatus) {
connToUse.closePipeline();
}
// TODO: any other connection processing?
return postProcessResult(result, connToUse, existingConnection);
} finally {
RedisConnectionUtils.releaseConnection(conn, factory);
}
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#execute(org.springframework.data.redis.core.SessionCallback)
*/
@Override
public <T> T execute(SessionCallback<T> session) {
Assert.isTrue(initialized, "template not initialized; call afterPropertiesSet() before using it");
Assert.notNull(session, "Callback object must not be null");
RedisConnectionFactory factory = getRequiredConnectionFactory();
// bind connection
RedisConnectionUtils.bindConnection(factory, enableTransactionSupport);
try {
return session.execute(this);
} finally {
RedisConnectionUtils.unbindConnection(factory);
}
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#executePipelined(org.springframework.data.redis.core.SessionCallback)
*/
@Override
public List<Object> executePipelined(SessionCallback<?> session) {
return executePipelined(session, valueSerializer);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#executePipelined(org.springframework.data.redis.core.SessionCallback, org.springframework.data.redis.serializer.RedisSerializer)
*/
@Override
public List<Object> executePipelined(SessionCallback<?> session, @Nullable RedisSerializer<?> resultSerializer) {
Assert.isTrue(initialized, "template not initialized; call afterPropertiesSet() before using it");
Assert.notNull(session, "Callback object must not be null");
RedisConnectionFactory factory = getRequiredConnectionFactory();
// bind connection
RedisConnectionUtils.bindConnection(factory, enableTransactionSupport);
try {
return execute((RedisCallback<List<Object>>) connection -> {
connection.openPipeline();
boolean pipelinedClosed = false;
try {
Object result = executeSession(session);
if (result != null) {
throw new InvalidDataAccessApiUsageException(
"Callback cannot return a non-null value as it gets overwritten by the pipeline");
}
List<Object> closePipeline = connection.closePipeline();
pipelinedClosed = true;
return deserializeMixedResults(closePipeline, resultSerializer, hashKeySerializer, hashValueSerializer);
} finally {
if (!pipelinedClosed) {
connection.closePipeline();
}
}
});
} finally {
RedisConnectionUtils.unbindConnection(factory);
}
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#executePipelined(org.springframework.data.redis.core.RedisCallback)
*/
@Override
public List<Object> executePipelined(RedisCallback<?> action) {
return executePipelined(action, valueSerializer);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#executePipelined(org.springframework.data.redis.core.RedisCallback, org.springframework.data.redis.serializer.RedisSerializer)
*/
@Override
public List<Object> executePipelined(RedisCallback<?> action, @Nullable RedisSerializer<?> resultSerializer) {
return execute((RedisCallback<List<Object>>) connection -> {
connection.openPipeline();
boolean pipelinedClosed = false;
try {
Object result = action.doInRedis(connection);
if (result != null) {
throw new InvalidDataAccessApiUsageException(
"Callback cannot return a non-null value as it gets overwritten by the pipeline");
}
List<Object> closePipeline = connection.closePipeline();
pipelinedClosed = true;
return deserializeMixedResults(closePipeline, resultSerializer, hashKeySerializer, hashValueSerializer);
} finally {
if (!pipelinedClosed) {
connection.closePipeline();
}
}
});
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#execute(org.springframework.data.redis.core.script.RedisScript, java.util.List, java.lang.Object[])
*/
@Override
public <T> T execute(RedisScript<T> script, List<K> keys, Object... args) {
return scriptExecutor.execute(script, keys, args);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#execute(org.springframework.data.redis.core.script.RedisScript, org.springframework.data.redis.serializer.RedisSerializer, org.springframework.data.redis.serializer.RedisSerializer, java.util.List, java.lang.Object[])
*/
@Override
public <T> T execute(RedisScript<T> script, RedisSerializer<?> argsSerializer, RedisSerializer<T> resultSerializer,
List<K> keys, Object... args) {
return scriptExecutor.execute(script, argsSerializer, resultSerializer, keys, args);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#executeWithStickyConnection(org.springframework.data.redis.core.RedisCallback)
*/
@Override
public <T extends Closeable> T executeWithStickyConnection(RedisCallback<T> callback) {
Assert.isTrue(initialized, "template not initialized; call afterPropertiesSet() before using it");
Assert.notNull(callback, "Callback object must not be null");
RedisConnectionFactory factory = getRequiredConnectionFactory();
RedisConnection connection = preProcessConnection(RedisConnectionUtils.doGetConnection(factory, true, false, false),
false);
return callback.doInRedis(connection);
}
private Object executeSession(SessionCallback<?> session) {
return session.execute(this);
}
protected RedisConnection createRedisConnectionProxy(RedisConnection pm) {
Class<?>[] ifcs = ClassUtils.getAllInterfacesForClass(pm.getClass(), getClass().getClassLoader());
return (RedisConnection) Proxy.newProxyInstance(pm.getClass().getClassLoader(), ifcs,
new CloseSuppressingInvocationHandler(pm));
}
/**
* Processes the connection (before any settings are executed on it). Default implementation returns the connection as
* is.
*
* @param connection redis connection
*/
protected RedisConnection preProcessConnection(RedisConnection connection, boolean existingConnection) {
return connection;
}
@Nullable
protected <T> T postProcessResult(@Nullable T result, RedisConnection conn, boolean existingConnection) {
return result;
}
/**
* Returns whether to expose the native Redis connection to RedisCallback code, or rather a connection proxy (the
* default).
*
* @return whether to expose the native Redis connection or not
*/
public boolean isExposeConnection() {
return exposeConnection;
}
/**
* Sets whether to expose the Redis connection to {@link RedisCallback} code. Default is "false": a proxy will be
* returned, suppressing <tt>quit</tt> and <tt>disconnect</tt> calls.
*
* @param exposeConnection
*/
public void setExposeConnection(boolean exposeConnection) {
this.exposeConnection = exposeConnection;
}
/**
* @return Whether or not the default serializer should be used. If not, any serializers not explicitly set will
* remain null and values will not be serialized or deserialized.
*/
public boolean isEnableDefaultSerializer() {
return enableDefaultSerializer;
}
/**
* @param enableDefaultSerializer Whether or not the default serializer should be used. If not, any serializers not
* explicitly set will remain null and values will not be serialized or deserialized.
*/
public void setEnableDefaultSerializer(boolean enableDefaultSerializer) {
this.enableDefaultSerializer = enableDefaultSerializer;
}
/**
* Returns the default serializer used by this template.
*
* @return template default serializer
*/
@Nullable
public RedisSerializer<?> getDefaultSerializer() {
return defaultSerializer;
}
/**
* Sets the default serializer to use for this template. All serializers (expect the
* {@link #setStringSerializer(RedisSerializer)}) are initialized to this value unless explicitly set. Defaults to
* {@link JdkSerializationRedisSerializer}.
*
* @param serializer default serializer to use
*/
public void setDefaultSerializer(RedisSerializer<?> serializer) {
this.defaultSerializer = serializer;
}
/**
* Sets the key serializer to be used by this template. Defaults to {@link #getDefaultSerializer()}.
*
* @param serializer the key serializer to be used by this template.
*/
public void setKeySerializer(RedisSerializer<?> serializer) {
this.keySerializer = serializer;
}
/**
* Returns the key serializer used by this template.
*
* @return the key serializer used by this template.
*/
@Override
public RedisSerializer<?> getKeySerializer() {
return keySerializer;
}
/**
* Sets the value serializer to be used by this template. Defaults to {@link #getDefaultSerializer()}.
*
* @param serializer the value serializer to be used by this template.
*/
public void setValueSerializer(RedisSerializer<?> serializer) {
this.valueSerializer = serializer;
}
/**
* Returns the value serializer used by this template.
*
* @return the value serializer used by this template.
*/
@Override
public RedisSerializer<?> getValueSerializer() {
return valueSerializer;
}
/**
* Returns the hashKeySerializer.
*
* @return Returns the hashKeySerializer
*/
@Override
public RedisSerializer<?> getHashKeySerializer() {
return hashKeySerializer;
}
/**
* Sets the hash key (or field) serializer to be used by this template. Defaults to {@link #getDefaultSerializer()}.
*
* @param hashKeySerializer The hashKeySerializer to set.
*/
public void setHashKeySerializer(RedisSerializer<?> hashKeySerializer) {
this.hashKeySerializer = hashKeySerializer;
}
/**
* Returns the hashValueSerializer.
*
* @return Returns the hashValueSerializer
*/
@Override
public RedisSerializer<?> getHashValueSerializer() {
return hashValueSerializer;
}
/**
* Sets the hash value serializer to be used by this template. Defaults to {@link #getDefaultSerializer()}.
*
* @param hashValueSerializer The hashValueSerializer to set.
*/
public void setHashValueSerializer(RedisSerializer<?> hashValueSerializer) {
this.hashValueSerializer = hashValueSerializer;
}
/**
* Returns the stringSerializer.
*
* @return Returns the stringSerializer
*/
public RedisSerializer<String> getStringSerializer() {
return stringSerializer;
}
/**
* Sets the string value serializer to be used by this template (when the arguments or return types are always
* strings). Defaults to {@link StringRedisSerializer}.
*
* @see ValueOperations#get(Object, long, long)
* @param stringSerializer The stringValueSerializer to set.
*/
public void setStringSerializer(RedisSerializer<String> stringSerializer) {
this.stringSerializer = stringSerializer;
}
/**
* @param scriptExecutor The {@link ScriptExecutor} to use for executing Redis scripts
*/
public void setScriptExecutor(ScriptExecutor<K> scriptExecutor) {
this.scriptExecutor = scriptExecutor;
}
@SuppressWarnings("unchecked")
private byte[] rawKey(Object key) {
Assert.notNull(key, "non null key required");
if (keySerializer == null && key instanceof byte[]) {
return (byte[]) key;
}
return keySerializer.serialize(key);
}
private byte[] rawString(String key) {
return stringSerializer.serialize(key);
}
@SuppressWarnings("unchecked")
private byte[] rawValue(Object value) {
if (valueSerializer == null && value instanceof byte[]) {
return (byte[]) value;
}
return valueSerializer.serialize(value);
}
private byte[][] rawKeys(Collection<K> keys) {
final byte[][] rawKeys = new byte[keys.size()][];
int i = 0;
for (K key : keys) {
rawKeys[i++] = rawKey(key);
}
return rawKeys;
}
@SuppressWarnings("unchecked")
private K deserializeKey(byte[] value) {
return keySerializer != null ? (K) keySerializer.deserialize(value) : (K) value;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@Nullable
private List<Object> deserializeMixedResults(@Nullable List<Object> rawValues,
@Nullable RedisSerializer valueSerializer, @Nullable RedisSerializer hashKeySerializer,
@Nullable RedisSerializer hashValueSerializer) {
if (rawValues == null) {
return null;
}
List<Object> values = new ArrayList<>();
for (Object rawValue : rawValues) {
if (rawValue instanceof byte[] && valueSerializer != null) {
values.add(valueSerializer.deserialize((byte[]) rawValue));
} else if (rawValue instanceof List) {
// Lists are the only potential Collections of mixed values....
values.add(deserializeMixedResults((List) rawValue, valueSerializer, hashKeySerializer, hashValueSerializer));
} else if (rawValue instanceof Set && !(((Set) rawValue).isEmpty())) {
values.add(deserializeSet((Set) rawValue, valueSerializer));
} else if (rawValue instanceof Map && !(((Map) rawValue).isEmpty())
&& ((Map) rawValue).values().iterator().next() instanceof byte[]) {
values.add(SerializationUtils.deserialize((Map) rawValue, hashKeySerializer, hashValueSerializer));
} else {
values.add(rawValue);
}
}
return values;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private Set<?> deserializeSet(Set rawSet, @Nullable RedisSerializer valueSerializer) {
if (rawSet.isEmpty()) {
return rawSet;
}
Object setValue = rawSet.iterator().next();
if (setValue instanceof byte[] && valueSerializer != null) {
return (SerializationUtils.deserialize(rawSet, valueSerializer));
} else if (setValue instanceof Tuple) {
return convertTupleValues(rawSet, valueSerializer);
} else {
return rawSet;
}
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private Set<TypedTuple<V>> convertTupleValues(Set<Tuple> rawValues, @Nullable RedisSerializer valueSerializer) {
Set<TypedTuple<V>> set = new LinkedHashSet<>(rawValues.size());
for (Tuple rawValue : rawValues) {
Object value = rawValue.getValue();
if (valueSerializer != null) {
value = valueSerializer.deserialize(rawValue.getValue());
}
set.add(new DefaultTypedTuple(value, rawValue.getScore()));
}
return set;
}
//
// RedisOperations
//
/**
* Execute a transaction, using the default {@link RedisSerializer}s to deserialize any results that are byte[]s or
* Collections or Maps of byte[]s or Tuples. Other result types (Long, Boolean, etc) are left as-is in the converted
* results. If conversion of tx results has been disabled in the {@link RedisConnectionFactory}, the results of exec
* will be returned without deserialization. This check is mostly for backwards compatibility with 1.0.
*
* @return The (possibly deserialized) results of transaction exec
*/
@Override
public List<Object> exec() {
List<Object> results = execRaw();
if (getRequiredConnectionFactory().getConvertPipelineAndTxResults()) {
return deserializeMixedResults(results, valueSerializer, hashKeySerializer, hashValueSerializer);
} else {
return results;
}
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#exec(org.springframework.data.redis.serializer.RedisSerializer)
*/
@Override
public List<Object> exec(RedisSerializer<?> valueSerializer) {
return deserializeMixedResults(execRaw(), valueSerializer, valueSerializer, valueSerializer);
}
protected List<Object> execRaw() {
List<Object> raw = execute(RedisTxCommands::exec);
return raw == null ? Collections.emptyList() : raw;
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#delete(java.lang.Object)
*/
@Override
public Boolean delete(K key) {
byte[] rawKey = rawKey(key);
Long result = execute(connection -> connection.del(rawKey), true);
return result != null && result.intValue() == 1;
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#delete(java.util.Collection)
*/
@Override
public Long delete(Collection<K> keys) {
if (CollectionUtils.isEmpty(keys)) {
return 0L;
}
byte[][] rawKeys = rawKeys(keys);
return execute(connection -> connection.del(rawKeys), true);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#unlink(java.lang.Object)
*/
@Override
public Boolean unlink(K key) {
byte[] rawKey = rawKey(key);
Long result = execute(connection -> connection.unlink(rawKey), true);
return result != null && result.intValue() == 1;
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#unlink(java.util.Collection)
*/
@Override
public Long unlink(Collection<K> keys) {
if (CollectionUtils.isEmpty(keys)) {
return 0L;
}
byte[][] rawKeys = rawKeys(keys);
return execute(connection -> connection.unlink(rawKeys), true);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#hasKey(java.lang.Object)
*/
@Override
public Boolean hasKey(K key) {
byte[] rawKey = rawKey(key);
return execute(connection -> connection.exists(rawKey), true);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#countExistingKeys(java.util.Collection)
*/
@Override
public Long countExistingKeys(Collection<K> keys) {
Assert.notNull(keys, "Keys must not be null!");
byte[][] rawKeys = rawKeys(keys);
return execute(connection -> connection.exists(rawKeys), true);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#expire(java.lang.Object, long, java.util.concurrent.TimeUnit)
*/
@Override
public Boolean expire(K key, final long timeout, final TimeUnit unit) {
byte[] rawKey = rawKey(key);
long rawTimeout = TimeoutUtils.toMillis(timeout, unit);
return execute(connection -> {
try {
return connection.pExpire(rawKey, rawTimeout);
} catch (Exception e) {
// Driver may not support pExpire or we may be running on Redis 2.4
return connection.expire(rawKey, TimeoutUtils.toSeconds(timeout, unit));
}
}, true);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#expireAt(java.lang.Object, java.util.Date)
*/
@Override
public Boolean expireAt(K key, final Date date) {
byte[] rawKey = rawKey(key);
return execute(connection -> {
try {
return connection.pExpireAt(rawKey, date.getTime());
} catch (Exception e) {
return connection.expireAt(rawKey, date.getTime() / 1000);
}
}, true);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#convertAndSend(java.lang.String, java.lang.Object)
*/
@Override
public void convertAndSend(String channel, Object message) {
Assert.hasText(channel, "a non-empty channel is required");
byte[] rawChannel = rawString(channel);
byte[] rawMessage = rawValue(message);
execute(connection -> {
connection.publish(rawChannel, rawMessage);
return null;
}, true);
}
//
// Value operations
//
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#getExpire(java.lang.Object)
*/
@Override
public Long getExpire(K key) {
byte[] rawKey = rawKey(key);
return execute(connection -> connection.ttl(rawKey), true);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#getExpire(java.lang.Object, java.util.concurrent.TimeUnit)
*/
@Override
public Long getExpire(K key, final TimeUnit timeUnit) {
byte[] rawKey = rawKey(key);
return execute(connection -> {
try {
return connection.pTtl(rawKey, timeUnit);
} catch (Exception e) {
// Driver may not support pTtl or we may be running on Redis 2.4
return connection.ttl(rawKey, timeUnit);
}
}, true);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#keys(java.lang.Object)
*/
@Override
@SuppressWarnings("unchecked")
public Set<K> keys(K pattern) {
byte[] rawKey = rawKey(pattern);
Set<byte[]> rawKeys = execute(connection -> connection.keys(rawKey), true);
return keySerializer != null ? SerializationUtils.deserialize(rawKeys, keySerializer) : (Set<K>) rawKeys;
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#persist(java.lang.Object)
*/
@Override
public Boolean persist(K key) {
byte[] rawKey = rawKey(key);
return execute(connection -> connection.persist(rawKey), true);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#move(java.lang.Object, int)
*/
@Override
public Boolean move(K key, final int dbIndex) {
byte[] rawKey = rawKey(key);
return execute(connection -> connection.move(rawKey, dbIndex), true);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#randomKey()
*/
@Override
public K randomKey() {
byte[] rawKey = execute(RedisKeyCommands::randomKey, true);
return deserializeKey(rawKey);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#rename(java.lang.Object, java.lang.Object)
*/
@Override
public void rename(K oldKey, K newKey) {
byte[] rawOldKey = rawKey(oldKey);
byte[] rawNewKey = rawKey(newKey);
execute(connection -> {
connection.rename(rawOldKey, rawNewKey);
return null;
}, true);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#renameIfAbsent(java.lang.Object, java.lang.Object)
*/
@Override
public Boolean renameIfAbsent(K oldKey, K newKey) {
byte[] rawOldKey = rawKey(oldKey);
byte[] rawNewKey = rawKey(newKey);
return execute(connection -> connection.renameNX(rawOldKey, rawNewKey), true);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#type(java.lang.Object)
*/
@Override
public DataType type(K key) {
byte[] rawKey = rawKey(key);
return execute(connection -> connection.type(rawKey), true);
}
/**
* Executes the Redis dump command and returns the results. Redis uses a non-standard serialization mechanism and
* includes checksum information, thus the raw bytes are returned as opposed to deserializing with valueSerializer.
* Use the return value of dump as the value argument to restore
*
* @param key The key to dump
* @return results The results of the dump operation
*/
@Override
public byte[] dump(K key) {
byte[] rawKey = rawKey(key);
return execute(connection -> connection.dump(rawKey), true);
}
/**
* Executes the Redis restore command. The value passed in should be the exact serialized data returned from
* {@link #dump(Object)}, since Redis uses a non-standard serialization mechanism.
*
* @param key The key to restore
* @param value The value to restore, as returned by {@link #dump(Object)}
* @param timeToLive An expiration for the restored key, or 0 for no expiration
* @param unit The time unit for timeToLive
* @param replace use {@literal true} to replace a potentially existing value instead of erroring.
* @throws RedisSystemException if the key you are attempting to restore already exists and {@code replace} is set to
* {@literal false}.
*/
@Override
public void restore(K key, final byte[] value, long timeToLive, TimeUnit unit, boolean replace) {
byte[] rawKey = rawKey(key);
long rawTimeout = TimeoutUtils.toMillis(timeToLive, unit);
execute(connection -> {
connection.restore(rawKey, rawTimeout, value, replace);
return null;
}, true);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#multi()
*/
@Override
public void multi() {
execute(connection -> {
connection.multi();
return null;
}, true);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#discard()
*/
@Override
public void discard() {
execute(connection -> {
connection.discard();
return null;
}, true);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#watch(java.lang.Object)
*/
@Override
public void watch(K key) {
byte[] rawKey = rawKey(key);
execute(connection -> {
connection.watch(rawKey);
return null;
}, true);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#watch(java.util.Collection)
*/
@Override
public void watch(Collection<K> keys) {
byte[][] rawKeys = rawKeys(keys);
execute(connection -> {
connection.watch(rawKeys);
return null;
}, true);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#unwatch()
*/
@Override
public void unwatch() {
execute(connection -> {
connection.unwatch();
return null;
}, true);
}
// Sort operations
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#sort(org.springframework.data.redis.core.query.SortQuery)
*/
@Override
@SuppressWarnings("unchecked")
public List<V> sort(SortQuery<K> query) {
return sort(query, valueSerializer);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#sort(org.springframework.data.redis.core.query.SortQuery, org.springframework.data.redis.serializer.RedisSerializer)
*/
@Override
public <T> List<T> sort(SortQuery<K> query, @Nullable RedisSerializer<T> resultSerializer) {
byte[] rawKey = rawKey(query.getKey());
SortParameters params = QueryUtils.convertQuery(query, stringSerializer);
List<byte[]> vals = execute(connection -> connection.sort(rawKey, params), true);
return SerializationUtils.deserialize(vals, resultSerializer);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#sort(org.springframework.data.redis.core.query.SortQuery, org.springframework.data.redis.core.BulkMapper)
*/
@Override
@SuppressWarnings("unchecked")
public <T> List<T> sort(SortQuery<K> query, BulkMapper<T, V> bulkMapper) {
return sort(query, bulkMapper, valueSerializer);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#sort(org.springframework.data.redis.core.query.SortQuery, org.springframework.data.redis.core.BulkMapper, org.springframework.data.redis.serializer.RedisSerializer)
*/
@Override
public <T, S> List<T> sort(SortQuery<K> query, BulkMapper<T, S> bulkMapper,
@Nullable RedisSerializer<S> resultSerializer) {
List<S> values = sort(query, resultSerializer);
if (values == null || values.isEmpty()) {
return Collections.emptyList();
}
int bulkSize = query.getGetPattern().size();
List<T> result = new ArrayList<>(values.size() / bulkSize + 1);
List<S> bulk = new ArrayList<>(bulkSize);
for (S s : values) {
bulk.add(s);
if (bulk.size() == bulkSize) {
result.add(bulkMapper.mapBulk(Collections.unmodifiableList(bulk)));
// create a new list (we could reuse the old one but the client might hang on to it for some reason)
bulk = new ArrayList<>(bulkSize);
}
}
return result;
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#sort(org.springframework.data.redis.core.query.SortQuery, java.lang.Object)
*/
@Override
public Long sort(SortQuery<K> query, K storeKey) {
byte[] rawStoreKey = rawKey(storeKey);
byte[] rawKey = rawKey(query.getKey());
SortParameters params = QueryUtils.convertQuery(query, stringSerializer);
return execute(connection -> connection.sort(rawKey, params, rawStoreKey), true);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#killClient(java.lang.Object)
*/
@Override
public void killClient(final String host, final int port) {
execute((RedisCallback<Void>) connection -> {
connection.killClient(host, port);
return null;
});
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#getClientList()
*/
@Override
public List<RedisClientInfo> getClientList() {
return execute(RedisServerCommands::getClientList);
}
/*
* @see org.springframework.data.redis.core.RedisOperations#slaveOf(java.lang.String, int)
*/
@Override
public void slaveOf(final String host, final int port) {
execute((RedisCallback<Void>) connection -> {
connection.slaveOf(host, port);
return null;
});
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#slaveOfNoOne()
*/
@Override
public void slaveOfNoOne() {
execute((RedisCallback<Void>) connection -> {
connection.slaveOfNoOne();
return null;
});
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#opsForCluster()
*/
@Override
public ClusterOperations<K, V> opsForCluster() {
return new DefaultClusterOperations<>(this);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#opsForGeo()
*/
@Override
public GeoOperations<K, V> opsForGeo() {
if (geoOps == null) {
geoOps = new DefaultGeoOperations<>(this);
}
return geoOps;
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#boundGeoOps(java.lang.Object)
*/
@Override
public BoundGeoOperations<K, V> boundGeoOps(K key) {
return new DefaultBoundGeoOperations<>(key, this);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#boundHashOps(java.lang.Object)
*/
@Override
public <HK, HV> BoundHashOperations<K, HK, HV> boundHashOps(K key) {
return new DefaultBoundHashOperations<>(key, this);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#opsForHash()
*/
@Override
public <HK, HV> HashOperations<K, HK, HV> opsForHash() {
return new DefaultHashOperations<>(this);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#opsForHyperLogLog()
*/
@Override
public HyperLogLogOperations<K, V> opsForHyperLogLog() {
if (hllOps == null) {
hllOps = new DefaultHyperLogLogOperations<>(this);
}
return hllOps;
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#opsForList()
*/
@Override
public ListOperations<K, V> opsForList() {
if (listOps == null) {
listOps = new DefaultListOperations<>(this);
}
return listOps;
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#boundListOps(java.lang.Object)
*/
@Override
public BoundListOperations<K, V> boundListOps(K key) {
return new DefaultBoundListOperations<>(key, this);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#boundSetOps(java.lang.Object)
*/
@Override
public BoundSetOperations<K, V> boundSetOps(K key) {
return new DefaultBoundSetOperations<>(key, this);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#opsForSet()
*/
@Override
public SetOperations<K, V> opsForSet() {
if (setOps == null) {
setOps = new DefaultSetOperations<>(this);
}
return setOps;
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#boundValueOps(java.lang.Object)
*/
@Override
public BoundValueOperations<K, V> boundValueOps(K key) {
return new DefaultBoundValueOperations<>(key, this);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#opsForValue()
*/
@Override
public ValueOperations<K, V> opsForValue() {
if (valueOps == null) {
valueOps = new DefaultValueOperations<>(this);
}
return valueOps;
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#boundZSetOps(java.lang.Object)
*/
@Override
public BoundZSetOperations<K, V> boundZSetOps(K key) {
return new DefaultBoundZSetOperations<>(key, this);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#opsForZSet()
*/
@Override
public ZSetOperations<K, V> opsForZSet() {
if (zSetOps == null) {
zSetOps = new DefaultZSetOperations<>(this);
}
return zSetOps;
}
/**
* If set to {@code true} {@link RedisTemplate} will use {@literal MULTI...EXEC|DISCARD} to keep track of operations.
*
* @param enableTransactionSupport
* @since 1.3
*/
public void setEnableTransactionSupport(boolean enableTransactionSupport) {
this.enableTransactionSupport = enableTransactionSupport;
}
/**
* Set the {@link ClassLoader} to be used for the default {@link JdkSerializationRedisSerializer} in case no other
* {@link RedisSerializer} is explicitly set as the default one.
*
* @param classLoader can be {@literal null}.
* @see org.springframework.beans.factory.BeanClassLoaderAware#setBeanClassLoader
* @since 1.8
*/
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
}
我们看看谁调用了RedisTemplate的构造方法
进入源码
/*
* Copyright 2012-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.data.redis;
import java.net.UnknownHostException;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
/**
* {@link EnableAutoConfiguration Auto-configuration} for Spring Data's Redis support.
*
* @author Dave Syer
* @author Andy Wilkinson
* @author Christian Dupuis
* @author Christoph Strobl
* @author Phillip Webb
* @author Eddú Meléndez
* @author Stephane Nicoll
* @author Marco Aust
* @author Mark Paluch
*/
@Configuration
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean(name = "redisTemplate")
public RedisTemplate<Object, Object> redisTemplate(
RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
@Bean
@ConditionalOnMissingBean
public StringRedisTemplate stringRedisTemplate(
RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}
这里我们很清楚的看到spring默认配置的redisTemplate。即RedisTemplate<Object, Object>
那我们更改我们测试类的RedisTemplate引用
package org.chenhui.study.springbootredis;
import org.chenhui.study.springbootredis.entity.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBootRedisApplicationTests {
@Autowired
private RedisTemplate<Object, Object> redisTemplate;
@Test
public void contextLoads() {
User user = new User(2l, "张san");
redisTemplate.opsForValue().set("user", user);
User user1 = (User) redisTemplate.opsForValue().get("user");
System.out.println(user1);
}
}
再次运行
我们可以查看redis中的数据进一步确认
二、pub/sub
spring boot为我们提供了一个消息监听容器org.springframework.data.redis.listener.RedisMessageListenerContainer
这个类为Redis消息侦听器提供异步行为的容器。处理侦听、转换和消息分派的低级细节。
1、那我们就来配置一个ListenerContainer
package org.chenhui.study.springbootredis.redis.config;
import org.chenhui.study.springbootredis.redis.message.Listener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
@Configuration
public class ListenerContainer {
@Autowired
private Listener listener;
/**
* 将RedisMessageListenerContainer注册到springbean
*
* @param redisConnectionFactory
* @param adapter
* @return
*/
@Bean
public RedisMessageListenerContainer redisMessageListenerContainer(RedisConnectionFactory redisConnectionFactory,
MessageListenerAdapter adapter){
RedisMessageListenerContainer redisMessageListenerContainer = new RedisMessageListenerContainer();
//配置redis连接信息
redisMessageListenerContainer.setConnectionFactory(redisConnectionFactory);
//订阅一个匹配(支持Ant通配符)message-*的通道
//这里可以添加多个消息监听
redisMessageListenerContainer.addMessageListener(adapter, new PatternTopic("message-*"));
return redisMessageListenerContainer;
}
/**
* 消息侦听器适配器,
* 它通过反射将消息处理委托给目标侦听器方法,具有灵活的消息类型转换。
* 允许侦听器方法操作消息内容类型,完全独立于Redis API。
*
* @return
*/
@Bean
public MessageListenerAdapter adapter(){
//这里的onMessage必须与listener方法名保持一致
return new MessageListenerAdapter(listener, "onMessage");
}
/**
* 弦聚焦的RedisTemplate延伸。
* 由于针对Redis的大多数操作都是基于字符串的,因此该类提供了一个专用类,可以最小化其更通用模板的配置,尤其是在序列化器方面。
* @return
*/
@Bean
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory){
return new StringRedisTemplate(redisConnectionFactory);
}
}
2、自定义一个消息接收器
package org.chenhui.study.springbootredis.redis.message;
import org.springframework.stereotype.Component;
/**
* 消息监听
*
* @author chenhui
* @time 2018年12月19日
* @e-mail personalmessage@foxmail.com
* @company nikey
*/
@Component
public class Listener {
//自定义一个方法用于接收消息
public void onMessage(String message) {
System.out.println("receiver : " + message);
}
}
至此,我们消息监听就完成了。我们通过redis订阅一个匹配(支持Ant通配符)message-*的通道,只要这个管道发布了消息我们的listener就会接收到发布的消息。
下面我们测试
package org.chenhui.study.springbootredis;
import org.chenhui.study.springbootredis.entity.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBootRedisApplicationTests {
@Autowired
private StringRedisTemplate StringRedisTemplate;
// @Test
// public void contextLoads() {
// User user = new User(2l, "张san");
// redisTemplate.opsForValue().set("user", user);
// User user1 = (User) redisTemplate.opsForValue().get("user");
// System.out.println(user1);
// }
@Test
public void pubMessage(){
//我们向管道(或者说频道)message-test发布一条消息
StringRedisTemplate.convertAndSend("message-test", "this is a message from message-test");
}
}
我们listener成功接收到了redis向message-test管道发布的消息。