博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
spring及springboot整合redis
阅读量:6218 次
发布时间:2019-06-21

本文共 10603 字,大约阅读时间需要 35 分钟。

前言:

redis是一种nosql数据库,以<key,value>的形式存储数据,其速度相比于MySQL之类的数据库,相当于内存读写与硬盘读写的差别,所以常常用作缓存。接下来就分别看看在spring项目和springboot项目中如何使用redis(项目都基于SSM)。

一、整合前提:

前提是你已经安装redis且支持远程连接,redis的安装这里不再赘述,有需要的可以参考我的另一篇文章:。这里主要讲讲如何判断及设置redis支持远程连接。

1、判断你的redis是否支持远程连接:

①:在centos中输入如下命令找到redis-cli:
whereis redis-cli

②:根据返回的目录找到redis-cli,再执行如下命令:

redis-cli -h 192.168.1.100

③:192.168.1.100就是你的虚拟机ip地址。若这一步报错connect refused,可能是防火墙没有开放6379端口。执行如下命令查看开放的端口:

firewall-cmd --zone=public --list-ports

④:若确实没有6379,那就执行如下命令添加:

firewall-cmd --zone=public --add-port=6379/tcp --permanent

⑤:然后重启防火墙:

firewall-cmd --reload

⑥:开放了6379端口后再次执行:

redis-cli -h 192.168.1.100
出现如下结果:

img_cf4b656584beefba499f98ccdd16138d.png
image.png

⑦:这样并不能说明支持远程连接,我们输入ping,如果返回pong,说明才是支持远程连接的。

img_17cdd2724268b87f9b23a21a090d3fe1.png
image.png

2、设置支持远程连接:

如果没有返回pong,而是报错了,执行如下操作:
①:先关闭redis:
redis-cli shutdown

②:找到redis的配置文件:

whereis redis.conf

③:根据返回的目录,用vim打开redis.conf:

vim redis.conf
bind 127.0.0.1改成bind 0.0.0.0,
再把protected-mode=yesyes改为no,

img_0bc820ffa391c886475e13e86b6cc99e.png
image.png

④:然后保存退出,重启redis,再用redis-cli连接,输入ping,就能返回pong了。

二、spring整合redis:

下载源码。

1、引依赖:
pom.xml:

org.springframework.data
spring-data-redis
1.7.1.RELEASE
redis.clients
jedis
2.9.0

除了ssm整合以及mysql数据库需要的依赖,引入以上两个即可。

注意:
注意这两个jar包的版本搭配,有些版本搭配可能会报错,这两个版本搭配亲测可用。

2、编写RedisUtil工具类:

