一、前言 之前分享过关于Redis集群如何搭建的,最近有小伙伴儿说分享一下Redis如何使用SpringBoot的整合,项目中经常使用的就是Redis,本次整合的是Redis单机版,后续会分享Redis集群版本,请多提出自己的意见。
二、开始整合 1.首先需要搭建Redis服务器,可参考之前的博客() 2019/04/26/Redis的搭建(win和linux版)
2.搭建SpringBoot工程,参考之前的博客 SpringBoot工程搭建
3.在pom文件加入redis的依赖和Json相关依赖 1 2 3 4 5 6 7 8 9 10 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-data-redis</artifactId > </dependency > <dependency > <groupId > com.alibaba</groupId > <artifactId > fastjson</artifactId > <version > 1.2.38</version > </dependency >
4.创建项目结构,结构如下图所示
5.项目全局配置文件application.properties文件配置Redis的相关配置 如下问全部的配置,因为我的redis没有设置密码,故password被我注释掉了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 #项目启动端口 server.port=8088 #应用上下文 server.context-path = /SpringBootRedis #redis相关配置 # Redis数据库索引(默认为0) spring.redis.database=0 # Redis服务器地址 spring.redis.host=127.0.0.1 # Redis服务器连接端口 spring.redis.port=6379 # Redis服务器连接密码(默认为空) #spring.redis.password= # 连接池最大连接数(使用负值表示没有限制) spring.redis.pool.max-active=200 # 连接池最大阻塞等待时间(使用负值表示没有限制) spring.redis.pool.max-wait=-1 # 连接池中的最大空闲连接 spring.redis.pool.max-idle=10 # 连接池中的最小空闲连接 spring.redis.pool.min-idle=0 # 连接超时时间(毫秒) spring.redis.timeout=1000
6.配置redis的配置文件,使用RedisTemplate进行操作,需要将数据的进行序列化,才不会出现乱码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 package com.yang.config.redis;import com.fasterxml.jackson.annotation.JsonAutoDetect;import com.fasterxml.jackson.annotation.PropertyAccessor;import com.fasterxml.jackson.databind.ObjectMapper;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.RedisTemplate;import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;import org.springframework.data.redis.serializer.StringRedisSerializer;@Configuration public class RedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate (RedisConnectionFactory factory) { RedisTemplate<String, Object> template = new RedisTemplate<String, Object>(); template.setConnectionFactory(factory); 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); StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); template.setKeySerializer(stringRedisSerializer); template.setHashKeySerializer(stringRedisSerializer); template.setValueSerializer(jackson2JsonRedisSerializer); template.setHashValueSerializer(jackson2JsonRedisSerializer); template.afterPropertiesSet(); return template; } }
7.编写redis工具类,供开发使用,注入RedisTemplate进行操作 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 package com.yang.config.redis;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Configuration;import org.springframework.data.redis.core.RedisTemplate;import java.util.concurrent.TimeUnit;@Configuration public class RedisUtil { @Autowired private RedisTemplate<String,Object> redisTemplate; public void set (String key , Object value) { redisTemplate.opsForValue().set(key,value); } public void set (String key , Object value , int exp,TimeUnit s) { if ( s==null ){ s = TimeUnit.SECONDS; } redisTemplate.opsForValue().set(key,value,exp, s); } public <T>T get (String key) { return (T)redisTemplate.opsForValue().get(key); } }
8.编写RedisController,编写set和get,使用请求来存储redis的值和获取redis的值 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 package com.yang.controller;import com.yang.config.redis.RedisUtil;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;@RestController @RequestMapping ("/redis" )public class RedisController { @Autowired private RedisUtil redisUtil; @GetMapping ("/get" ) public String get (@RequestParam(value="key" ) String key) { return redisUtil.get(key).toString(); } @GetMapping ("/put" ) public String put (@RequestParam(value="key" ) String key,@RequestParam (value="value" ) String value) { redisUtil.set(key,value); return "success" ; } }
9.使用浏览器访问接口保存数据,并查询数据
三、加载机制剖析 1.经过查看,Redis的包中,包含RedisAutoConfiguration这个配置类,使用了Configuration注解,SpringBoot会自动加载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 package org.springframework.boot.autoconfigure.data.redis;import java.net.URI;import java.net.URISyntaxException;import java.net.UnknownHostException;import java.util.ArrayList;import java.util.List;import org.apache.commons.pool2.impl.GenericObjectPool;import org.springframework.beans.factory.ObjectProvider;import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;import org.springframework.boot.autoconfigure.data.redis.RedisProperties.Cluster;import org.springframework.boot.autoconfigure.data.redis.RedisProperties.Pool;import org.springframework.boot.autoconfigure.data.redis.RedisProperties.Sentinel;import org.springframework.boot.context.properties.EnableConfigurationProperties;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.data.redis.connection.RedisClusterConfiguration;import org.springframework.data.redis.connection.RedisConnectionFactory;import org.springframework.data.redis.connection.RedisNode;import org.springframework.data.redis.connection.RedisSentinelConfiguration;import org.springframework.data.redis.connection.jedis.JedisConnection;import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;import org.springframework.data.redis.core.RedisOperations;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.core.StringRedisTemplate;import org.springframework.util.Assert;import org.springframework.util.StringUtils;import redis.clients.jedis.Jedis;import redis.clients.jedis.JedisPoolConfig;@Configuration @ConditionalOnClass ({JedisConnection.class, RedisOperations.class, Jedis.class})@EnableConfigurationProperties ({RedisProperties.class})public class RedisAutoConfiguration { public RedisAutoConfiguration () { } @Configuration protected static class RedisConfiguration { protected RedisConfiguration () { } @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 ({StringRedisTemplate.class}) public StringRedisTemplate stringRedisTemplate (RedisConnectionFactory redisConnectionFactory) throws UnknownHostException { StringRedisTemplate template = new StringRedisTemplate(); template.setConnectionFactory(redisConnectionFactory); return template; } } @Configuration @ConditionalOnClass ({GenericObjectPool.class}) protected static class RedisConnectionConfiguration { private final RedisProperties properties; private final RedisSentinelConfiguration sentinelConfiguration; private final RedisClusterConfiguration clusterConfiguration; public RedisConnectionConfiguration (RedisProperties properties, ObjectProvider<RedisSentinelConfiguration> sentinelConfiguration, ObjectProvider<RedisClusterConfiguration> clusterConfiguration) { this .properties = properties; this .sentinelConfiguration = (RedisSentinelConfiguration)sentinelConfiguration.getIfAvailable(); this .clusterConfiguration = (RedisClusterConfiguration)clusterConfiguration.getIfAvailable(); } @Bean @ConditionalOnMissingBean ({RedisConnectionFactory.class}) public JedisConnectionFactory redisConnectionFactory () throws UnknownHostException { return this .applyProperties(this .createJedisConnectionFactory()); } protected final JedisConnectionFactory applyProperties (JedisConnectionFactory factory) { this .configureConnection(factory); if (this .properties.isSsl()) { factory.setUseSsl(true ); } factory.setDatabase(this .properties.getDatabase()); if (this .properties.getTimeout() > 0 ) { factory.setTimeout(this .properties.getTimeout()); } return factory; } private void configureConnection (JedisConnectionFactory factory) { if (StringUtils.hasText(this .properties.getUrl())) { this .configureConnectionFromUrl(factory); } else { factory.setHostName(this .properties.getHost()); factory.setPort(this .properties.getPort()); if (this .properties.getPassword() != null ) { factory.setPassword(this .properties.getPassword()); } } } private void configureConnectionFromUrl (JedisConnectionFactory factory) { String url = this .properties.getUrl(); if (url.startsWith("rediss://" )) { factory.setUseSsl(true ); } try { URI uri = new URI(url); factory.setHostName(uri.getHost()); factory.setPort(uri.getPort()); if (uri.getUserInfo() != null ) { String password = uri.getUserInfo(); int index = password.lastIndexOf(":" ); if (index >= 0 ) { password = password.substring(index + 1 ); } factory.setPassword(password); } } catch (URISyntaxException var6) { throw new IllegalArgumentException("Malformed 'spring.redis.url' " + url, var6); } } protected final RedisSentinelConfiguration getSentinelConfig () { if (this .sentinelConfiguration != null ) { return this .sentinelConfiguration; } else { Sentinel sentinelProperties = this .properties.getSentinel(); if (sentinelProperties != null ) { RedisSentinelConfiguration config = new RedisSentinelConfiguration(); config.master(sentinelProperties.getMaster()); config.setSentinels(this .createSentinels(sentinelProperties)); return config; } else { return null ; } } } protected final RedisClusterConfiguration getClusterConfiguration () { if (this .clusterConfiguration != null ) { return this .clusterConfiguration; } else if (this .properties.getCluster() == null ) { return null ; } else { Cluster clusterProperties = this .properties.getCluster(); RedisClusterConfiguration config = new RedisClusterConfiguration(clusterProperties.getNodes()); if (clusterProperties.getMaxRedirects() != null ) { config.setMaxRedirects(clusterProperties.getMaxRedirects().intValue()); } return config; } } private List<RedisNode> createSentinels (Sentinel sentinel) { List<RedisNode> nodes = new ArrayList(); String[] var3 = StringUtils.commaDelimitedListToStringArray(sentinel.getNodes()); int var4 = var3.length; for (int var5 = 0 ; var5 < var4; ++var5) { String node = var3[var5]; try { String[] parts = StringUtils.split(node, ":" ); Assert.state(parts.length == 2 , "Must be defined as 'host:port'" ); nodes.add(new RedisNode(parts[0 ], Integer.valueOf(parts[1 ]).intValue())); } catch (RuntimeException var8) { throw new IllegalStateException("Invalid redis sentinel property '" + node + "'" , var8); } } return nodes; } private JedisConnectionFactory createJedisConnectionFactory () { JedisPoolConfig poolConfig = this .properties.getPool() != null ? this .jedisPoolConfig() : new JedisPoolConfig(); if (this .getSentinelConfig() != null ) { return new JedisConnectionFactory(this .getSentinelConfig(), poolConfig); } else { return this .getClusterConfiguration() != null ? new JedisConnectionFactory(this .getClusterConfiguration(), poolConfig) : new JedisConnectionFactory(poolConfig); } } private JedisPoolConfig jedisPoolConfig () { JedisPoolConfig config = new JedisPoolConfig(); Pool props = this .properties.getPool(); config.setMaxTotal(props.getMaxActive()); config.setMaxIdle(props.getMaxIdle()); config.setMinIdle(props.getMinIdle()); config.setMaxWaitMillis((long )props.getMaxWait()); return config; } } }
2.配置了EnableConfigurationProperties,配置了RedisProperties,而RedisProperties则使用了ConfigurationProperties,加载了前缀为spring.redis的所有配置,故读取了application.properties文件中的内容。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 package org.springframework.boot.autoconfigure.data.redis;import java.util.List;import org.springframework.boot.context.properties.ConfigurationProperties;@ConfigurationProperties (prefix = "spring.redis" )public class RedisProperties { private int database = 0 ; private String url; private String host = "localhost" ; private String password; private int port = 6379 ; private boolean ssl; private int timeout; private Pool pool; private Sentinel sentinel; private Cluster cluster; public int getDatabase () { return this .database; } public void setDatabase (int database) { this .database = database; } public String getUrl () { return this .url; } public void setUrl (String url) { this .url = url; } public String getHost () { return this .host; } public void setHost (String host) { this .host = host; } public String getPassword () { return this .password; } public void setPassword (String password) { this .password = password; } public int getPort () { return this .port; } public void setPort (int port) { this .port = port; } public boolean isSsl () { return this .ssl; } public void setSsl (boolean ssl) { this .ssl = ssl; } public void setTimeout (int timeout) { this .timeout = timeout; } public int getTimeout () { return this .timeout; } public Sentinel getSentinel () { return this .sentinel; } public void setSentinel (Sentinel sentinel) { this .sentinel = sentinel; } public Pool getPool () { return this .pool; } public void setPool (Pool pool) { this .pool = pool; } public Cluster getCluster () { return this .cluster; } public void setCluster (Cluster cluster) { this .cluster = cluster; } public static class Pool { private int maxIdle = 8 ; private int minIdle = 0 ; private int maxActive = 8 ; private int maxWait = -1 ; public int getMaxIdle () { return this .maxIdle; } public void setMaxIdle (int maxIdle) { this .maxIdle = maxIdle; } public int getMinIdle () { return this .minIdle; } public void setMinIdle (int minIdle) { this .minIdle = minIdle; } public int getMaxActive () { return this .maxActive; } public void setMaxActive (int maxActive) { this .maxActive = maxActive; } public int getMaxWait () { return this .maxWait; } public void setMaxWait (int maxWait) { this .maxWait = maxWait; } } public static class Cluster { private List<String> nodes; private Integer maxRedirects; public List<String> getNodes () { return this .nodes; } public void setNodes (List<String> nodes) { this .nodes = nodes; } public Integer getMaxRedirects () { return this .maxRedirects; } public void setMaxRedirects (Integer maxRedirects) { this .maxRedirects = maxRedirects; } } public static class Sentinel { private String master; private String nodes; public String getMaster () { return this .master; } public void setMaster (String master) { this .master = master; } public String getNodes () { return this .nodes; } public void setNodes (String nodes) { this .nodes = nodes; } } }
四、源码地址 点我查看