记录下第一次在springboot 用redis
未完待续...
RedisConfig
@Configuration
@EnableCaching
public class RedisConfig
{
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)
{
//自定义redisTemplate
// RedisTemplate<Object, Employee> template = new RedisTemplate<Object, Employee>();
RedisTemplate<Object, Object> template = new RedisTemplate<>();
// 配置连接工厂
template.setConnectionFactory(redisConnectionFactory);
//使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值
//这里对Object.class可以为自己的类
Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper mapper = new ObjectMapper();
//设置时间转换
LocalDateTimeDeserializer localDateTimeDeserializer = new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern("HH:mm:ss")));
javaTimeModule.addDeserializer(LocalDateTime.class, localDateTimeDeserializer);
mapper.registerModule(javaTimeModule);
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// 指定序列化输入的类型
mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
serializer.setObjectMapper(mapper);
template.setValueSerializer(serializer);
//使用StringRedisSerializer来序列化和反序列化redis的key值
template.setKeySerializer(new StringRedisSerializer());
template.afterPropertiesSet();
return template;
}
@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory)
{
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
config = config.entryTtl(Duration.ofMinutes(60*60*24*4));
/*config = config.entryTtl(Duration.ofHours(1));*/
// 设置一个初始化的缓存空间set集合
Set<String> cacheNames = new HashSet<>();
cacheNames.add("car");
cacheNames.add("userInfo");
// 对每个缓存空间应用不同的配置
Map<String, RedisCacheConfiguration> configMap = new HashMap<>();
//entryTtl设置缓存失效时间,单位是秒
configMap.put("car", config.entryTtl(Duration.ofSeconds(60*60)));
RedisCacheManager cacheManager = RedisCacheManager.builder(redisConnectionFactory)
.initialCacheNames(cacheNames)
.withInitialCacheConfigurations(configMap)
.build();
return cacheManager;
}
/**
* 对hash类型的数据操作
* @return
*/
@Bean
public HashOperations<Object, Object, Object> hashOperations(RedisTemplate<Object,Object> redisTemplate)
{
return redisTemplate.opsForHash();
}
/**
* 对redis字符串类型数据库操作
* @return
*/
@Bean
public ValueOperations<Object, Object> valueOperations(RedisTemplate<Object, Object> redisTemplate) {
return redisTemplate.opsForValue();
}
购物车jsp
<c:forEach items="${shopingList}" var="goods" varStatus="i">
<div class="goods-item" id="item${i}">
<div class="panel panel-default">
<div class="panel-body">
<div class="col-md-3 col-sm-2 col-xs-2 car-goods-info goods-image-column">
<a href="goodsDetail.html">
<img class="goods-image" src="${goods.firstPic}" />
</a>
</div>
<div class="col-md-3 col-sm-2 col-xs-2 car-goods-info goods-params">
<p class="goods-info" id="goodsNum" value="${goods.gName}">
${goods.gName}
</p>
</div>
<div class="col-md-1 col-sm-2 col-xs-2 car-goods-info goods-price">
<span class="goods-price single-price">¥${goods.gPrice}</span></div>
<div class="col-md-2 col-sm-2 col-xs-2 car-goods-info goods-counts">
<div class="input-group">
<div class="input-group-btn">
<button type="button"
class="goods-sub btn btn-default car-decrease myadd minue" value="${i.count}" onclick="updateNum(0,${i.count},${goods.cGoodId},${goods.cPrice})" >-</button>
</div>
<input type="text" disabled class="goods-num form-control goods-count myaddNum"
value="${goods.cnum}" id="num${i.count}">
<div class="input-group-btn">
<button type="button" id="addNum"
class="goods-add btn btn-default car-add myadd plus" value="${i.count}" onclick=updateNum(1,${i.count},${goods.cGoodId},${goods.cPrice}) >+</button>
</div>
<
</div>
</div>
<div class="col-md-1 col-sm-2 col-xs-2 car-goods-info goods-money-count">
<span class="goods-totalMoney single-total" id="totalPrice">¥${goods.cnum*goods.gPrice}</span></div>
<div class="col-md-2 col-sm-2 col-xs-2 car-goods-info goods-operate">
<a href="waitPay.html" class="btn btn-primary">结算</a>
<a data-toggle="modal" data-target=".bs-example-modal-sm" href="#"
class="btn btn-danger item-delete">删除</a>
</div>
</div>
</div>
</div>
</c:forEach>
<script>
//总共需要上传的数据数组
const updateData = new Array(50);
function updateNum(flag,count,gId,price)
{
var num1 = $("#num"+count).val();
var num = Number(num1);
//判断点击的是+还是- 更新数据
num=(flag===1)? (num+1) : (num-1);
//用来传给后台的json
var updateThisG =
{
"count":count,
"newNum": num,
"gId": gId
}
var Jupdata = JSON.stringify(updateThisG);
$.ajax
(
{
url: "/shop/addNum2",
data: Jupdata,
type:'POST',//默认为get请求,这里设置为post请求
contentType:'application/json;charset=UTF-8',
success: function(res)
{
//修改更改数量后的价格
price = res*price
$("#totalPrice").html("¥"+price);
//回显修改后的num
$("#num"+count).val(num);
console.log("这是第 "+count+ " 次修改商品数量,修改的goodsid是: "+gId+" 修改的数量是: "+num);
},
error(res)
{
}
}
)
}
</script>
goodsServiceImpl
@Override
public List<HashMap> getCarByUId(Long uid)
{
//判断redis里有没有该uid的购物车
if(redisService.hasUidCar(uid))
{
return redisService.queryCarInfoByUid(uid);
}
//redis里没有购物车,则查询数据库
List<HashMap> carInfo = userMapper.getCarByUid(uid);
//信息存入redis
redisService.setToRedis(carInfo,uid);
return carInfo;
}
RedisService
@Service
public class RedisService
{
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private RedisUtil redisUtil;
//将购物车list存入redis
public void setToRedis(List<HashMap> carInfo,Long uid)
{
redisUtil.setCacheList("car:userId:"+uid,carInfo);
}
//修改购物车中商品的数量,并更新redis
public void updateNum(JSONObject jupdata,Long userId)
{
//当前需要修改的下标
int count = (int) jupdata.get("count");
//更新后的数据
int updateNum = (int) jupdata.get("newNum");
//redis的key
String keyI = "car:userId:"+userId;
//拿到该key的所有value
List<HashMap> list = redisTemplate.opsForList().range(keyI,0,-1);
//对需要修改的map进行修改
HashMap map = list.get(count-1);
if (map.containsKey("cnum"))
{
map.put("cnum",updateNum);
}
//修改后的map放入list
list.set(count-1,map);
//删除原有list并放回新的list
redisTemplate.delete("car:userId:"+userId);
redisUtil.setCacheList("car:userId:"+userId,list);
}
//判断该uid在redis有没有存购物车信息
public boolean hasUidCar(Long uid)
{
return redisTemplate.hasKey("car:userId:"+uid);
}
//打开购物车页面前,判断若redis存在该uid的购物车信息则调用该方法
public List<HashMap> queryCarInfoByUid(Long uid)
{
String keyI = "car:userId:"+uid;
return redisTemplate.opsForList().range(keyI,0,-1);
}
}
util:
/**
* 缓存List数据
*
* @param key 缓存的键值
* @param dataList 待缓存的List数据
* @return 缓存的对象
*/
public <T> long setCacheList(final String key, final List<T> dataList)
{
Long count = redisTemplate.opsForList().rightPushAll(key, dataList);
return count == null ? 0 : count;
}
shop:增加、减少购物车某商品数量的controller
@RequestMapping("/addNum2")
public void add2(HttpServletRequest request, @RequestBody JSONObject jupdata,HttpServletResponse response) throws IOException
{
//当前用户id
//获取用户id
TUser loginedUser = (TUser) request.getSession().getAttribute("loginedUser");
Long userId = loginedUser.getId();
//修改redis
redisService.updateNum(jupdata,userId);
//更新后的数据
int updateNum = (int) jupdata.get("newNum");
response.getWriter().write(updateNum);
}
|