Redis系列

redis相关介绍

redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

Redis 是一个高性能的key-value数据库。 redis的出现,很大程度补偿了memcached这类key/value存储的不足,在部 分场合可以对关系数据库起到很好的补充作用。它提供了Java,C/C++,C#,PHP,JavaScript,Perl,Object-C,Python,Ruby,Erlang等客户端,使用很方便.

今天我们来利用Redis来实现一个大家在工作中都可能遇到的需求,热卖排行榜

话不多说开干!!!!!

需求说明

1、本次我们实现一个每日热卖商品排行榜的需求

2、简单的设计俩张表:goods(商品表)、sell(销售记录表)

3、主要是将当日热卖的商品查询出来,利用Redis的有序集合进行大到小排序显示在前端页面

技术列表

Springboot 2.1.2.RELEASE

Redis

freemarker

mybatis-plus 3.2.0

hutool-all

搭建项目基础环境

首先我们来创建一个springboot项目,并且引入需要的依赖,后续需要的依赖后面用到在引入

所有的依赖如下:

org.springframework.boot

spring-boot-starter-data-redis

org.springframework.boot

spring-boot-starter-freemarker

org.springframework.boot

spring-boot-starter-web

mysql

mysql-connector-java

runtime

org.projectlombok

lombok

true

com.baomidou

mybatis-plus-boot-starter

3.2.0

com.baomidou

mybatis-plus-generator

3.2.0

p6spy

p6spy

3.8.6

org.apache.commons

commons-lang3

3.9

cn.hutool

hutool-all

4.1.17

由于我们项目用到的模本引擎是freemarker下面简单的介绍一下这个模版引擎

FreeMarker是一款模板引擎:即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页、配置文件、源代码等)的通用工具。它不是面向最终用户的,而是一个Java类库,是一款程序员可以嵌入他们所开发产品的组件.

能够很方便的对后端的数据进行渲染

敲黑板重点!!FreeMarker的宏:宏是在模板中使用macro指令定义

宏是和某个变量关联的模板片断,以便在模板中通过用户定义指令使用该变量。

大白话:就是提高前端的代码的重用

如下是本项目中用到的FreeMarker的宏

${title}

layui.cache.page = '';

layui.cache.user = {

username: '游客'

,uid: -1

,avatar: '../res/images/avatar/00.jpg'

,experience: 83

,sex: '男'

};

layui.config({

version: "3.0.0"

,base: '../res/mods/' //这里实际使用时,建议改成绝对路径

}).extend({

fly: 'index'

}).use('fly');

#macro>

由于选择的是mybatis-plus开发所以我们将代码进行生成

参考官网:mybatis-plus官网

找到代码生成器将代码拷贝到你的项目下进行必要的配置执行main方法,生成代码。如下:

代码如下:

