学习redis做的小demo
1.1 demo具体功能
显示所有数据时,先查询redis是否有缓存,没有缓存则查看数据库,有缓存则显示缓存中的内容
搜索数据时,先查询redis是否有搜索的key,没有。。。,有。。。同上
删除和修改商品成功后,要删除redis中所有数据的缓存及所有搜索数据的缓存
纯属个人学习做的小demo,大佬勿喷。
界面
2.1 数据展示
2.2 搜索数据
2.3 删除/修改
代码块
3.1 sql
3.2 entity
import lombok.Data;
@Data
public class Shop {
private int shop_id;
private String shop_name;
private double shop_price;
}
3.3 service
import java.util.List;
public interface ShopService {
List<Shop> getAllShop();
List<Shop> queryShopByName(String shop_name);
int deleteShop(int shop_id);
int updateShop(int shop_id,String shop_name,double shop_price);
}
3.4 mapper
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface ShopMapper {
List<Shop> getAllShop();
List<Shop> queryShopByName(String shop_name);
int deleteShop(int shop_id);
int updateShop(int shop_id,String shop_name,double shop_price);
}
3.5 serviceImpl
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class ShopServiceImpl implements ShopService {
@Autowired
ShopMapper shopMapper;
@Override
public List<Shop> getAllShop() {
return shopMapper.getAllShop();
}
@Override
public List<Shop> queryShopByName(String shop_name) {
return shopMapper.queryShopByName(shop_name);
}
@Override
public int deleteShop(int shop_id) {
return shopMapper.deleteShop(shop_id);
}
@Override
public int updateShop(int shop_id, String shop_name, double shop_price) {
return shopMapper.updateShop(shop_id,shop_name,shop_price);
}
}
3.6 mapper.xml。namespace需要修改为自己的包名地址
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.wjh.redis.mapper.ShopMapper">
<resultMap id="ShopMap" type="com.wjh.redis.entity.Shop">
<id property="shop_id" column="shop_id"/>
<result property="shop_name" column="shop_name"/>
<result property="shop_price" column="shop_price"/>
</resultMap>
<select id="getAllShop" resultMap="ShopMap">
select shop_id,shop_name,shop_price from shop;
</select>
<select id="queryShopByName" resultType="com.wjh.redis.entity.Shop" parameterType="string">
select shop_id,shop_name,shop_price from shop where shop_name like CONCAT('%',#{shop_name},'%')
</select>
<delete id="deleteShop" parameterType="com.wjh.redis.entity.Shop">
delete from shop where shop_id=#{shop_id}
</delete>
<update id="updateShop" parameterType="com.wjh.redis.entity.Shop">
update shop set shop_name=#{shop_name},shop_price=#{shop_price} where shop_id=#{shop_id}
</update>
</mapper>
3.7 redisConfig 在操作所有redis中,关于对象的保存我们得序列化才能正常操作
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* 在操作所有redis中,关于对象的保存我们得序列化才能正常操作
*
* 自定义封装RedisTemplate类
*/
@Configuration
public class RedisConfig {
@Bean
@SuppressWarnings("all")
public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory factory){
RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
template.setConnectionFactory(factory);
//json序列化配置
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
//String的序列化
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
//key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
//hash的key也采用了序列化方式
template.setHashKeySerializer(stringRedisSerializer);
//value序列化方式采用jackson
template.setValueSerializer(jackson2JsonRedisSerializer);
//hash的value序列化采用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
3.8 redis工具类
@Component
public class RedisUtils {
@Resource
private RedisTemplate<String, Object> redisTemplate;
/**
* 普通获取缓存
*
* @param key 键
* @return 值
*/
public Object get(String key) {
return key == null ? null : redisTemplate.opsForValue().get(key);
}
/**
* 普通缓存放入
*
* @param key 键
* @param value 值
* @return true 成功 false 失败
*/
public boolean set(String key, Object value) {
try {
redisTemplate.opsForValue().set(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* HashGet
* @param key 键 不能为null
* @param item 项 不能为null
* @return 值
*/
public Object hget(String key,String item){
return redisTemplate.opsForHash().get(key,item);
}
/**
* 向一张hash表中放入数据,如果不存在将创建
* @param key 键
* @param item 项
* @param value 值
* @return true 成功 false 失败
*/
public boolean hset(String key,String item,Object value){
try {
redisTemplate.opsForHash().put(key,item,value);
return true;
}catch (Exception e){
e.printStackTrace();
return false;
}
}
/**
* 删除缓存
*
* @param key 可以传一个值或多个
*/
@SuppressWarnings("unchecked")
public boolean del(String... key) {
if (key != null && key.length > 0) {
if (key.length == 1) {
redisTemplate.delete(key[0]);
return true;
} else {
redisTemplate.delete((Collection<String>) CollectionUtils.arrayToList(key));
}
}
return false;
}
}
3.9 controller log是当时为了校验打的。可以不写
import com.wjh.redis.entity.Shop;
import com.wjh.redis.redisUtils.RedisUtils;
import com.wjh.redis.service.ShopService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.logging.Logger;
@RestController
public class ShopController {
private static String name = ShopController.class.getName();
private static Logger log = Logger.getLogger(name);
@Autowired
RedisUtils redisUtils;
@Autowired
ShopService shopService;
//获取所有商品
@RequestMapping(value = "/getAllShop")
public List<Shop> queryAllShop() {
List<Shop> shops = (List<Shop>) redisUtils.get("allShops");
if (CollectionUtils.isEmpty(shops)) {
shops = shopService.getAllShop();
redisUtils.set("allShops", shops);
System.out.println("shops内容:"+shops);
log.info("商品数据添加到redis缓存中成功!");
} else {
log.info("redis中已存在商品数据");
}
return shops;
}
//根据名称查找商品
@RequestMapping(value = "/queryShopByName", method = RequestMethod.GET)
public List<Shop> queryShopByName(String shop_name) {
log.info("正在查询redis中是否有该缓存?");
List<Shop> list = (List<Shop>) redisUtils.hget("myQuery", shop_name);
if (CollectionUtils.isEmpty(list)) {
log.info("redis缓存中没有" + shop_name);
log.info("即将查看数据库");
list = shopService.queryShopByName(shop_name);
if(list.size() == 0){
log.info("数据库暂未此商品");
}else{
redisUtils.hset("myQuery", shop_name, list);
log.info("redis添加" + shop_name + "成功");
}
} else {
log.info("redis缓存中有" + shop_name + ",获取缓存中的内容");
}
return list;
}
@RequestMapping(value = "/deleteShop")
public String deleteShop(int shop_id) {
String message = null;
shopService.deleteShop(shop_id);
log.info("删除id为:" + shop_id + "的商品成功");
boolean redis = redisUtils.del("allShops");
boolean redis2 = redisUtils.del("myQuery");
if (redis && redis2) {
message = "success";
} else {
log.warning("删除缓存失败");
message = "fail";
}
return message;
}
//会有数据库内容更改了,redis缓存删除失败的情况,如果返回fail,则让用户决定是否重新删除
@RequestMapping(value = "/restartClearRedisCache")
public String clearCache() {
boolean flag = redisUtils.del("allShops");
boolean flag2 = redisUtils.del("myQuery");
String message = null;
if (flag && flag2) {
message = "success";
log.info("重新清空redis商品数据缓存成功!");
} else {
message = "fail";
log.warning("重新清空redis商品数据缓存失败!");
}
return message;
}
@RequestMapping(value = "/updateShop")
public void updateShop(int shop_id, String shop_name, double shop_price) {
shopService.updateShop(shop_id, shop_name, shop_price);
log.info("修改id为:" + shop_id + "的商品成功");
log.info("需删除商品数据的缓存。");
redisUtils.del("allShops");
log.info("删除所有商品缓存成功");
redisUtils.del("myQuery");
log.info("删除搜索商品缓存成功");
}
}
3.10 显示所有商品、删除、修改.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Redis Test</title>
<script src="https://cdn.staticfile.org/jquery/2.0.0/jquery.min.js"></script>
<link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/semantic-ui@2.4.2/dist/semantic.min.css">
</head>
<style>
.black_overlay {
display: none; /* 此元素不会被显示*/
position: absolute;
top: 0%;
left: 0%;
width: 100%;
height: 100%;
background-color: black;
z-index: 1001; /* z-index 属性设置元素的堆叠顺序。拥有更高堆叠顺序的元素总是会处于堆叠顺序较低的元素的前面。*/
-moz-opacity: 0.8;
opacity: .80; /* opacity 属性设置元素的不透明级别。*/
filter: alpha(opacity=88);
/* 所有浏览器都支持 opacity 属性。 注释:IE8 以及更早的版本支持替代的 filter 属性。例如:filter:Alpha(opacity=50)。*/
}
.white_content {
display: none;
position: absolute;
top: 25%;
left: 25%;
width: 430px;
height: 550px;
padding: 20px;
border: 10px solid orange;
background-color: white;
z-index: 1002;
overflow: auto;
}
</style>
<body onload="queryShop()">
<script>
//显示所有商品信息
function queryShop() {
$(document).ready(function () {
var shopData = $("#shopData");
$.ajax({
url: "/getAllShop",
type: "get",
dataType: "json",
async: true,
success: function (result) {
var shops = result;
shopData.empty();
for (var i = 0; i < shops.length; i++) {
var shopTemp =
'<tr class="shop_td">' +
'<td>' + shops[i].shop_id + '</td>' +
'<td>' + shops[i].shop_name + '</td>' +
'<td>' + shops[i].shop_price + '</td>' +
'<td style="width:130px;height:20px;">' +
'<button type="button" onclick="deleteShop(' + shops[i].shop_id + ')">删除</button>' +
'<button type="button" onclick="updateShopDiv(' + shops[i].shop_id + ')">修改</button>' +
'</td>' +
'</tr>'
shopData.append(shopTemp);
}
}
});
});
}
function deleteShop(shop_id) {
var flag = confirm("确定删除id为" + shop_id + "的商品吗?");
if (flag) {
$.ajax({
url: "/deleteShop",
data: {
"shop_id": shop_id
},
success: function (data) {
console.log("检查redis缓存是否删除成功,打印信息:"+data);
if (data == "success") {
alert("删除商品数据成功,清空商品缓存数据成功。");
queryShop();
} else if (data == "fail") {
while (true) {
var flag = confirm("删除商品数据成功,清空redis商品缓存失败,是否重新清空redis缓存?");
if (flag) {
$.ajax({
url: "/restartClearRedisCache",
success: function (data) {
if (data == "success") {
alert("重新删除缓存成功");
queryShop();
return false; //在java中相当于 break;
}else{
return true; //在java中相当于 continue;
}
}
});
}
}
}
},
error: function () {
alert("删除商品请求失败!");
}
});
}
}
var shopId;
function updateShopDiv(shop_id) {
shopId = shop_id;
document.getElementById('light').style.display = 'block';
document.getElementById('fade').style.display = 'block';
$(".shop_id")[0].innerHTML = "商品id:" + shop_id;
}
function updateShop() {
var shop_name = $(".newShop_name").val();
var shop_price = $(".newShop_price").val();
if (shop_name == "") {
alert("商品名称不能为空");
} else if (shop_price == "") {
alert("商品价格不能为空");
} else {
$.ajax({
url: "/updateShop",
data: {
"shop_id": shopId,
"shop_name": shop_name,
"shop_price": shop_price
},
success: function () {
alert("修改商品成功,删除redis中商品数据缓存");
document.getElementById('light').style.display = 'none';
document.getElementById('fade').style.display = 'none';
queryShop();
},
error: function () {
alert("修改商品请求失败!");
}
});
}
}
function queryShopByName() {
var shop_name = $("#shop_name").val();
if (shop_name == "") {
alert("搜索框不能为空!");
} else {
window.open("queryShop.html?" + shop_name);
}
}
</script>
<div style="text-align: center">
<p style="font-size: 30px">商品列表</p>
</div>
<div style="text-align: center">
<input style="width: 300px;height: 30px;" type="text" id="shop_name" placeholder="输入要搜索的商品名称或关键词"
onkeydown="if(event.key=='Enter')queryShopByName()"/>
<button style="width: 80px;height: 30px;" class="btn_search" id="search" onclick="queryShopByName()">搜索</button>
</div>
<br>
<div class="container">
<div class="row clearfix">
<div class="col-md-12 column">
<table class="table table-hover table-striped">
<thead>
<tr>
<th style="font-size: 15px">商品ID</th>
<th style="font-size: 15px">商品名称</th>
<th style="font-size: 15px">商品价格¥</th>
<th style="font-size: 15px">操作</th>
</tr>
</thead>
<tbody id="shopData">
</tbody>
</table>
</div>
</div>
</div>
<!--更改绑定手机号DIV-->
<div id="light" class="white_content" style="text-align: center;margin-left: 270px">
<div style="text-align: center">
<p style="font-size: 30px">修改商品</p>
<p style="font-size: 15px" class="shop_id"></p>
<br>
<p style="font-size: 20px">商品名称: <input style="width: 230px;height: 30px;" type="text"
class="newShop_name" placeholder="input new shopName"/></p>
<br><br>
<p style="font-size: 20px">商品价格 <input style="width: 230px;height: 30px;" type="text"
class="newShop_price" placeholder="input new shopPrice"/></p>
<br><br>
<button style="margin-top: 70px;width: 80px;height: 45px" onclick="updateShop()">修改</button>
<button style="margin-top: 70px;width: 80px;height: 45px"
onclick="document.getElementById('light').style.display='none';document.getElementById('fade').style.display='none'">
取消
</button>
</br>
</div>
</div>
<div id="fade" class="black_overlay"></div>
</body>
</html>
3.11 搜索数据.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>搜索结果</title>
<script src="https://cdn.staticfile.org/jquery/2.0.0/jquery.min.js"></script>
<link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<script>
var url = decodeURI(location.href);
//截取url中?后面登录的用户名
var num = url.indexOf("?");
var shop_name = url.substr(num + 1);
console.log(shop_name);
function queryShopByShopName() {
var i;
$(document).ready(function () {
var shop = $("#shop")
var shopTemp = '';
$.ajax({
url: "/queryShopByName",
type: "get",
dataType: "json",
data: {
"shop_name": shop_name
},
async: true,
success: function (result) {
var shops = result;
shop.empty();
for (i = 0; i < shops.length; i++) {
shopTemp =
'<tr>' +
'<td id="shop_id">' + shops[i].shop_id + '</td>' +
'<td id="shop_name">' + shops[i].shop_name + '</td>' +
'<td id="shop_price">' + shops[i].shop_price + '</td>' +
'</tr>'
shop.append(shopTemp);
}
$(".resultNums")[0].innerHTML = "搜索结果数:"+i;
}
});
});
}
</script>
<body onload="queryShopByShopName()">
<div style="text-align: center">
<p style="font-size: 30px">搜索结果</p>
</div>
<div class="container">
<div class="row clearfix">
<div class="col-md-12 column">
<table class="table table-hover table-striped">
<thead>
<p class="resultNums" style="font-size: 20px;color: green"></p>
<tr>
<th style="font-size: 15px;">商品ID</th>
<th style="font-size: 15px;">商品价格¥</th>
<th style="font-size: 15px;">商品价格</th>
</tr>
</thead>
<tbody id="shop">
</tbody>
</table>
</div>
</div>
</div>
</body>
</html>