SpringBoot学习秒杀一、SpringBoot集成Redis (使用Jedis实现)

Nita ·
更新时间:2024-11-10
· 549 次阅读

在Springboot中已经有实现好的jar包可以很方便的集成Redis,也可以自己来封装Jedis实现Redis,这里我们使用Jedis来封装,从而使我们的程序更具有灵活性
首先,我们需要安装Redis: redis下载
安装完成之后在控制台输入redis-cli 如果出现以下界面即表示安装成功
在这里插入图片描述
redis安装成功之后打开idea,我们新建一个Springboot项目,选择Create New Project
然后选择新建的项目类型为Spring Initializr 即可以很方便的新建一个Springboot项目
在这里插入图片描述
我在这里使用的是Maven作为包管理,因此生成的项目目录是这样的
在这里插入图片描述
项目新建完成之后我们需要添加jedis的依赖
打开pom.xml在下添加

redis.clients jedis 3.2.0 com.alibaba fastjson 1.2.62

其中jedis就是redis的java客户端,而FastJson是一个可以将JavaBean 转化为JSON字符串的工具,因为Redis存储默认是以字符串形式来进行存储的,因此我们在进行JavaBean的存储的时候,需要将JavaBean序列化为JSON字符串,同样取出的时候我们也要讲字符串转化为JavaBean。
然后我们需要在SpringBoot的配置文件中定义Redis的配置参数,在Idea帮我们生成的SpringBoot项目中已经为我们默认添加了Application.properties文件作为配置文件,在这里我们换成更为方便的yml文件
在这里插入图片描述
在新建好的application.yml文件中,写入我们的redis配置参数

redis: host: 127.0.0.1 # redis服务器的地址 port: 6379 #redis服务器的端口 默认为6379 timeout: 3 #客户端超时时长 password: #redis客户端密码 poolMaxTotal: 10 #redis连接池最大连接 poolMaxIdle: 10 #连接池最大空闲连接数 poolMaxWait: 5 # 连接最大等待时间(毫秒)

我们新建一个名为redis的package,来保存我们封装的Redis代码
首先我们需要一个配置类来读入我们在配置文件中定义好的配置项
使用@Componet来表示此类是一个SpringBoot组件类,
使用 @ConfigurationProperties(prefix = "redis")来标识我们读取的配置项前缀为redis
RedisConfig.java