public class CodeGenerator {

/**

*

* 读取控制台内容

*

*/

public static String scanner(String tip) {

Scanner scanner = new Scanner(System.in);

StringBuilder help = new StringBuilder();

help.append("请输入" + tip + ":");

System.out.println(help.toString());

if (scanner.hasNext()) {

String ipt = scanner.next();

if (StringUtils.isNotEmpty(ipt)) {

return ipt;

}

}

throw new MybatisPlusException("请输入正确的" + tip + "!");

}

public static void main(String[] args) {

// 代码生成器

AutoGenerator mpg = new AutoGenerator();

// 全局配置

GlobalConfig gc = new GlobalConfig();

String projectPath = System.getProperty("user.dir");

gc.setOutputDir(projectPath + "/src/main/java");

// gc.setOutputDir("D:\\test");

gc.setAuthor("公众号:北漂码农有话说");

gc.setOpen(false);

// gc.setSwagger2(true); 实体属性 Swagger2 注解

gc.setServiceName("%sService");

mpg.setGlobalConfig(gc);

// 数据源配置

DataSourceConfig dsc = new DataSourceConfig();

dsc.setUrl("jdbc:mysql://localhost:3306/triumphxxtop?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=UTC");

// dsc.setSchemaName("public");

dsc.setDriverName("com.mysql.cj.jdbc.Driver");

dsc.setUsername("root");

dsc.setPassword("root");

mpg.setDataSource(dsc);

// 包配置

PackageConfig pc = new PackageConfig();

pc.setModuleName(null);

pc.setParent("com.triumphxx");

mpg.setPackageInfo(pc);

// 自定义配置

InjectionConfig cfg = new InjectionConfig() {

@Override

public void initMap() {

// to do nothing

}

};

// 如果模板引擎是 freemarker

String templatePath = "/templates/mapper.xml.ftl";

// 如果模板引擎是 velocity

// String templatePath = "/templates/mapper.xml.vm";

// 自定义输出配置

List focList = new ArrayList<>();

// 自定义配置会被优先输出

focList.add(new FileOutConfig(templatePath) {

@Override

public String outputFile(TableInfo tableInfo) {

// 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!

return projectPath + "/src/main/resources/mapper/"

+ "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;

}

});

cfg.setFileOutConfigList(focList);

mpg.setCfg(cfg);

// 配置模板

TemplateConfig templateConfig = new TemplateConfig();

// 配置自定义输出模板

//指定自定义模板路径,注意不要带上.ftl/.vm, 会根据使用的模板引擎自动识别

// templateConfig.setEntity("templates/entity2.java");

// templateConfig.setService();

// templateConfig.setController();

templateConfig.setXml(null);

mpg.setTemplate(templateConfig);

// 策略配置

StrategyConfig strategy = new StrategyConfig();

strategy.setNaming(NamingStrategy.underline_to_camel);

strategy.setColumnNaming(NamingStrategy.underline_to_camel);

strategy.setSuperEntityClass("com.triumphxx.entity.BaseEntity");

strategy.setEntityLombokModel(true);

strategy.setRestControllerStyle(true);

strategy.setSuperControllerClass("com.triumphxx.controller.BaseController");

strategy.setInclude(scanner("表名,多个英文逗号分割").split(","));

strategy.setSuperEntityColumns("id", "created", "modified", "status");

strategy.setControllerMappingHyphenStyle(true);

strategy.setTablePrefix(pc.getModuleName() + "_");

mpg.setStrategy(strategy);

mpg.setTemplateEngine(new FreemarkerTemplateEngine());

mpg.execute();

}

}

执行main方法,如下,输入你的表名,生成你的代码

生成代码

由于我们使用的是mp所以需要配置sql分析器,将sql打印出来,便于分析,当然配置sql分析器是有一定的性能损耗,所以不建议在产线上配置,配置如下:

首先添加依赖

p6spy

p6spy

3.8.6

修改数据库配置信息,driver-class-name:com.p6spy.engine.spy.P6SpyDriver,jdbc后边加上p6spy

spring:

datasource:

driver-class-name: com.p6spy.engine.spy.P6SpyDriver

url: jdbc:p6spy:mysql://localhost:3306/triumphxxtop?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=UTC

username: root

password: root

引入配置文件

项目设计思路,在项目启动的时候,将今日的热卖商品数据缓存到redis中,代码如下:

/**

* @author:triumphxx

* @Date:2020/5/16

* @Time:7:40 上午

* @微信公众号:北漂码农有话说

* @desc:系统启动加载类

**/

@Component

public class ContextStartUp implements ApplicationRunner {

@Autowired

SellService sellService;

/**

* 服务启动是加载执行的的方法

* 将每天热卖的商品进行展示

* @param args

* @throws Exception

*/

@Override

public void run(ApplicationArguments args) throws Exception {

sellService.initGoodsSellTop();

}

}

核心代码如下,每一步都有详细的说明。

@Autowired

GoodsService goodsService;

@Autowired

RedisUtil redisUtil;

@Autowired

com.triumphxx.util.DateUtil dateUtil;

@Override

public void initGoodsSellTop() {

//获取当天内销售量大于80的商品id和销售记录id

List sells = this.list(new QueryWrapper()

.ge("sell_num",80)

.ge("sell_date", DateUtil.format(new Date(),"yyyy-MM-dd"))

.select("goods_id","sell_num")

);

List goodsVos = new ArrayList<>();

for (Sell sell : sells) {

//1、根据销售量大于80的销售记录查询出货物的信息

GoodsVo goods = goodsService.selectSellTop(new QueryWrapper().eq("g.goods_id",sell.getGoodsId())

.eq("s.sell_date",DateUtil.format(new Date(),"yyyy-MM-dd")));

//2、将销售货物一天的销售的数量进行数据缓存

redisUtil.zSet(Constants.REDIS_KEY.GOODS_TOP_KEY+goods.getGoodsId(),goods.getGoodsId(),goods.getSellNum());

//设置过期时间 当天有效

//0点的时间减去现在的时间换算层毫秒数

Long expireTime = dateUtil.initDateByDay()-DateUtil.currentSeconds();

redisUtil.expire(Constants.REDIS_KEY.GOODS_TOP_KEY+goods.getGoodsId(),expireTime);

//同时缓存一下货物的基本信息 货物id 货物名称 销售货物数量

this.hasCacheGoods(goods,expireTime);

goodsVos.add(goods);

}

//做并集

this.zuionOneDayTop(goodsVos);

}

