1. 前言
上一篇文章整合了springboot+spring mvc+mybatis诺擅,基于三層架構(gòu)搭建了一個接口平臺萧朝。這篇文章主要整合一下springboot和redis的框架负芋,redis也是目前使用較多的nosql數(shù)據(jù)庫。
這篇文章的整個項目框架都是基于上一篇文章的搓蚪,所以很多配置或者代碼不會寫完像寒。
2. redis簡介與環(huán)境搭建
2.1 redis簡介
redis是一個key-value。和Memcached類似誓焦,它支持存儲的value類型相對更多胆敞,包括string(字符串)、list(鏈表)罩阵、set(集合)竿秆、zset(sorted set --有序集合)和hash(哈希類型)。這些數(shù)據(jù)類型都支持push/pop稿壁、add/remove及取交集并集和差集及更豐富的操作幽钢,而且這些操作都是原子性的。在此基礎(chǔ)上傅是,redis支持各種不同方式的排序匪燕。與memcached一樣,為了保證效率喧笔,數(shù)據(jù)都是緩存在內(nèi)存中帽驯。區(qū)別的是redis會周期性的把更新的數(shù)據(jù)寫入磁盤或者把修改操作寫入追加的記錄文件,并且在此基礎(chǔ)上實現(xiàn)了master-slave(主從)同步书闸。(來自百度百科)
Redis 是一個開源(BSD許可)的尼变,內(nèi)存中的數(shù)據(jù)結(jié)構(gòu)存儲系統(tǒng),它可以用作數(shù)據(jù)庫浆劲、緩存和消息中間件嫌术。 它支持多種類型的數(shù)據(jù)結(jié)構(gòu),如 字符串(strings)牌借, 散列(hashes)度气, 列表(lists), 集合(sets)膨报, 有序集合(sorted sets)與范圍查詢磷籍, bitmaps适荣, hyperloglogs和 地理空間(geospatial)索引半徑查詢。 Redis 內(nèi)置了 復(fù)制(replication)院领,LUA腳本(Lua scripting)弛矛, LRU驅(qū)動事件(LRU eviction),事務(wù)(transactions)和不同級別的 磁盤持久化(persistence)栅盲, 并通過 Redis哨兵(Sentinel)和自動 分區(qū)(Cluster)提供高可用性(high availability)汪诉。(來自redis中文官方網(wǎng)站)
這里貼上redis中文網(wǎng)地址,很好的一個redis學(xué)習(xí)網(wǎng)站谈秫。redis中文官方網(wǎng)站
2.2. redis特點
- Redis將其數(shù)據(jù)庫完全保存在內(nèi)存中扒寄,僅使用磁盤進行持久化。
- 與其它鍵值數(shù)據(jù)存儲相比拟烫,Redis有一組相對豐富的數(shù)據(jù)類型该编。
- Redis可以將數(shù)據(jù)復(fù)制到任意數(shù)量的從機中。
2.3. redis優(yōu)點
- 異乘妒纾快 - Redis非晨慰ⅲ快,每秒可執(zhí)行大約110000次的設(shè)置(SET)操作置媳,每秒大約可執(zhí)行81000次的讀取/獲取(GET)操作于樟。
- 支持豐富的數(shù)據(jù)類型 - Redis支持開發(fā)人員常用的大多數(shù)數(shù)據(jù)類型,例如列表拇囊,集合迂曲,排序集和散列等等。這使得Redis很容易被用來解決各種問題寥袭,因為我們知道哪些問題可以更好使用地哪些數(shù)據(jù)類型來處理解決路捧。
- 操作具有原子性 - 所有Redis操作都是原子操作,這確保如果兩個客戶端并發(fā)訪問传黄,Redis服務(wù)器能接收更新的值杰扫。
- 多實用工具 - Redis是一個多實用工具,可用于多種用例膘掰,如:緩存章姓,消息隊列(Redis本地支持發(fā)布/訂閱),應(yīng)用程序中的任何短期數(shù)據(jù)识埋,例如啤覆,web應(yīng)用程序中的會話,網(wǎng)頁命中計數(shù)等惭聂。
2.4 redis安裝
因為電腦是Windows系統(tǒng),這里就介紹一下Windows系統(tǒng)下的安裝相恃。linux系統(tǒng)下的安裝請另行百度辜纲。redis在Windows下的安裝十分簡單。
- 下載redis:Redis 沒有官方的Windows版本,但是微軟開源技術(shù)團隊(Microsoft Open Tech group)開發(fā)和維護著這個 Win64 的版本耕腾。所以可以在這里下載releases版本的见剩。https://github.com/MicrosoftArchive/redis/releases。
解壓出來的目錄:
- 啟動redis:在這個目錄下cmd扫俺,然后直接redis-server.exe redis.windows.conf苍苞,即可啟動redis。
- 修改密碼:在使用之前狼纬,先修改一下redis的密碼羹呵。在先前那個解壓目錄下,打開redis-cli.exe疗琉。
- 輸入config get requirepass可查看當前密碼冈欢,這里是我已經(jīng)改過密碼之后的。
- 然后輸入 config set requirepass "yourpassword" 可修改redis的密碼盈简。
- 連接redis:這里我是使用的RedisDesktopManager進行連接凑耻,這個是一個可視化管理redis的界面工具,下載windows版本的就行柠贤。https://redisdesktop.com/download
然后在這個工具里可使用redis基本操作香浩,這里有一些我已經(jīng)添加進去的數(shù)據(jù):
3. springboot中redis相關(guān)配置
- 在pom中配置redis的相關(guān)依賴包:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-redis</artifactId>
<version>1.3.8.RELEASE</version>
</dependency>
- 上一篇文章中已經(jīng)寫道,springboot的習(xí)慣優(yōu)于配置臼勉。也在項目中使用了application.yml文件配置mysql的基本配置項邻吭。這里也在application.yml里面配置redis的配置項。
spring:
datasource:
# 驅(qū)動配置信息
url: jdbc:mysql://localhost:3306/spring_boot?useUnicode=true&characterEncoding=utf8
username: root
password: root
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
# 連接池的配置信息
filters: stat
maxActive: 20
initialSize: 1
maxWait: 60000
minIdle: 1
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: select 'x'
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
maxOpenPreparedStatements: 20
redis:
host: 127.0.0.1
port: 6379
password: pass1234
pool:
max-active: 100
max-idle: 10
max-wait: 100000
timeout: 0
比上一篇文章中多的就是redis下面的幾個坚俗,分別是主機镜盯,端口和密碼,其他還有很多配置項猖败,具體可另在網(wǎng)上搜索了解速缆。
4. springboot中redis相關(guān)類
- 項目操作redis是使用的RedisTemplate方式,另外還可以完全使用JedisPool和Jedis來操作redis恩闻。整合的內(nèi)容也是從網(wǎng)上收集整合而來艺糜,網(wǎng)上整合的方式和方法非常的多,有使用注解形式的幢尚,有使用Jackson2JsonRedisSerializer來序列化和反序列化key value的值等等破停,很多很多。這里使用的是我認為比較容易理解和掌握的尉剩,基于JedisPool配置真慢,使用RedisTemplate來操作redis的方式。
- redis單獨放在一個包redis里理茎,在包里先創(chuàng)建RedisConfig.java文件黑界。
RedisConfig.java
@Configuration
@EnableAutoConfiguration
public class RedisConfig {
@Bean
@ConfigurationProperties(prefix = "spring.redis.pool")
public JedisPoolConfig getRedisConfig(){
JedisPoolConfig config = new JedisPoolConfig();
return config;
}
@Bean
@ConfigurationProperties(prefix = "spring.redis")
public JedisConnectionFactory getConnectionFactory() {
JedisConnectionFactory factory = new JedisConnectionFactory();
factory.setUsePool(true);
JedisPoolConfig config = getRedisConfig();
factory.setPoolConfig(config);
return factory;
}
@Bean
public RedisTemplate<?, ?> getRedisTemplate() {
JedisConnectionFactory factory = getConnectionFactory();
RedisTemplate<?, ?> template = new StringRedisTemplate(factory);
return template;
}
}
以上三個方法分別為獲取JedisPoolConfig配置管嬉、獲取JedisConnectionFactory工廠和獲取RedisTemplate模板。
@Configuration 注解是用于定義配置類朗鸠,可替換xml配置文件蚯撩,被注解的類內(nèi)部包含有一個或多個被@Bean注解的方法,這些方法將會被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext類進行掃描烛占,并用于構(gòu)建bean定義胎挎,初始化Spring容器。
@EnableAutoConfiguration 注解是啟用Spring應(yīng)用程序上下文的自動配置忆家,嘗試猜測和配置您可能需要的bean犹菇。自動配置類通常基于類路徑和定義的bean應(yīng)用弦赖。
@ConfigurationProperties 注解是用于讀取配置文件的信息疗涉,在這里是讀取配置在yml里的redis的相關(guān)配置項炮赦。
@Bean 注解用在方法上虐拓,告訴Spring容器丈冬,你可以從下面這個方法中拿到一個Bean
- 在包里創(chuàng)建RedisService接口,在這個接口定義了一些redis的基本操作币厕。在這里我把所有存取操作都封裝成了基于json字符串完成列另,就沒有對于list或者對于object等單獨定義方法。所有的數(shù)據(jù)類型的存儲都由代碼轉(zhuǎn)換成json字符串方式進行旦装。所以這里就只有四個方法页衙。
RedisService.java
public interface RedisService {
/**
* set存數(shù)據(jù)
* @param key
* @param value
* @return
*/
boolean set(String key, String value);
/**
* get獲取數(shù)據(jù)
* @param key
* @return
*/
String get(String key);
/**
* 設(shè)置有效天數(shù)
* @param key
* @param expire
* @return
*/
boolean expire(String key, long expire);
/**
* 移除數(shù)據(jù)
* @param key
* @return
*/
boolean remove(String key);
}
- 在包里創(chuàng)建RedisService接口的實現(xiàn)類RedisServiceImpl,這個類實現(xiàn)了接口的所有方法阴绢。
RedisServiceImpl.java
@Service("redisService")
public class RedisServiceImpl implements RedisService {
@Resource
private RedisTemplate<String, ?> redisTemplate;
@Override
public boolean set(final String key, final String value) {
boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {
@Override
public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
connection.set(serializer.serialize(key), serializer.serialize(value));
return true;
}
});
return result;
}
@Override
public String get(final String key) {
String result = redisTemplate.execute(new RedisCallback<String>() {
@Override
public String doInRedis(RedisConnection connection) throws DataAccessException {
RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
byte[] value = connection.get(serializer.serialize(key));
return serializer.deserialize(value);
}
});
return result;
}
@Override
public boolean expire(final String key, long expire) {
return redisTemplate.expire(key, expire, TimeUnit.SECONDS);
}
@Override
public boolean remove(final String key) {
boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {
@Override
public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
connection.del(key.getBytes());
return true;
}
});
return result;
}
}
在這里execute()方法具體的底層沒有去研究店乐,只知道這樣能實現(xiàn)對于redis數(shù)據(jù)的操作。
redis保存的數(shù)據(jù)會在內(nèi)存和硬盤上存儲呻袭,所以需要做序列化眨八;這個里面使用的StringRedisSerializer來做序列化,不過這個方式的泛型指定的是String左电,只能傳String進來廉侧。所以項目中采用json字符串做redis的交互。
到此篓足,redis在springboot中的整合已經(jīng)完畢段誊,下面就來測試使用一下。
5. springboot項目中使用redis
在這里就直接使用springboot項目中自帶的單元測試類SpringbootApplicationTests進行測試栈拖。
SpringbootApplicationTests.java
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootApplicationTests {
private JSONObject json = new JSONObject();
@Autowired
private RedisService redisService;
@Test
public void contextLoads() throws Exception {
}
/**
* 插入字符串
*/
@Test
public void setString() {
redisService.set("redis_string_test", "springboot redis test");
}
/**
* 獲取字符串
*/
@Test
public void getString() {
String result = redisService.get("redis_string_test");
System.out.println(result);
}
/**
* 插入對象
*/
@Test
public void setObject() {
Person person = new Person("person", "male");
redisService.set("redis_obj_test", json.toJSONString(person));
}
/**
* 獲取對象
*/
@Test
public void getObject() {
String result = redisService.get("redis_obj_test");
Person person = json.parseObject(result, Person.class);
System.out.println(json.toJSONString(person));
}
/**
* 插入對象List
*/
@Test
public void setList() {
Person person1 = new Person("person1", "male");
Person person2 = new Person("person2", "female");
Person person3 = new Person("person3", "male");
List<Person> list = new ArrayList<>();
list.add(person1);
list.add(person2);
list.add(person3);
redisService.set("redis_list_test", json.toJSONString(list));
}
/**
* 獲取list
*/
@Test
public void getList() {
String result = redisService.get("redis_list_test");
List<String> list = json.parseArray(result, String.class);
System.out.println(list);
}
@Test
public void remove() {
redisService.remove("redis_test");
}
}
class Person {
private String name;
private String sex;
public Person() {
}
public Person(String name, String sex) {
this.name = name;
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
在這里先是用@Autowired注解把redisService注入進來连舍,然后由于是使用json字符串進行交互,所以引入fastjson的JSONObject類涩哟。然后為了方便索赏,直接在這個測試類里面加了一個Person的內(nèi)部類诗鸭。
一共測試了:對于string類型的存取,對于object類型的存取参滴,對于list類型的存取,其實本質(zhì)都是轉(zhuǎn)成了json字符串锻弓。還有就是根據(jù)key來執(zhí)行remove操作砾赔。
獲取字符串:
獲取對象:
獲取list:
redis管理客戶端數(shù)據(jù):
到此,測試完成青灼,對于常用的一些數(shù)據(jù)類型的轉(zhuǎn)換存取操作也基本調(diào)試通過暴心。所以本文對于springboot整合redis到此結(jié)束。
小生水平有限杂拨,不喜勿噴专普。這是我在學(xué)習(xí)、工作過程中弹沽,經(jīng)歷和使用后整合的基礎(chǔ)教程檀夹,非常簡單和基礎(chǔ),只適合新手學(xué)習(xí)策橘。
有很多不足之處炸渡,另外也還有很多其他方式方法,希望各位大大不吝賜教丽已。
目前全部文章列表:
idea整合restful風(fēng)格的ssm框架(一)
idea整合restful風(fēng)格的ssm框架(二)
idea整合spring boot+spring mvc+mybatis框架
idea整合springboot+redis
JVM學(xué)習(xí)之—Java內(nèi)存區(qū)域
JVM學(xué)習(xí)之—垃圾回收與內(nèi)存分配策略
專題整理之—不可變對象與String的不可變
專題整理之—String的字符串常量池