import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @Component @ConfigurationProperties(prefix = "redis") public class RedisConfig { private String host; private int port; private int timeout; private String password; private int poolMaxTotal; private int poolMaxIdle; private int poolMaxWait; public String getHost() { return host; } public void setHost(String host) { this.host = host; } public int getPort() { return port; } public void setPort(int port) { this.port = port; } public int getTimeout() { return timeout; } public void setTimeout(int timeout) { this.timeout = timeout; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public int getPoolMaxTotal() { return poolMaxTotal; } public void setPoolMaxTotal(int poolMaxTotal) { this.poolMaxTotal = poolMaxTotal; } public int getPoolMaxIdle() { return poolMaxIdle; } public void setPoolMaxIdle(int poolMaxIdle) { this.poolMaxIdle = poolMaxIdle; } public int getPoolMaxWait() { return poolMaxWait; } public void setPoolMaxWait(int poolMaxWait) { this.poolMaxWait = poolMaxWait; } }

接下来我们新建RedisService 来对jedis进行封装
操作redis我们需要最基本的两个方法,一个是向redis中存入数据
boolean set(String key,Class clazz)
另一个是从redis中取出数据 T get(String key ,Class clazz)
在进行存储的时候,我们需要将数据由Bean类型转化为String类型在进行存储,因此我们定义一个BeanToString 方法,代码如下:

private String beanToString(T value) { if (null == value) { return null; } Class clazz = value.getClass(); if (clazz == int.class || clazz == Integer.class) return "" + value; else if (clazz == long.class || clazz == Long.class) return "" + value; else if (clazz == String.class) return String.valueOf(value); else return JSON.toJSONString(value); }

同样的,在读取的时候我们也要将String转化为Bean ,所以我们需要在定义一个StringToBean方法:

private T stringToBean(String str, Class clazz) { if (null == str || str.length() <= 0 || null == clazz) { return null; } if (clazz == int.class || clazz == Integer.class) return (T) Integer.valueOf(str); else if (clazz == long.class || clazz == Long.class) return (T) Long.valueOf(str); else if (clazz == String.class) return (T) str; else return (T) JSON.toJavaObject(JSON.parseObject(str), clazz); }

然后接下来我们就可以进行写入和读取的操作了,我们使用jedis客户端的get set 方法来进行,那么如何获得jedis对象呢,我们可以直接实例化一个Jedis对象,但是我们由于要使用连接池,所以我们需要一个JedisPool 来实例化我们的Jedis,我们新建一个文件 RedisFactory

import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Service; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; @Service public class RedisFactory { @Autowired private RedisConfig redisConfig; @Bean public JedisPool jedisPoolFactory(){ JedisPoolConfig poolConfig = new JedisPoolConfig(); poolConfig.setMaxTotal(redisConfig.getPoolMaxTotal()); poolConfig.setMaxIdle(redisConfig.getPoolMaxIdle()); poolConfig.setMaxWaitMillis(redisConfig.getPoolMaxWait() * 1000); return new JedisPool(poolConfig,redisConfig.getHost(),redisConfig.getPort(),redisConfig.getTimeout()); } }

然后在我们的RedisService中注入我们的RedisFactory

@Autowired private JedisPool jedisPool;

接下来我们就可以通过 JedisPool.getResource() 来获取我们的 Jedis 对象
接下来来写我们的set和get方法

/** * redis 中设置值 * @param prefix * @param key * @param value * @param * @return */ public boolean set(String key, T value) { Jedis jedis = null; try { jedis = jedisPool.getResource(); String str = beanToString(value); if (null == str || str.length() <= 0) return false; jedis.set(str , str); return true; } finally { returnToPool(jedis); } } /** * redis 中获取值 * @param prefix * @param key * @param clazz * @param * @return */ public T get(String key, Class clazz) { Jedis jedis = null; try { jedis = jedisPool.getResource(); String str = jedis.get(key); return stringToBean(str, clazz); } finally { returnToPool(jedis); } } /** 连接使用完成之后放回连接池 **/ private void returnToPool(Jedis jedis) { if (null != jedis) jedis.close(); }

最基本的get 、 set方法之后,我们再来定义几个常用的方法

/** * 判断redis 中key是否存在 * @param prefix * @param key * @param * @return */ public boolean exists(String key,String key) { Jedis jedis = null; try { jedis = jedisPool.getResource(); return jedis.exists(key); } finally { returnToPool(jedis); } } /** * redis 数值增加 * @param prefix * @param key * @param * @return */ public Long incr(String key,String key) { Jedis jedis = null; try { jedis = jedisPool.getResource(); return jedis.incr(key); } finally { returnToPool(jedis); } } /** * redis 数值减少 * @param prefix * @param key * @param * @return */ public Long decr(String key,String key) { Jedis jedis = null; try { jedis = jedisPool.getResource(); return jedis.decr(key); } finally { returnToPool(jedis); } }

好了,我们的Redis客户端就基本上封装好了,但是,目前还有一个问题,就是我们的Key传入的是一个字符串,由于Redis的存储是Key ,Value形式的,因此我们存入的Value值很可能被Key相同的值给覆盖掉,因此为了解决这个问题,我们需要给我们传入的Key加一个前缀。
我们来定义一个接口来实现前缀,在接口中定义两个方法,一个expireSeconds 表示我们存储值得过期时间,getPrefix来获取我们的前缀

public interface KeyPrefix { public int expireSeconds(); public String getPrefix(); }

然后定一个Base类来实现这个接口,我们使用 “类名:前缀”的方式来作为我们key的前缀

public abstract class BasePrefix implements KeyPrefix { private int expireSeconds; private String prefix; public BasePrefix(String prefix){ this(0,prefix); } public BasePrefix(int expireSeconds,String prefix){ this.expireSeconds = expireSeconds; this.prefix = prefix; } @Override public int expireSeconds() { return 0; } @Override public String getPrefix() { String className = getClass().getSimpleName(); return className + ":" + prefix; } }

接下来我们写一个UserKey来继承我们的BasePrefix,我们假设User从Redis中存储的两种方式,一种为通过id获取 getById 另一种 通过name获取 getByName

public class Userkey extends BasePrefix { private Userkey(String prefix) { super(prefix); } public static Userkey getById = new Userkey("id"); public static Userkey getByName = new Userkey("name"); }

接下来我们需要改造一下我们的RedisService,使每个操作Redis的方法都要携带Prefix,完整代码如下:

package com.newcode.seckill_redis.redis; import com.alibaba.fastjson.JSON; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; @Service public class RedisService { @Autowired private JedisPool jedisPool; /** * redis 中获取值 * @param prefix * @param key * @param clazz * @param * @return */ public T get(KeyPrefix prefix,String key, Class clazz) { Jedis jedis = null; try { jedis = jedisPool.getResource(); String realKey = prefix.getPrefix() + key; String str = jedis.get(realKey); return stringToBean(str, clazz); } finally { returnToPool(jedis); } } /** * redis 中设置值 * @param prefix * @param key * @param value * @param * @return */ public boolean set(KeyPrefix prefix,String key, T value) { Jedis jedis = null; try { jedis = jedisPool.getResource(); String str = beanToString(value); if (null == str || str.length() 0 ) jedis.setex(realKey,seconds,str); else jedis.set(realKey, str); return true; } finally { returnToPool(jedis); } } /** * 判断redis 中key是否存在 * @param prefix * @param key * @param * @return */ public boolean exists(KeyPrefix prefix,String key) { Jedis jedis = null; try { jedis = jedisPool.getResource(); String realKey = prefix.getPrefix() + key; return jedis.exists(realKey); } finally { returnToPool(jedis); } } /** * redis 数值增加 * @param prefix * @param key * @param * @return */ public Long incr(KeyPrefix prefix,String key) { Jedis jedis = null; try { jedis = jedisPool.getResource(); String realKey = prefix.getPrefix() + key; return jedis.incr(realKey); } finally { returnToPool(jedis); } } /** * redis 数值减少 * @param prefix * @param key * @param * @return */ public Long decr(KeyPrefix prefix,String key) { Jedis jedis = null; try { jedis = jedisPool.getResource(); String realKey = prefix.getPrefix() + key; return jedis.decr(realKey); } finally { returnToPool(jedis); } } private String beanToString(T value) { if (null == value) { return null; } Class clazz = value.getClass(); if (clazz == int.class || clazz == Integer.class) return "" + value; else if (clazz == long.class || clazz == Long.class) return "" + value; else if (clazz == String.class) return String.valueOf(value); else return JSON.toJSONString(value); } private T stringToBean(String str, Class clazz) { if (null == str || str.length() <= 0 || null == clazz) { return null; } if (clazz == int.class || clazz == Integer.class) return (T) Integer.valueOf(str); else if (clazz == long.class || clazz == Long.class) return (T) Long.valueOf(str); else if (clazz == String.class) return (T) str; else return (T) JSON.toJavaObject(JSON.parseObject(str), clazz); } private void returnToPool(Jedis jedis) { if (null != jedis) jedis.close(); } }

接下来我们就可以愉快的使用我们的RedisServie了:

Boolean f = redisService.set(Userkey.getById,"key","value"); String str = redisService.get(Userkey.getById,"key",String.class);
作者:许家耀哟



springboot jedis Redis

需要 登录 后方可回复, 如果你还没有账号请 注册新账号