1. redis相关配置
1.1 spring整合redis
spring-redis.xml
配置了Jedis相关的配置
什么是Jedis?
——Jedis用Java语言连接redis服务,并提供对应的操作API,方便我们把程序中的数据交给redis管理,同时,还可以取出redis中的数据到我们的程序中
maven坐标
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--Jedis连接池的相关配置-->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxTotal">
<value>200</value>
</property>
<property name="maxIdle">
<value>50</value>
</property>
<property name="testOnBorrow" value="true"/>
<property name="testOnReturn" value="true"/>
</bean>
<bean id="jedisPool" class="redis.clients.jedis.JedisPool">
<constructor-arg name="poolConfig" ref="jedisPoolConfig" />
<constructor-arg name="host" value="127.0.0.1" />
<constructor-arg name="port" value="6379" type="int" />
<constructor-arg name="timeout" value="30000" type="int" />
</bean>
</beans>
在后台的使用
@Autowired
private JedisPool jedisPool;
//将上传图片名称存入Redis,基于Redis的Set集合存储 RedisConstant.SETMEAL_PIC_RESOURCES表示key值
jedisPool.getResource().sadd(RedisConstant.SETMEAL_PIC_RESOURCES,fileName);
1.2 Jedis简易工具类开发
基于连接池获取连接
JedisPool:Jedis提供的连接池技术 poolConfig:连接池配置对象 host:redis服务地址 port:redis服务端口号
JedisUtils.java
package com.itheima.util;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import java.util.ResourceBundle;
public class JedisUtils {
private static int maxTotal;
private static int maxIdel;
private static String host;
private static int port;
private static JedisPoolConfig jpc;
private static JedisPool jp;
static {
ResourceBundle bundle = ResourceBundle.getBundle("redis");
maxTotal = Integer.parseInt(bundle.getString("redis.maxTotal"));
maxIdel = Integer.parseInt(bundle.getString("redis.maxIdel"));
host = bundle.getString("redis.host");
port = Integer.parseInt(bundle.getString("redis.port"));
//Jedis连接池配置
jpc = new JedisPoolConfig();
jpc.setMaxTotal(maxTotal);
jpc.setMaxIdle(maxIdel);
jp = new JedisPool(jpc,host,port);
}
public static Jedis getJedis(){
return jp.getResource();
}
}
redis.propeties
redis.maxTotal=50
redis.maxIdel=10
redis.host=192.168.40.130
redis.port=6379
1.3 Redis的相关API
2. Redis应用场景
2.1 定时清理垃圾图片
使用到的技术点:
Redis(统计出哪些是垃圾图片)+Qiniuyun(图片存储服务器)+Quartz(定时清理七牛云上的垃圾图片)
基于Quartz定时任务,通过计算redis两个集合的差值找出所有的垃圾图片,就可以将垃圾图片清理掉。
点击+号上传图片,图片存储到七牛云服务器上,但如果用户只上传了图片而没有最终保存套餐信息到我们的数据库,这时我们上传的图片就变为了垃圾图片。对于这些垃圾图片我们需要定时清理来释放磁盘空间。这就需要我们能够区分出来哪些是垃圾图片,哪些不是垃圾图片。如何实现呢?
方案就是利用redis来保存图片名称,具体做法为:
1、当用户上传图片后,将图片名称保存到redis的一个Set集合中,例如集合名称为setmealPicResources(在服务消费方操作)
2、当用户添加套餐后,将图片名称保存到redis的另一个Set集合中,例如集合名称为setmealPicDbResources(在服务提供方操作)
3、计算setmealPicResources集合与setmealPicDbResources集合的差值,结果就是垃圾图片的名称集合,清理这些图片即可
创建ClearImgJob定时任务类
package com.itheima.jobs;
import com.itheima.constant.RedisConstant;
import com.itheima.utils.QiniuUtils;
import org.springframework.beans.factory.annotation.Autowired;
import redis.clients.jedis.JedisPool;
import java.util.Set;
/**
* 自定义Job,实现定时清理垃圾图片
*/
public class ClearImgJob {
@Autowired
private JedisPool jedisPool;
public void clearImg(){
//根据Redis中保存的两个set集合进行差值计算,获得垃圾图片名称集合
Set<String> set =
jedisPool.getResource().sdiff(RedisConstant.SETMEAL_PIC_RESOURCES,
RedisConstant.SETMEAL_PIC_DB_RESOURCES);
if(set != null){
for (String picName : set) {
//删除七牛云服务器上的图片
QiniuUtils.deleteFileFromQiniu(picName);
//从Redis集合中删除图片名称
jedisPool.getResource().
srem(RedisConstant.SETMEAL_PIC_RESOURCES,picName);
}
}
}
}
2.2 利用redis存放手机验证码
redis存放手机验证码需要注意:
- 验证码一般是有时效性的,需要设置过期时间
- 在项目中会有多个场景需要使用到验证码(比如手机快速登录、预约体检、找回密码),因此需要使用手机号+场景码作为redis的key,防止出现验证码替换问题
为什么需要保存验证码到redis中?**
因为验证码一般是有时效性的,所以保存在数据库中不合适。如果把验证码存在session中,会对服务器产生压力;而存储在redis中,由于它是另一台服务器,不会造成压力
2.2.1 实际应用
public class RedisConstant {
//不同的场景码
public static final String SENDTYPE_ORDER = "001";//用于缓存体检预约时发送的验证码
public static final String SENDTYPE_LOGIN = "002";//用于缓存手机号快速登录时发送的验证码
public static final String SENDTYPE_GETPWD = "003";//用于缓存找回密码时发送的验证码
}
Controller层
@RestController
@RequestMapping("/validateCode")
public class ValidateCodeController {
@Autowired
private JedisPool jedisPool;
@RequestMapping("/send4Order")
public Result send4Order(String telephone){
Integer code = ValidateCodeUtils.generateValidateCode(4);
try {
SMSUtils.sendShortMessage(SMSUtils.VALIDATE_CODE,telephone, String.valueOf(code));
} catch (ClientException e) {
e.printStackTrace();
return new Result(false, MessageConstant.SEND_VALIDATECODE_FAIL);
}
System.out.println("发送的手机验证码为:" + code);
//将生成的验证码缓存到redis
//考虑到多个场景下都需要用到验证码 因此使用手机号+场景码作为redis的key值 防止出现验证码替换问题
jedisPool.getResource().setex(telephone+ RedisConstant.SENDTYPE_ORDER,5*60,String.valueOf(code));
//验证码发送成功
return new Result(true, MessageConstant.SEND_VALIDATECODE_SUCCESS);
}
}