-
} catch (JedisException e) {
-
log.info("client can't connect server");
-
if(null !=jedis){
-
//redisUtil 对象
-
redisUtil.brokenResource(jedis);
-
}
-
}
-
return v;
-
}
-
@Override
-
public Map<String, V> hget(String cacheKey,Object object) {
-
JSONObject json = JSONObject.fromObject(cacheKey);//将java对象转换为json对象
-
String jCacheKey = json.toString();//将json对象转换为字符串
-
//非空校验
-
if(StringUtils.isEmpty(jCacheKey)){
-
log.info("cacheKey is empty!");
-
return null;
-
}
-
Jedis jedis =null;
-
Map<String,V> result =null;
-
V v=null;
-
try {
-
jedis =redisUtil.getResource();
-
//获取列表集合 因为插入redis的时候是jsonString格式,所以取出来key是String value也是String
-
Map<String,String> map = jedis.hgetAll(jCacheKey);
-
if(null !=map){
-
for(Map.Entry<String, String> entry : map.entrySet()){
-
if(result ==null){
-
result =new HashMap<String,V>();
-
}
-
JSONObject obj = new JSONObject().fromObject(entry.getValue());//将json字符串转换为json对象
-
v = (V)JSONObject.toBean(obj,object.getClass());//将建json对象转换为java对象
-
result.put(entry.getKey(), v);
-
}
-
}
-
} catch (JedisException e) {
-
log.info("client can't connect server");
-
if(null !=jedis){
-
//释放jedis 对象
-
redisUtil.brokenResource(jedis);
-
}
-
}
-
return result;
-
}
5.最后我们来测试一下,注意实际开发中肯定是再service层调用redis的操作接口,我这里写个简单的单元测试
第二种:序列化后存入redis, 我这里用SerializeUtil,不过我推荐使用ProtoBuff更好
-
/**
-
* Created by ${HeJD} on 2018/6/29.
-
*/
-
@RunWith(SpringJUnit4ClassRunner.class)
-
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
-
public class RedisCacheStorageTest {
-
@Autowired
-
private RedisCacheStorage<String,User> redisCacheStorage;
-
@Test
-
public void testSetGet() throws Exception {
-
System.out.print("开始执行测试");
-
User user=new User();
-
user.setUsername("admin7");
-
user.setPassword("admin8");
-
redisCacheStorage.set("Akey7",user);
-
User user2= redisCacheStorage.get("Akey7",new User());
-
System.out.print("======="+user2.getUsername()+"====="+user2.getPassword());
-
}
代码在上一种方式的基础之上,我这里只写一些新的文件和需要修改的地方
1.首先我们需要一个序列化类
public class SerializeUtil {
/*
* 序列化
* */
public static byte[] serizlize(Object object){
ObjectOutputStream oos = null;
ByteArrayOutputStream baos = null;
3.最后测试的代码是一样的
(注意两个地方:1.这里是多实现,要用Qualifier指定注入的bean 2.序列化的方式实体类要实现Serializable接口)
2.我们需要对redis操作接口的实现类修改为另一种方式,我这里新建一个RedisCacheStorageImpl2来做对比
-
@RunWith(SpringJUnit4ClassRunner.class)
-
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
-
public class RedisCacheStorageTest {
-
@Autowired
-
@Qualifier("redisCacheStorage2")
-
private RedisCacheStorage<String,User> redisCacheStorage;
-
@Test
-
public void testSet() throws Exception {
-
System.out.print("开始执行测试");
-
User user=new User();
-
user.setUsername("admin9");
-
user.setPassword("admin12");
-
redisCacheStorage.set("Akey9",user);
-
User user2= (User) redisCacheStorage.get("Akey9",new User());
-
System.out.print("======="+user2.getUsername()+"====="+user2.getPassword());
-
}
-
}
-
package com.mmall.service.impl;
-
/**
-
* Created by ${HeJD} on 2018/7/1.
-
*/
-
import com.mmall.service.RedisCacheStorage;
-
import com.mmall.util.RedisUtil;
-
import com.mmall.util.SerializeUtil;
-
import org.slf4j.Logger;
-
import org.slf4j.LoggerFactory;
-
import org.springframework.beans.factory.annotation.Autowired;
-
import org.springframework.stereotype.Service;
-
import org.springframework.util.StringUtils;
-
import redis.clients.jedis.Jedis;
-
import redis.clients.jedis.exceptions.JedisException;
-
import java.util.HashMap;
-
import java.util.Map;
-
/**
-
* Created by ${HeJD} on 2018/6/29.
-
*/
-
@Service("redisCacheStorage2") //这里注入的名称不能相同,方便程序识别
-
public class RedisCacheStorageImpl2<V> implements RedisCacheStorage<String,V> {
-
//日志记录
-
private Logger log= LoggerFactory.getLogger(RedisCacheStorageImpl2.class);
-
/**
-
* 默认过时时间
-
*/
-
private static final int EXPRIE_TIME =3600*24;
-
/**
-
* 获取Jedis相关操作
-
*/
-
@Autowired
-
private RedisUtil redisUtil;
-
@Override
-
public boolean set(String key, V value) {
-
return set(key,value,EXPRIE_TIME);
-
}
-
@Override
-
public boolean set(String key, V value, int exp) {
-
Jedis jedis=null;
-
if(StringUtils.isEmpty(key)){
-
return false;
-
}
-
try {
-
//获取jedis对象
-
jedis= redisUtil.getResource();
-
//序列化对象后插入到redis
-
//我们需要使用 public String setex(byte[] key, int seconds, byte[] value),所以将key.getBytes()
-
jedis.setex(key.getBytes(),exp, SerializeUtil.serizlize(value));
-
}catch (Exception e){
-
//释放jedis对象
-
redisUtil.brokenResource(jedis);
-
log.info("client can't connect server");
-
return false;
-
}finally {
-
//返还连接池
-
redisUtil.returnResource(jedis);
-
return true;
-
}
-
}
-
@Override
-
public V get(String key,Object object) {
-
Jedis jedis=null;
-
V v=null;
-
if(StringUtils.isEmpty(key)){
-
log.info("redis取值,key为空");
-
return null;
-
}
-
try{
-
jedis=redisUtil.getResource(); //获取连接
-
//我们存入的时候使用的是key.getBytes(),所以取的时候也要使用它的key数组
-
byte valueByte[]=jedis.get(key.getBytes()); //从redis得到值
-
if(valueByte.length<=0){
-
return null;
-
}
-
//反序列化取出我们的数据
-
v=(V)SerializeUtil.deserialize(valueByte); //将值转换为我们插入redis之前的数据类型
-
return v;
-
}catch (Exception e){
-
//释放jedis对象
-
if(jedis!=null){
-
redisUtil.brokenResource(jedis);
-
}
-
log.info("client can't get value");
-
return null;
-
}finally {
-
//返还连接池
-
redisUtil.returnResource(jedis);
-
}
-
}
-
@Override
-
public boolean remove(String key) {
-
Jedis jedis=null;
-
try{
-
jedis=redisUtil.getResource();
-
if(StringUtils.isEmpty(key)){
-
log.info("redis取值,key为空");
-
return false;
-
}
-
jedis.del(key.getBytes());
-
}catch (Exception e) {
-
//释放jedis对象
-
if(jedis!=null){
-
redisUtil.brokenResource(jedis);
-
}
-
log.info(" del fail from redis");
-
return false;
-
}finally{
-
//返还连接池
-
redisUtil.returnResource(jedis);
-
return true;
-
}
-
}
-
@Override
-
public boolean hset(String cacheKey, String key, V value) {
-
Jedis jedis =null;
-
byte valueDate[]= SerializeUtil.serizlize(value);
-
//操作是否成功
-
boolean isSucess =true;
-
if(StringUtils.isEmpty(cacheKey)){
-
log.info("cacheKey is empty");
-
return false;
-
}
-
try {
-
jedis =redisUtil.getResource();
-
//执行插入哈希
-
//public Long hset(byte[] key, byte[] field, byte[] value)
-
jedis.hset(cacheKey.getBytes(),key.getBytes(),valueDate);
-
} catch (Exception e) {
-
log.info("client can't connect server");
-
isSucess =false;
-
if(null !=jedis){
-
//释放jedis 对象
-
redisUtil.brokenResource(jedis);
-
}
-
return false;
-
}finally{
-
if (isSucess) {
-
//返还连接池
-
redisUtil.returnResource(jedis);
-
}
-
return true;
-
}
-
}
-
@Override
-
public V hget(String cacheKey, String key,Object object) {
-
Jedis jedis =null;
-
V v =null;
-
if(cacheKey.getBytes().length<=0){
-
log.info("cacheKey is empty");
-
return null;
-
}
-
try {
-
//获取客户端对象
-
jedis =redisUtil.getResource();
-
//执行查询
-
byte valueDate[] = jedis.hget(cacheKey.getBytes(), key.getBytes());
-
//判断值是否非空
-
if(valueDate.length<0){
-
return null;
-
}else{
-
//反序列化拿到数据
-
v= (V)SerializeUtil.deserialize(valueDate);
-
return v;
-
}
-
} catch (JedisException e) {
-
log.info("client can't connect server");
-
if(null !=jedis){
-
//redisUtil 对象
-
redisUtil.brokenResource(jedis);
-
}
-
}finally {
-
//返还连接池
-
redisUtil.returnResource(jedis);
-
}
-
return v;
-
}
-
@Override
-
public Map<String, V> hget(String cacheKey,Object object) {
-
//非空校验
-
if(StringUtils.isEmpty(cacheKey)){
-
log.info("cacheKey is empty!");
-
return null;
-
}
-
Jedis jedis =null;
-
Map<String,V> result =new HashMap<String,V>();
-
try {
-
jedis =redisUtil.getResource();
-
//获取列表集合 因为插入redis的时候是key和value都是字节数组,所以返回的结果也是字节数组
-
Map<byte[], byte[]> map= jedis.hgetAll(cacheKey.getBytes());
-
if(null !=map){
-
for(Map.Entry<byte[], byte[]> entry : map.entrySet()){
-
result.put(new String(entry.getKey()),(V)SerializeUtil.deserialize(entry.getValue()));
-
}
-
}
-
} catch (JedisException e) {
-
log.info("client can't connect server");
-
if(null !=jedis){
-
//释放jedis 对象
-
redisUtil.brokenResource(jedis);
-
}
-
}
-
return result;
-
}
-
}
-
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;
-
}
-
/*
-
* 反序列化
-
* */
-
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();
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
总目录展示
该笔记共八个节点(由浅入深),分为三大模块。
高性能。 秒杀涉及大量的并发读和并发写,因此支持高并发访问这点非常关键。该笔记将从设计数据的动静分离方案、热点的发现与隔离、请求的削峰与分层过滤、服务端的极致优化这4个方面重点介绍。
一致性。 秒杀中商品减库存的实现方式同样关键。可想而知,有限数量的商品在同一时刻被很多倍的请求同时来减库存,减库存又分为“拍下减库存”“付款减库存”以及预扣等几种,在大并发更新的过程中都要保证数据的准确性,其难度可想而知。因此,将用一个节点来专门讲解如何设计秒杀减库存方案。
高可用。 虽然介绍了很多极致的优化思路,但现实中总难免出现一些我们考虑不到的情况,所以要保证系统的高可用和正确性,还要设计一个PlanB来兜底,以便在最坏情况发生时仍然能够从容应对。笔记的最后,将带你思考可以从哪些环节来设计兜底方案。
篇幅有限,无法一个模块一个模块详细的展示(这些要点都收集在了这份《高并发秒杀顶级教程》里),麻烦各位转发一下(可以帮助更多的人看到哟!)
由于内容太多,这里只截取部分的内容。
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
-
} catch (Exception e2) {
-
e2.printStackTrace();
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。[外链图片转存中…(img-flJdvx40-1712843800365)]
[外链图片转存中…(img-YNZolWXP-1712843800365)]
[外链图片转存中…(img-XncC0Kb5-1712843800366)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
总目录展示
该笔记共八个节点(由浅入深),分为三大模块。
高性能。 秒杀涉及大量的并发读和并发写,因此支持高并发访问这点非常关键。该笔记将从设计数据的动静分离方案、热点的发现与隔离、请求的削峰与分层过滤、服务端的极致优化这4个方面重点介绍。
一致性。 秒杀中商品减库存的实现方式同样关键。可想而知,有限数量的商品在同一时刻被很多倍的请求同时来减库存,减库存又分为“拍下减库存”“付款减库存”以及预扣等几种,在大并发更新的过程中都要保证数据的准确性,其难度可想而知。因此,将用一个节点来专门讲解如何设计秒杀减库存方案。
高可用。 虽然介绍了很多极致的优化思路,但现实中总难免出现一些我们考虑不到的情况,所以要保证系统的高可用和正确性,还要设计一个PlanB来兜底,以便在最坏情况发生时仍然能够从容应对。笔记的最后,将带你思考可以从哪些环节来设计兜底方案。
篇幅有限,无法一个模块一个模块详细的展示(这些要点都收集在了这份《高并发秒杀顶级教程》里),麻烦各位转发一下(可以帮助更多的人看到哟!)
[外链图片转存中…(img-jXPi623k-1712843800366)]
[外链图片转存中…(img-MfIJ45n8-1712843800366)]
由于内容太多,这里只截取部分的内容。
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!