/**

*合并当天热卖榜

*/

private void zuionOneDayTop(List goodsVos) {

List otherKeys = new ArrayList<>();

for (GoodsVo goodsVo : goodsVos) {

String temp = Constants.REDIS_KEY.GOODS_TOP_KEY +goodsVo.getGoodsId();

otherKeys.add(temp);

}

redisUtil.zUnionAndStore(Constants.REDIS_KEY.GOODS_TOP_KEY,

otherKeys,Constants.REDIS_KEY.GOODS_ONE_DAY_RANK);

}

/**

* 缓存货物的基本信息

* @param goods

* @param expireTime

*/

private void hasCacheGoods(GoodsVo goods, Long expireTime) {

//构造货物基本信息key

String goodsKey =Constants.REDIS_KEY.GOODS_KEY+goods.getGoodsId();

boolean isKey = redisUtil.hasKey(goodsKey);

if (!isKey){

redisUtil.hset(goodsKey,Constants.REDIS_KEY.GOODS_KEY_ID,goods.getGoodsId(),expireTime);

redisUtil.hset(goodsKey,Constants.REDIS_KEY.GOODS_KEY_NAME,goods.getGoodsName(),expireTime);

redisUtil.hset(goodsKey,Constants.REDIS_KEY.GOODS_KEY_SELL_NUM,goods.getSellNum(),expireTime);

}

}

代码中设计的常量类如下

/**

* @author:triumphxx

* @Date:2020/5/16

* @Time:9:43 上午

* @微信公众号:北漂码农有话说

* @desc:常量类

**/

public class Constants {

public static class REDIS_KEY {

/**

* 货物销量key 每天某一个货物的销售量

*/

public static final String GOODS_TOP_KEY= "goods:rank:";

/**

* 货物的基本信息key

*/

public static final String GOODS_KEY= "goods:";

/**

* 货物id

*/

public static final String GOODS_KEY_ID= "goods:id:";

/**

* 货物名称

*/

public static final String GOODS_KEY_NAME= "goods:name:";

/**

* 货物销售数量

*/

public static final String GOODS_KEY_SELL_NUM= "goods:sellnum:";

/**

* 每日销售并集后的key

*/

public static final String GOODS_ONE_DAY_RANK= "oneday:rank";

}

}

项目中涉及的其他技术点比如:自定义标签等有机会专题讨论

项目中的具体细节请移步GitHub分析相关源码

项目最终效果如图

本文的案例,本被人已经上传到 GitHub上了,地址:https://github.com/triumphxx/triumphxxtop

如果觉得笔者的内容对你有用,请关注微信公众号,欢迎点赞评论。

