背景介紹 公司最近的新項目在進行技術框架升級,基於的Spring Boot的版本是2.0.2,整合Redis數據庫。網上基於2.X版本的整個Redis少之又少,中間踩了很多坑,特此把整合過程記錄,以供小夥伴們參考。 本文的基於在於會搭建Spring Boot項目的基礎上進行的,入門是小白的話,請自行學習相關基礎知識,網上或相關書籍不少。 因爲我本人對Maven比較熟悉,因此是以Maven進行的。Gradle相似,核心思想都是同樣的,實現項目管理工具不一樣而已。 整合過程 建立Spring Boot項目(2.0.2版本) 利用idea提供的接口進行建立,建立後目錄結構以下:(請忽略mybatis.log4j2等相關代碼和文件) pom依賴 <!-- Spring Boot Redis依賴 --> <!-- 注意:1.5版本的依賴和2.0的依賴不同,注意看哦 1.5我記得名字裏面應該沒有「data」, 2.0必須是「spring-boot-starter-data-redis」 這個才行--> <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> </dependency> <!--spring2.0集成redis所需common-pool2--> <!-- 必須加上,jedis依賴此 --> <!-- spring boot 2.0 的操做手冊有標註 你們能夠去看看 地址是:https://docs.spring.io/spring-boot/docs/2.0.3.RELEASE/reference/htmlsingle/--> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> <version>2.5.0</version> </dependency> <!-- 將做爲Redis對象序列化器 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.47</version> </dependency> yml相關Redis配置 其實關於Redis的配置主要包括兩方面,一時Redis的配置,一個是jedis pool鏈接池的配置 具體配置以下 Redis自定義配置 關於Redis的配置方式有不少,我知道有1.自動配置;2.手動配置;3.傳統的xml文件也是能夠的。在這裏我只講第2中,第二種比較靈活,符合spring boot風格。 新建config包 新建RedisConfiguration類 package com.cherry.framework.config; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.cache.Cache; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.CachingConfigurerSupport; import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.interceptor.CacheErrorHandler; import org.springframework.cache.interceptor.KeyGenerator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.cache.RedisCacheManager; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; /** * Redis 配置類 * * @author Leon * @version 2018/6/17 17:46 */ @Configuration // 必須加,使配置生效 @EnableCaching public class RedisConfiguration extends CachingConfigurerSupport { /** * Logger */ private static final Logger lg = LoggerFactory.getLogger(RedisConfiguration.class); @Autowired private JedisConnectionFactory jedisConnectionFactory; @Bean @Override public KeyGenerator keyGenerator() { // 設置自動key的生成規則,配置spring boot的註解,進行方法級別的緩存 // 使用:進行分割,能夠不少顯示出層級關係 // 這裏其實就是new了一個KeyGenerator對象,只是這是lambda表達式的寫法,我感受很好用,你們感興趣能夠去了解下 return (target, method, params) -> { StringBuilder sb = new StringBuilder(); sb.append(target.getClass().getName()); sb.append(":"); sb.append(method.getName()); for (Object obj : params) { sb.append(":" + String.valueOf(obj)); } String rsToUse = String.valueOf(sb); lg.info("自動生成Redis Key -> [{}]", rsToUse); return rsToUse; }; } @Bean @Override public CacheManager cacheManager() { // 初始化緩存管理器,在這裏咱們能夠緩存的總體過時時間什麼的,我這裏默認沒有配置 lg.info("初始化 -> [{}]", "CacheManager RedisCacheManager Start"); RedisCacheManager.RedisCacheManagerBuilder builder = RedisCacheManager .RedisCacheManagerBuilder .fromConnectionFactory(jedisConnectionFactory); return builder.build(); } @Bean public RedisTemplate<String, Object> redisTemplate(JedisConnectionFactory jedisConnectionFactory ) { //設置序列化 Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); // 配置redisTemplate RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>(); redisTemplate.setConnectionFactory(jedisConnectionFactory); RedisSerializer stringSerializer = new StringRedisSerializer(); redisTemplate.setKeySerializer(stringSerializer); // key序列化 redisTemplate.setValueSerializer(jackson2JsonRedisSerializer); // value序列化 redisTemplate.setHashKeySerializer(stringSerializer); // Hash key序列化 redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer); // Hash value序列化 redisTemplate.afterPropertiesSet(); return redisTemplate; } @Override @Bean public CacheErrorHandler errorHandler() { // 異常處理,當Redis發生異常時,打印日誌,可是程序正常走 lg.info("初始化 -> [{}]", "Redis CacheErrorHandler"); CacheErrorHandler cacheErrorHandler = new CacheErrorHandler() { @Override public void handleCacheGetError(RuntimeException e, Cache cache, Object key) { lg.error("Redis occur handleCacheGetError:key -> [{}]", key, e); } @Override public void handleCachePutError(RuntimeException e, Cache cache, Object key, Object value) { lg.error("Redis occur handleCachePutError:key -> [{}];value -> [{}]", key, value, e); } @Override public void handleCacheEvictError(RuntimeException e, Cache cache, Object key) { lg.error("Redis occur handleCacheEvictError:key -> [{}]", key, e); } @Override public void handleCacheClearError(RuntimeException e, Cache cache) { lg.error("Redis occur handleCacheClearError:", e); } }; return cacheErrorHandler; } /** * 此內部類就是把yml的配置數據,進行讀取,建立JedisConnectionFactory和JedisPool,以供外部類初始化緩存管理器使用 * 不瞭解的同窗能夠去看@ConfigurationProperties和@Value的做用 * */ @ConfigurationProperties class DataJedisProperties{ @Value("${spring.redis.host}") private String host; @Value("${spring.redis.password}") private String password; @Value("${spring.redis.port}") private int port; @Value("${spring.redis.timeout}") private int timeout; @Value("${spring.redis.jedis.pool.max-idle}") private int maxIdle; @Value("${spring.redis.jedis.pool.max-wait}") private long maxWaitMillis; @Bean JedisConnectionFactory jedisConnectionFactory() { lg.info("Create JedisConnectionFactory successful"); JedisConnectionFactory factory = new JedisConnectionFactory(); factory.setHostName(host); factory.setPort(port); factory.setTimeout(timeout); factory.setPassword(password); return factory; } @Bean public JedisPool redisPoolFactory() { lg.info("JedisPool init successful,host -> [{}];port -> [{}]", host, port); JedisPoolConfig jedisPoolConfig = new JedisPoolConfig(); jedisPoolConfig.setMaxIdle(maxIdle); jedisPoolConfig.setMaxWaitMillis(maxWaitMillis); JedisPool jedisPool = new JedisPool(jedisPoolConfig, host, port, timeout, password); return jedisPool; } } } 整合測試 在UserService的實現類中(業務層)進行緩存測試,注入RedisTemplate或StringRedisTemplate均可以 package com.cherry.framework.service.impl; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.cherry.framework.dao.UserEntityMapper; import com.cherry.framework.model.UserEntity; import com.cherry.framework.service.UserService; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.List; /** * User ServiceImpl * * @author Leon * @version 2018/6/14 17:12 */ @Service public class UserServiceImpl implements UserService { @Autowired UserEntityMapper userEntityMapper; @Autowired RedisTemplate redisTemplate; @Autowired StringRedisTemplate stringRedisTemplate; /** * 新增 * * @param userEntity * @return */ @Override @Transactional public int save(UserEntity userEntity) { userEntityMapper.insert(userEntity); return userEntity.getUserId(); } /** * 查詢全部 * * @return */ @Override public PageInfo<UserEntity> findAllUserList(int pageNum, int pageSize) { PageHelper.startPage(pageNum, pageSize); List<UserEntity> list = userEntityMapper.selectAll(); PageInfo<UserEntity> pageInfo = new PageInfo<>(list); // 具體使用 redisTemplate.opsForList().leftPush("user:list", JSON.toJSONString(list)); stringRedisTemplate.opsForValue().set("user:name", "張三"); return pageInfo; } } 使用postman訪問對象controller的url /** * 列表查詢 * * @return */ @RequestMapping(value = "/user/list") public PageInfo<UserEntity> findUserList(int pageNum, int pageSize) { PageInfo<UserEntity> pageInfo = userService.findAllUserList(pageNum, pageSize); return pageInfo; } 端口配置以下 server: port: 8080 servlet: path: / 訪問url 經過Redis Desktop Manager 進行查看 總結 2.0整合在不少方面和1.5版本不同,若是有問題參考官方英文文檔,能夠大大提升咱們效率,(畢竟東西剛出,又沒人翻譯,只能看原版文檔) 若是有說的不清楚的地方,在下面留言,我天天都會看博客,一塊兒交流學習 最後曬出最後的整體結構圖 Github地址:Spring Boot 2.X 整合Redis https://github.com/gyoomi/framework.git