叮嘟!最近做项目学习用到了Redis,在刚开始的摸索过程踩了不少雷,写篇博客分享一下踩雷经验。
声明:本文章仅供参考,学无止境,若有不足之处请指出,非常感谢!
源代码+相关工具下载:
https://download.csdn.net/download/corleone_4ever/10811258
————————————————
一.相关工具
如果没有服务器的同学,可以在自己的电脑安装虚拟机,我这里使用的是:VMware10+centos7+redis5.0
贴出 VMware10+centos7 下载地址:
https://download.csdn.net/download/corleone_4ever/10812834
开发工具用的myeclipse2014
jdk版本为1.7
java连接redis所需依赖jar包:
jedis-2.9.0.jar (redis连接工具)
commons-pool2-2.6.0.jar (jedis连接池)
fastjson-1.2.2.jar (阿里的json序列化工具)
junit-4.12.jar (单元测试)
贴出demo下载地址(包含vm10+centos7+redis5.0+jedis连接依赖jar包及其相关工具文档):
https://download.csdn.net/download/corleone_4ever/10811258
二.准备工作
在通过java连接redis之前,首先得配置好java环境。
安装好redis,并且能通过外部访问(需要关闭对应防火墙)。
1.启动redis
2.外部连接测试
输入ifconfig获取本机ip,通过外部连接测试,我这里使用的是RedisDesktopManager。
3.新建连接。
输入你自己的ip,redis端口和密码,没有密码就不输入。
4.连接成功
三.新建jedis项目
1.新建项目
右键→new→other→选择web下的Dynamic Web Project
2.命名项目
这里项目名称为jedis
3.引入相关jar包
直接把依赖jar包复制到WEB-INF下的lib目录下
4.引入 junit
右键项目→properties-→ava build parh→Libraries→ADD Library→Junit→Finish
这里也可以直接引用junit包,我是用的myeclipse自带的。
5.新建包com.redis.test
项目结构如下
四.编写代码
这里直接贴出代码
1.redis.properties : redis连接配置文件
连接池配置参考:
https://blog.csdn.net/wx5040257/article/details/78474157
#redis服务器ip
redis.ip=192.168.10.21
#redis服务器端口号
redis.port=6379
#redis密码
redis.passWord=
#与服务器建立连接的超时时间
redis.timeout=3000
#jedis的最大活跃连接数
pool.maxTotal=10
#jedis最大空闲连接数
pool.maxIdle=3
#jedis池没有连接对象返回时,等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。
#如果超过等待时间,则直接抛出JedisConnectionException
pool.maxWaitMillis=3000
2.RedisPoolUtil : 连接池配置工具
这里使用单例模式+双重锁定写的一个redis连接池配置工具。
(如需xml配置连接池,自行百度,原理相同)
package com.redis.test;
import java.util.Properties;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.exceptions.JedisConnectionException;
/**
* jedis连接池工具
* @author corleone
* @date 2018年11月27日
*/
public class RedisPoolUtil {
private volatile static JedisPool jedisPool = null;
private static String redisConfigFile = "redis.properties";
//把redis连接对象放到本地线程中
private static ThreadLocal<Jedis> local=new ThreadLocal<Jedis>();
private RedisPoolUtil() {
}
/**
* 初始化连接池
* @author corleone
* @date 2018年11月27日
*/
public static void initialPool() {
try {
Properties props = new Properties();
//加载连接池配置文件
props.load(RedisPoolUtil.class.getClassLoader().getResourceAsStream(redisConfigFile));
// 创建jedis池配置实例
JedisPoolConfig config = new JedisPoolConfig();
// 设置池配置项值
config.setMaxTotal(Integer.valueOf(props.getProperty("pool.maxTotal")));
config.setMaxIdle(Integer.valueOf(props.getProperty("pool.maxIdle")));
config.setMaxWaitMillis(Long.valueOf(props.getProperty("pool.maxWaitMillis")));
// 根据配置实例化jedis池
jedisPool = new JedisPool(config, props.getProperty("redis.ip"),
Integer.valueOf(props.getProperty("redis.port")),
Integer.valueOf(props.getProperty("redis.timeout")),
"".equals(props.getProperty("redis.passWord"))?null:props.getProperty("redis.passWord"));
System.out.println("连接池初始化成功");
} catch (Exception e) {
e.printStackTrace();
System.err.println("连接池初始化失败");
}
}
/**
* 获取连接
* @return
* @author corleone
* @date 2018年11月27日
*/
public static Jedis getInstance() {
//Redis对象
Jedis jedis =local.get();
if(jedis==null){
if (jedisPool == null) {
synchronized (RedisPoolUtil.class) {
if (jedisPool == null) {
initialPool();
}
}
}
try{
jedis = jedisPool.getResource();
}catch(JedisConnectionException e){
e.printStackTrace();
}
local.set(jedis);
}
return jedis;
}
/**
* 关闭连接
* @author corleone
* @date 2018年11月27日
*/
public static void closeConn(){
Jedis jedis =local.get();
if(jedis!=null){
jedis.close();
}
local.set(null);
}
}
3.SerializeUtil : java序列化/反序列化封装工具
package com.redis.test;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
/**
* java序列化/反序列化工具
* @author corleone
* @date 2018年11月27日
*/
public class SerializeUtil {
/**
* 序列化
* @param object
* @author corleone
* @date 2018年11月27日
*/
public static byte[] serizlize(Object object){
ObjectOutputStream oos = null;
ByteArrayOutputStream baos = null;
try {
baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
oos.writeObject(object);
byte[] bytes = baos.toByteArray();
return bytes;
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(baos != null){
baos.close();
}
if (oos != null) {
oos.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
return null;
}
/**
* 反序列化
* @param bytes
* @author corleone
* @date 2018年11月27日
*/
public static Object deserialize(byte[] bytes){
ByteArrayInputStream bais = null;
ObjectInputStream ois = null;
try{
bais = new ByteArrayInputStream(bytes);
ois = new ObjectInputStream(bais);
return ois.readObject();
}catch(Exception e){
e.printStackTrace();
}finally {
try {
} catch (Exception e2) {
e2.printStackTrace();
}
}
return null;
}
}
4.MapUtil : 对象与map相互转换封装工具
能够转换的对象需要该对象的属性必须是String或int类型,我这里只做演示,其他类型需要自己扩展
package com.redis.test;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;
/**
* java反射机制
* 对象与map相互转换
* @author corleone
* @date 2018年11月14日
*/
public class MapUtil {
/**
* map转对象(目前只支持对象中含有String和int类型的属性,其他类型需要自己扩展)
* @param map
* @param beanClass
* @throws Exception
* @author corleone
* @date 2018年11月27日
*/
public static <T> Object mapToObject(Map<String, String> map, Class<?> beanClass)
throws Exception {
if (map == null)
return null;
Object obj = beanClass.newInstance();
Field[] fields = obj.getClass().getDeclaredFields();
for (Field field : fields) {
int mod = field.getModifiers();
if (Modifier.isStatic(mod) || Modifier.isFinal(mod)) {
continue;
}
field.setAccessible(true);
if(field.getType().equals(int.class)){
field.set(obj, Integer.parseInt(map.get(field.getName())));
}else{
field.set(obj, (Object)map.get(field.getName()));
}
}
return obj;
}
/**
* 对象转map(目前只支持对象属性为基本类型)
* @param obj
* @throws Exception
* @author corleone
* @date 2018年11月27日
*/
public static Map<String, String> objectToMap(Object obj) throws Exception {
if (obj == null) {
return null;
}
Map<String, String> map = new HashMap<String, String>();
Field[] declaredFields = obj.getClass().getDeclaredFields();
for (Field field : declaredFields) {
field.setAccessible(true);
map.put(field.getName(), field.get(obj).toString());
}
return map;
}
}
5.ReflectUtil : 通过反射根据对象属性名称获取对应属性的值
(在实际项目中用aop实现连接redis的时候有用到,本次演示没有用到该工具类,所以不贴出代码,有兴趣可以下载demo自己研究下:一.相关工具)
6.RedisOps : jedis存取常用数据封装工具类
这里写了String类型和hash类型两种数据存取,如需要存取其他数据类型可以自己扩展
package com.redis.test;
import com.alibaba.fastjson.JSON;
import redis.clients.jedis.Jedis;
/**
* redis存取工具类
* @author corleone
* @date 2018年11月15日
*/
public class RedisOps {
/**
* kv字符串存
* @param key
* @param value
* @author corleone
* @date 2018年11月15日
*/
public static void set(String key,String value){
Jedis jedis = RedisPoolUtil.getInstance();
jedis.set(key, value);
RedisPoolUtil.closeConn();
}
/**
* kv字符串取
* @param key
* @return 字符串
* @author corleone
* @date 2018年11月15日
*/
public static String get(String key){
Jedis jedis = RedisPoolUtil.getInstance();
String value = jedis.get(key);
RedisPoolUtil.closeConn();
return value;
}
/**
* kv对象存(java序列化方式)
* @param key
* @param object 对象类必须实现序列化
* @author corleone
* @date 2018年11月15日
*/
public static void setObjectSerialize(String key,Object object){
Jedis jedis = RedisPoolUtil.getInstance();
if(jedis==null){
return;
}
jedis.set(key.getBytes(), SerializeUtil.serizlize(object));
RedisPoolUtil.closeConn();
}
/**
* kv对象取(java反序列化)
* @param key
* @return 对象
* @author corleone
* @date 2018年11月15日
*/
public static Object getObjectSerialize(String key){
Jedis jedis = RedisPoolUtil.getInstance();
if(jedis==null){
return null;
}
byte[] bytes = jedis.get(key.getBytes());
RedisPoolUtil.closeConn();
if(bytes==null){
return null;
}
return SerializeUtil.deserialize(bytes);
}
/**
* 删除key
* @param key
* @author corleone
* @date 2018年11月15日
*/
public static void del(String key){
Jedis jedis = RedisPoolUtil.getInstance();
if(jedis==null){
return;
}
jedis.del(key.getBytes());
RedisPoolUtil.closeConn();
}
/**
* kv对象存(json方式)
* @param key
* @param object
* @author corleone
* @date 2018年11月15日
*/
public static void setObjectJson(String key,Object object){
Jedis jedis = RedisPoolUtil.getInstance();
if(jedis==null){
return;
}
jedis.set(key, JSON.toJSONString(object));
RedisPoolUtil.closeConn();
}
/**
* kv对象取(json方式)
* @param key
* @param clazz反序列化对象类型
* @return 对象
* @author corleone
* @date 2018年11月15日
*/
@SuppressWarnings({ "unchecked" })
public static <T> Object getObjectJson(String key,Class<?> clazz){
Jedis jedis = RedisPoolUtil.getInstance();
if(jedis==null){
return null;
}
String result= jedis.get(key);
RedisPoolUtil.closeConn();
if(result==null){
return null;
}
T obj=(T)JSON.parseObject(result,clazz);
return obj;
}
/**
* kv对象存(map形势)
* @param key
* @param u
* @throws Exception
* @author corleone
* @date 2018年11月27日
*/
public static void setObjectHash(String key, Object u) throws Exception {
Jedis jedis = RedisPoolUtil.getInstance();
if(jedis==null){
return ;
}
jedis.hmset(key, MapUtil.objectToMap(u));
RedisPoolUtil.closeConn();
}
/**
* kv对象取(map形势)
* @param key
* @param clazz
* @throws Exception
* @author corleone
* @date 2018年11月27日
*/
public static Object getObjectHash(String key,Class<?> clazz) throws Exception {
Jedis jedis = RedisPoolUtil.getInstance();
if(jedis==null){
return null;
}
Object obj = MapUtil.mapToObject(jedis.hgetAll(key), clazz);
RedisPoolUtil.closeConn();
if(obj==null){
return null;
}
return obj;
}
}
7.User Vehicle两个实体类
后者没有实现Serializable,不能用于java序列化存取
User
package com.redis.test;
import java.io.Serializable;
/**
* 用户实体类
* @author corleone
* @date 2018年11月27日
*/
public class User implements Serializable {
private static final long serialVersionUID = -3210884885630038713L;
private int id;
private String name;
private int age;
public User(){
}
public User(int id,String name,int age){
this.id = id;
this.name = name;
this.age=age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", age=" + age + "]";
}
}
Vehicle
package com.redis.test;
/**
* 车辆实体类
* @author corleone
* @date 2018年11月27日
*/
public class Vehicle {
private int id;
private String platenumber;
private String color;
public Vehicle(){
}
public int getId() {
return id;
}
public Vehicle(int id, String platenumber, String color) {
this.id = id;
this.platenumber = platenumber;
this.color = color;
}
public void setId(int id) {
this.id = id;
}
public String getPlatenumber() {
return platenumber;
}
public void setPlatenumber(String platenumber) {
this.platenumber = platenumber;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
@Override
public String toString() {
return "Vehicle [id=" + id + ", platenumber=" + platenumber
+ ", color=" + color + "]";
}
}
8.JTest : jedis存取数据测试类
package com.redis.test;
import org.junit.Test;
import redis.clients.jedis.Jedis;
/**
* jedis存取测试
* @author corleone
* @date 2018年11月27日
*/
public class JTest {
/**
* 测试连接
* @author corleone
* @date 2018年11月27日
*/
@Test
public void TestPing(){
Jedis jedis = RedisPoolUtil.getInstance();
System.out.println(jedis.ping());
}
/**
* 测试java序列化存取
* @author corleone
* @date 2018年11月27日
*/
@Test
public void TestSerialize(){
User u = new User(1,"小明",6);
RedisOps.setObjectSerialize(User.class.getName().toString()+":"+1, u);
User u2 = (User)RedisOps.getObjectSerialize(User.class.getName().toString()+":"+1);
System.out.println(u2.toString());
}
/**
* 测试json序列化存取
* @author corleone
* @date 2018年11月27日
*/
@Test
public void TestJson(){
User u = new User(1,"小明",6);
Vehicle v = new Vehicle(1,"渝A00000","蓝色");
RedisOps.setObjectJson(User.class.getName().toString()+":"+1, u);
RedisOps.setObjectJson(Vehicle.class.getName().toString()+":"+1, v);
User u2 = (User)RedisOps.<User>getObjectJson(User.class.getName().toString()+":"+1,User.class);
Vehicle v2 = (Vehicle)RedisOps.<Vehicle>getObjectJson(Vehicle.class.getName().toString()+":"+1,Vehicle.class);
System.out.println(u2.toString());
System.out.println(v2.toString());
}
/**
* 测试hash存取
* @throws Exception
* @author corleone
* @date 2018年11月27日
*/
@Test
public void TestHash() throws Exception{
Vehicle v = new Vehicle(1,"渝A00000","蓝色");
RedisOps.setObjectHash(Vehicle.class.getName().toString()+":"+1, v);
Vehicle v2=(Vehicle) RedisOps.getObjectHash(Vehicle.class.getName().toString()+":"+1,Vehicle.class);
System.out.println(v2.toString());
}
}
五.连接测试
这里以json序列化存取对象为例
1.执行TestJson方法成功
2.查看redis中的数据
六.注意事项
这里都是踩坑过来的,把我遇到过的问题也贴出来
1.外部无法连接:一般是linux防火墙未关闭的原因,这里特别注意centos7关闭防火墙与之前版本不一样,如果你用的centos7,那么请整对centos7进行百度
2.如果你的redis没有密码,请不要输入空字符串
3.java序列化存取对象,记得实现Serializable
4.如果你的实体类添加了有参构造方法,请重写无参构造方法,否则报如下错误
终于小结了,累晕辽。
关于Redis的更多学习使用随后再来吧!
就酱,嘎啦!
注:本文为转载文章。
版权声明:本文为CSDN博主「hashdog」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/corleone_4ever/article/details/84582394