首先,先查看Redis相关的配置类:
shift+shift进行搜索,查看RedisAutoConfiguration类:
在我们查看redis的配置类RedisAutoConfiguration时,可以看到RedisAutoConfiguation中封装了两个Bean:
接下来查看redis所对应的自动配置类:RedisProperties,该类对应一个properties配置文件,当然我们也可以在application中进行配置:
在SpringBoot操作数据是封装在Spring-data中的,jpa、jdbc、mongodb、redis,而在SpringBoot2.x以后与原来使用的jedis被替换成来看lettuce,底层已经不使用jedis了
- jedis: 采用的直连,多个线程操作的话,不安全,要提高安全性要使用jedis pool连接池
- lettuce: 采用netty,高性能网络框架,异步请求,实例在多线程中可以共享,不存在线程不安全的情况,dubbo底层也是用netty,可以减少线程数量,更像NIO模式
[](
)整合实现
导入依赖pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
编写配置文件applacation.yml:
spring:
redis:
host: 127.0.0.1 # Redis服务器地址
port: 6379 # Redis服务器连接端口
password: # Redis服务器连接密码(默认为空)
database: 0 # Redis数据库索引(默认为0)
jedis:
pool:
max-active: 8 # 连接池最大连接数(使用负值表示没有限制)
max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
max-idle: 500 # 连接池中的最大空闲连接
min-idle: 0 # 连接池中的最小空闲连接
lettuce:
shutdown-timeout: 0ms
timeout: 1000 # 连接超时时间(毫秒)
测试:
@SpringBootTest
public class SpringbootRedisTest {
@Autowired
private RedisTemplate<String,String> redisTemplate;
@Test
void contextLoads() {
redisTemplate.opsForValue().set("key1","value1");
redisTemplate.opsForValue().set("key2","张三");
System.out.println("key1="+redisTemplate.opsForValue().get("key1"));
System.out.println("key2="+redisTemplate.opsForValue().get("key2"));
}
}
运行结果:
查看RedisTemplate类:
测试代码:
@Test
public void test() throws JsonProcessingException {
//真实开发一般有使用json传递对象
User user =new User();
user.setName("龙源");
user.setAge(10);
String jsonUser = new ObjectMapper().writeValueAsString(user);
redisTemplate.opsForValue().set("user",jsonUser);
System.out.println(redisTemplate.opsForValue().get("user"));
}
//新建一个User类
@Component
public class User implements Serializable {//需要序列化Serializable
private String name;
private int age;
/**
* Get,Set,toString
**/
}
运行结果:
在客户端进行查看:发现user对象前面有转义字符
[](
)序列化
编写配置类,自定义RedisTemplate,修改默认的序列化方式:
@Configuration
public class RedisConfig {
@Bean
@SuppressWarnings("all")
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
//为了方便开发,使用<String,Object>
RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
template.setConnectionFactory(factory);
//Json序列化配置
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);
//String的序列化
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
// hash的key也采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
// value序列化方式采用jackson
template.setValueSerializer(jackson2JsonRedisSerializer);
// hash的value序列化方式采用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
再次测试:
//为了方便识别可以修改:RedisTemplate
@Autowired
//private RedisTemplate redisTemplate;
private RedisTemplate<String,Object> redisTemplate;
@Test
public void test() throws JsonProcessingException {
//真实开发一般有使用json传递对象
User user =new User();
user.setName("龙源");
user.setAge(10);
String jsonUser = new ObjectMapper().writeValueAsString(user);
redisTemplate.opsForValue().set("user",jsonUser);
System.out.println(redisTemplate.opsForValue().get("user"));
}
运行结果:
自定义工具类:
在真实开发中,一般不会使用原生的API而是使用自己封装的工具类RedisUtil
@Component
public final class RedisUtil {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
// =============================common============================
/**
* 指定缓存失效时间
* @param key 键
* @param time 时间(秒)
*/
public boolean expire(String key, long time) {
try {
if (time > 0) {
redisTemplate.expire(key, time, TimeUnit.SECONDS);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 根据key 获取过期时间
* @param key 键 不能为null
* @return 时间(秒) 返回0代表为永久有效
*/
public long getExpire(String key) {
return redisTemplate.getExpire(key, TimeUnit.SECONDS);
}
/**
* 判断key是否存在
* @param key 键
* @return true 存在 false不存在
*/
public boolean hasKey(String key) {
try {
return redisTemplate.hasKey(key);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 删除缓存
* @param key 可以传一个值 或多个
*/
@SuppressWarnings("unchecked")
public void del(String... key) {
if (key != null && key.length > 0) {
if (key.length == 1) {
redisTemplate.delete(key[0]);
} else {
redisTemplate.delete(CollectionUtils.arrayToList(key));
}
}
}
// ============================String=============================
/**
* 普通缓存获取
* @param key 键
* @return 值
*/
public Object get(String key) {
return key == null ? null : redisTemplate.opsForValue().get(key);
}
/**
* 普通缓存放入
* @param key 键
* @param value 值
* @return true成功 false失败
*/
public boolean set(String key, Object value) {
try {
redisTemplate.opsForValue().set(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 普通缓存放入并设置时间
* @param key 键
* @param value 值
* @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
* @return true成功 false 失败
*/
public boolean set(String key, Object value, long time) {
try {
if (time > 0) {
redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
} else {
set(key, value);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 递增
* @param key 键
* @param delta 要增加几(大于0)
*/
public long incr(String key, long delta) {
if (delta < 0) {
throw new RuntimeException("递增因子必须大于0");
}
return redisTemplate.opsForValue().increment(key, delta);
}
/**
* 递减
* @param key 键
* @param delta 要减少几(小于0)
*/
public long decr(String key, long delta) {
if (delta < 0) {
throw new RuntimeException("递减因子必须大于0");
}
return redisTemplate.opsForValue().increment(key, -delta);
}
// ================================Map=================================
/**
* HashGet
* @param key 键 不能为null
* @param item 项 不能为null
*/
public Object hget(String key, String item) {
return redisTemplate.opsForHash().get(key, item);
}
/**
* 获取hashKey对应的所有键值
* @param key 键
* @return 对应的多个键值
*/
public Map<Object, Object> hmget(String key) {
return redisTemplate.opsForHash().entries(key);
}
/**
* HashSet
* @param key 键
* @param map 对应多个键值
*/
public boolean hmset(String key, Map<String, Object> map) {
try {
redisTemplate.opsForHash().putAll(key, map);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
# 分享
这次面试我也做了一些总结,确实还有很多要学的东西。相关面试题也做了整理,可以分享给大家,了解一下面试真题,想进大厂的或者想跳槽的小伙伴不妨好好利用时间来学习。学习的脚步一定不能停止!
**[CodeChina开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频】](
)**
![薪酬缩水,“裸辞”奋战25天三面美团,交叉面却被吊打,我太难了](https://img-blog.csdnimg.cn/img_convert/cad22362bfb22263318f2a46d1426d3b.png)
Spring Cloud实战
![薪酬缩水,“裸辞”奋战25天三面美团,交叉面却被吊打,我太难了](https://img-blog.csdnimg.cn/img_convert/4e43803fe491fb4b9c58cdee2946ac10.png)
Spring Boot实战
![薪酬缩水,“裸辞”奋战25天三面美团,交叉面却被吊打,我太难了](https://img-blog.csdnimg.cn/img_convert/09887395d9391a8799dcbc210ea93f84.png)
y);
}
/**
* HashSet
* @param key 键
* @param map 对应多个键值
*/
public boolean hmset(String key, Map<String, Object> map) {
try {
redisTemplate.opsForHash().putAll(key, map);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
# 分享
这次面试我也做了一些总结,确实还有很多要学的东西。相关面试题也做了整理,可以分享给大家,了解一下面试真题,想进大厂的或者想跳槽的小伙伴不妨好好利用时间来学习。学习的脚步一定不能停止!
**[CodeChina开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频】](
)**
[外链图片转存中...(img-YlEo6KhH-1631183146003)]
Spring Cloud实战
[外链图片转存中...(img-11ap1uJO-1631183146005)]
Spring Boot实战
[外链图片转存中...(img-0mE4EGko-1631183146006)]
面试题整理(性能优化+微服务+并发编程+开源框架+分布式)