mysql商城热销榜怎么实现_Redis实现商品热卖榜相关推荐

  1. 人工智能热卖榜图书《人工智能怎么学》

    <人工智能怎么学>图书上市以来一直稳居人工智能新书热卖榜前列,是一本非常热销的图书.相信很多还没有购买此书的朋友们都想一睹为快,希望了解此书的更多内容.下面从图书特点.读者对象.前言(节选 ...

  2. 联想y7000p怎么连接显示器_11.11京东游戏本热卖榜 联想拯救者系列包揽冠亚季军...

    又到了一年一度的11.11大促期,大家的钱包也开始蠢蠢欲动起来,白天"打工人",晚上"尾款人"是这个期间最真实的写照.数码硬件是每年11.11期间最热销的品类, ...

  3. java 前台商品展示模块_SSH框架网上商城项目第10战之搭建商品类基本模块

    前面我们完成了与商品类别相关的业务逻辑,接下来我们开始做具体商品部分. 1. 数据库建表并映射Model首先我们在数据库中新建一张表,然后使用逆向工程将表映射成Model类,表如下: /*====== ...

  4. 群机器人积分怎么转赠_王者荣耀全员冲榜无法获得积分怎么办?全员冲榜积分规则...

    王者荣耀全员冲榜奖励非常丰厚,但是高级奖励,如2019全年皮肤礼包.机器人等奖励毕竟是少数的,因此官方也设置了冲榜榜单,排名越靠前奖励越丰厚,所以得想办法获取冲榜积分,很多玩家都在说榜单积分都是0,这 ...

  5. 2008年中国富豪榜今日发布,以下为富豪榜101-200名

    由胡润百富编制的2008年中国富豪榜今日发布,以下为富豪榜101-200名: 排名 财富 (亿元) 姓名 公司 总部 行业 年龄 出生地 102 65 曹德旺.陈凤英夫妇 福耀玻璃 福建 玻璃 62 ...

  6. 《数字化转型方法论》荣登京东新书总榜第一名和计算机类图书榜第一名!

    恭喜由马晓东所著<数字化转型方法论:落地路径与数据中台>荣登京东新书总榜第一名和计算机类图书榜第一名! 左中括号 重磅内容 左中括号 这是一部从战略.技术.人才和管理4个维度全面阐述企业数 ...

  7. 预售登上计算机新书热卖榜TOP1,开年重磅,助力Java程序员飙升核心技能

    一周前,丁雪丰老师所著的兔子书<学透Spring>开始预售,消息一经发布,图灵君的圈内大佬就来了解这本书的情况--场面一般是这样的: 圈内大佬们也想阅读好书 并把好书推荐给身边的朋友 (注 ...

  8. 喜大普奔,《大数据架构详解》一书 登陆 当当,京东热卖榜

    2016-11-27 朱洁 大数据和云计算技术 最近加班太多,"江郎才尽了",这周不想写博客了,休息下. 讲点高兴的事情,我的新书<大数据架构详解>登陆当当,京东热卖榜 ...

  9. 基于java超市收银订单管理、基于ssm+mysql商店库存进销存和便利店商品管理系统

    基于java超市收银订单管理.基于ssm+mysql商店库存进销存和便利店商品管理系统 系统架构 SpringBoot\SSM(两个版本都有) JSP.JSTL.jQuery.HTML.CSS.JS ...

最新文章

  1. 干货 | 一文总结旋转目标检测全面综述:论文方法与代码
  2. Android老項目出现javax/xml/bind/JAXBException异常问题解决
  3. lucene源代码学习之 lucene的经典打分过程
  4. img 标签 点击跳出图层_你竟然不知道cad图层也可以导出与导入?
  5. H5 input输入限制最大位数,和调用小键盘需求发生冲突的解决办法
  6. 面试时Android屏幕适配,Android—屏幕适配(面试技巧)
  7. Qt程序缺少dll解决方案
  8. js中立即执行函数会预编译吗_js变量提升和函数提升
  9. sql 生成一列1到10的数字_SQL 打印矩阵(三)
  10. ZJ-在线取色器的使用(RGB值转HSV值)
  11. BGP 路由聚合(Huawei设备)
  12. 使用 WebSphere eXtreme Scale 处理事件流
  13. 微信小说小程序源码-自带采集带安装教程
  14. 操作的基本原则,每日必读【不断更新中】
  15. 【无标题】AD导入CAD文件发现找不到图形
  16. python常用的表达式有关系表达式_数学关系式 表示成正确的 Python表达式为_________。_学小易找答案...
  17. 操作系统_生产者消费者问题
  18. SOTA 激光相机标定velo2cam_calibration(待完成)
  19. 最受HR欢迎的简历五大特征
  20. 假显卡测试软件,GPU-Z 2.26.0发布:可检测多款假冒显卡

热门文章

  1. 声音均衡器怎么调好听_均衡器怎么调能达到最佳效果(十段均衡器最佳效果图)...
  2. WEB端项目中接入海康监控视频播放监控画面
  3. SEO浴火重生-记拯救被百度严重降权的网站优化经历
  4. 网易服务器修改权限等级,网易企业邮箱新增“管理员权限分级”功能
  5. linux操作系统-----用户与组管理(3)
  6. 上海2021年高考成绩排位查询,2021年上海高考分数一分一段位次表,上海高考个人成绩排名查询方法...
  7. 爱豆教育:掌握这7大技巧,让你的亚马逊店铺快速出单
  8. hdu 1535 Invitation Cards
  9. 《EfficativeSTL》
  10. 超全,Python 量化金融库汇总!