package com.zhu.redis.util;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.util.concurrent.Callable;import org.springframework.cache.Cache;import org.springframework.cache.support.SimpleValueWrapper;import org.springframework.data.redis.connection.RedisConnection;import org.springframework.data.redis.core.RedisCallback;import org.springframework.data.redis.core.RedisTemplate;public class RedisUtil implements Cache {    private RedisTemplate
redisTemplate; private String name; public RedisTemplate
getRedisTemplate() { return redisTemplate; } public void setRedisTemplate(RedisTemplate
redisTemplate) { this.redisTemplate = redisTemplate; } public void setName(String name) { this.name = name; } public String getName() { return this.name; } public byte[] toByteArray(Object obj) { byte[] bytes = null; ByteArrayOutputStream bos = new ByteArrayOutputStream(); try { ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(obj); oos.flush(); bytes = bos.toByteArray(); oos.close(); bos.close(); } catch (IOException e) { e.printStackTrace(); } return bytes; } public Object toObject(byte[] bytes) { Object obj = null; try { ByteArrayInputStream bis = new ByteArrayInputStream(bytes); ObjectInputStream ois = new ObjectInputStream(bis); obj = ois.readObject(); ois.close(); bis.close(); } catch (Exception e) { e.printStackTrace(); } return obj; } @Override public Object getNativeCache() { return this.redisTemplate; } @Override public ValueWrapper get(Object key) { System.out.println("--------------------------- get key ----------------------------"); final String keyf = key.toString(); Object object = null; object = redisTemplate.execute(new RedisCallback
() { public Object doInRedis(RedisConnection connection) { byte[] key = keyf.getBytes(); byte[] value = connection.get(key); if (value == null) { return null; } return toObject(value); } }); return (object != null ? new SimpleValueWrapper(object) : null); } @Override public void put(Object key, Object value) { System.out.println("------------------- put key --------------------------"); final String keyf = key.toString(); final Object valuef = value; final long liveTime = 86400; redisTemplate.execute(new RedisCallback
() { public Long doInRedis(RedisConnection connection) { byte[] keyb = keyf.getBytes(); byte[] valueb = toByteArray(valuef); connection.set(keyb, valueb); if (liveTime > 0) { connection.expire(keyb, liveTime); } return 1L; } }); } @Override public void evict(Object key) { System.out.println("-------------------------- del key ---------------------------"); final String keyf = key.toString(); redisTemplate.execute(new RedisCallback
() { public Long doInRedis(RedisConnection connection) { return connection.del(keyf.getBytes()); } }); } @Override public void clear() { System.out.println("-------------------- clear key -------------------------"); redisTemplate.execute(new RedisCallback
() { public String doInRedis(RedisConnection connection) { connection.flushDb(); return "ok"; } }); } @Override public ValueWrapper putIfAbsent(Object key, Object value) { // TODO Auto-generated method stub return null; } @Override public
T get(Object key, Class
type) { // TODO Auto-generated method stub return null; } @Override public
T get(Object key, Callable
valueLoader) { // TODO Auto-generated method stub return null; }}

这个类等下要在spring-redis.xml中配置。该类继承了spring的cache,提供了对缓存的一些基本操作的方法(get、del等),还定义了一个name成员变量,在需要用缓存的地方直接用注解@Cacheable(value="name的值")即可。

3、连接参数redis.properties:

redis.properties:

redis.host=192.168.1.100redis.port=6379redis.dbIndex=0redis.expiration=3000redis.maxIdle=300redis.maxActive=600redis.maxWait=1000redis.testOnBorrow=true

4、在spring-redis.xml中整合:

注意:

我这里并没有引入redis.properties,是因为我在spring-dao.xml中引入jdbc.properties时一起引入了,所以这里无需再引入。
spring-dao.xml中引入.properties文件代码:

classpath:jdbc.properties
classpath:redis.properties

5、在service层使用redis:

@Servicepublic class AreaServiceImpl implements AreaService {    @Autowired    private AreaDao areaDao;        @Cacheable(value="common") //加入缓存    //@CacheEvict(value="common") //清除缓存    @Override    public List getAreaList() {        return areaDao.queryArea();    }}

注意:

要使用redis,实体类必须实现序列化接口(implements Serializable),否则会抛java.io.NotSerializableException异常。

6、测试:

首先看一下数据库:

img_b382e831347bc010a5d852c1f887a035.png
image.png

然后用junit测试:

BaseTest.java:(用来加载配置文件)

@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration({ "classpath:spring/spring-dao.xml","classpath:spring/spring-service.xml","classpath:spring/spring-redis.xml"})public class BaseTest {}

AreaServiceTest.java:

public class AreaServiceTest extends BaseTest {        @Autowired    private AreaService areaService;        @Test    public void test() {        List areaList = areaService.getAreaList();        for(Area area : areaList) {            System.out.println(area.getAreaName());        }        System.out.println(areaList.size());    }}

看运行结果:

img_4eb9c2d0586d3d632d489a2a2da49eae.png
image.png
从图中可以看到这一次是从MySQL数据库查询的,且RedisUtil已经运行,因为打印出了put key。

再运行一次:

img_df869a62af1257c9043bc68fece70555.png
image.png

可以看到这次没有打印sql语句,且打印了get key,说明缓存已经生效。

把AreaService.java中的@Cacheable(value="common")注释掉,把@CacheEvict(value="common")放开,

再次运行:

img_c7a919856b80bbacab1b56edcfdfd82d.png
image.png
可以看到又打印出了sql语句,且输出了del key,说明已经清除了缓存,再次从数据库中查找。

这样就完成了spring与redis的整合。

三、springboot整合redis:

springboot整合redis就简单了,只需要简单配置就行了。

1、引依赖:

org.springframework.boot
spring-boot-starter-redis
1.4.7.RELEASE

springboot整合redis,只需引入这一个依赖即可。

2、在application.properties中配置redis:

spring.redis.host=192.168.1.100spring.redis.port=6379#连接池最大连接数spring.redis.jedis.pool.max-active=8#最小空闲连接spring.redis.jedis.pool.min-idle=0#最大阻塞等待时间,负值表示没有限制spring.redis.jedis.pool.max-wait=-1#最大空闲连接spring.redis.jedis.pool.max-idle=8#连接超时时间(毫秒)spring.redis.timeout=20

3、在springboot启动类上加上@EnableCaching注解,如下图:

img_156ba2aab558464e14a9f82e517d71f9.png
image.png

4、接下来就可以使用redis缓存了:

在需要使用的地方加上注解即可。
AreaServiceImpl.java:

@Servicepublic class AreaServiceImpl implements AreaService {    @Autowired    private AreaDao areaDao;    @Override    @Transactional    @Cacheable(value = "common")    //@CacheEvict(value="common")    public List getAreaList() {        return areaDao.queryArea();    }}

5、测试:

AreaServiceTest.java:

@RunWith(SpringRunner.class)@SpringBootTestpublic class AreaServiceTest {        @Autowired    private AreaService areaService;        @Test    public void test() {        List areaList = areaService.getAreaList();        for(Area area : areaList) {            System.out.println(area.getAreaName());        }    }}

第一次运行:

img_b5ed56afffe749a1609082b816024d84.png
image.png

打印出了sql语句,是从数据库查询的。

第二次运行:

img_c25f11f034c943c2398da891aeb4a3c6.png
image.png
没有sql语句,是从缓存中读取的。

@Cacheable(value = "common")注释掉,把@CacheEvict(value="common")放开,

再运行:

img_9d9c87d16d4f9a914fdeec901a42eeec.png
image.png
又是从数据库中读取的,说明redis清除成功。

总结:

spring整合redis:

总的来说就是引依赖、编写RedisUtil、编写redis.properties、在spring-redis.xml中配置,最后在需要使用的地方用注解就行了。
spring boot整合redis:
总的来说就是引依赖、在application.properties中配置、在启动类上加@EnableCaching注解,然后在需要使用的地方用注解就行了。
注意事项:
1、首先你的redis得支持远程连接。
2、实体类必须实现序列化接口。
3、redis的注解是@Cacheable(value = "?",key="?")这样的key、value形式,value必须自己指定,可以随便写,key可以不写,不写会自动生成。
4、如果要使用缓存的方法的参数是引用类型,比如方法是getStudent(Student stu)那么该引用类型的必须重写toString方法,即Student实体类必须重写toString方法,否则使用缓存时会报错can not convert com.zhu.entity.Student toString
5、若项目发布到服务器上,一开始redis可以正常使用,一段时间后redis不能正常使用,用redis-cli -h xx.xxx.x.xxx -p 6379命令连接显示connection timeout,访问项目中用到了redis的路由会报错could not get a resource from pool,可按如下步骤解决:
先kill掉redis的服务:
ps aux | grep redis
kill -9 redis服务的pid
换端口开启redis服务:
redis-server redis.conf --port=6000 &
这里指定的6000端口,也可以是其他的,&表示后台启动。再用redis-cli -h xx.xxx.x.xxx -p 6000就可以连接上了。然后把项目中的redis配置的端口换成6000,重新发布项目即可。
项目说明:
1、springboot是springboot2.x,springboot 1.5整合redis与这个不一样。
2、上述两个项目之所以会打印查询的sql语句,是因为在mybatis-config.xml中进行了如下配置:

以上内容属于个人笔记整理,如有错误,欢迎批评指正!

转载地址:http://splja.baihongyu.com/

你可能感兴趣的文章
ATM+购物商城(第一版)
查看>>
Android 音量键拦截
查看>>
转载:Linux+mysql+apache+php+wordpress搭建个人空间
查看>>
QQ2008自动聊天精灵delphi源码
查看>>
Android IOS WebRTC 音视频开发总结(十四)-- sip和xmpp异同
查看>>
iOS NSNotification传递带参数的通知
查看>>
python之路--管道, 事件, 信号量, 进程池
查看>>
POJ 3667 & HDU 3308 & HDU 3397 线段树的区间合并
查看>>
Mysql 常用语句
查看>>
Java解惑(三) puzzle 24--35
查看>>
断舍离~~~
查看>>
查询结果多个合并一个GROUP_CONCAT(EmployeeName)
查看>>
selenium获取弹窗提示
查看>>
JQuery 的Ajax的使用
查看>>
5. Web vulnerability scanners (网页漏洞扫描器 20个)
查看>>
Mysql存储过程(四)——异常处理
查看>>
aptana 报错:Java heap space
查看>>
POJ 1840 Eqs
查看>>
10.9h5日记
查看>>
canvas图片与img图片的相互转换
查看>>