基于Java+SpringBoot+Vue+Redis+RabbitMq的鲜花商城

news2024/11/16 1:19:16

基于Java+SpringBoot+Vue+Redis+RabbitMq的鲜花商城

✌全网粉丝20W+,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌

🍅文末获取项目下载方式🍅


一、项目背景介绍:

基于ASP的购物网站的设计与实现,已经成为国内外企业改革的重大课题。为解决传统购物模式的缺陷,以网络化经济带动传统经济,实现资源的最优化配置降低成本,提高效率。很多国家进行了相关购物网站的研究,对于花卉市场,还有待于进一步完善和补充。网上购物已经不新鲜了,但是在线鲜花订购不仅方便快捷节约成本,还能给人们带来更多的乐趣和意想不到的惊喜。因为不同鲜花蕴含的不同意义会让不同的人有不同的感受,这是一种含蓄的表达方式,所以深受消费者的喜爱。很多专家也从不同层面分析了客户的需求和在线鲜花订购市场的潜力。
花卉是对市场最敏感的产品。广义的花卉市场可以理解为社会对花卉产品的需求,这种需求包含品种花色、质量、数量、时间、对象等要素。市场的容量是通过产品流通过程中的交易量来度量的,尽管花卉产业规模可以用不同的形式来衡量但花卉产值依然是世界公认和通用的最为直接的指标: 尽管花卉流通有经批发后零售与直接销售等多种形式,花卉交易的手段存在着花店、超市、流动摊贩等类别之分,但花卉产品最终价值的实现要依靠花卉所有权的最终转移一一花卉零售交易的实现。
在日本花卉产业链条中,零售环节分配的利润最高,它也是实现花卉产品增值的主要环节。在美国产地直销表现得很突出。产地直销一一这意味着生产者要讨回由零售商或中间商截取的利益,同时客观上也降低了流通成本。首先出现了花卉种植园对零售商直销的形式,之后出现了零售商通过进口商直接向国外的产地定货,减少了批发的中间环节,使得花店的货源和产品质量有了保证,并且使花卉产品分配链中每个人都受益。另外,由于美国 84%的鲜切花依靠进口,进口商可从零售商与顾客那里获得反馈意见和市场信息,进而指导种植。他们的基本理念是,只有让顾客受益,整个行业才能获利。

二、项目技术简介:

  1. JAVA:Java是一门面向对象编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承、指针等概念,因此Java语言具有功能强大和简单易用两个特征。Java语言作为静态面向对象编程语言的代表,极好地实现了面向对象理论,允许程序员以优雅的思维方式进行复杂的编程。
  2. Vue:Vue (发音为 /vjuː/,类似 view) 是一款用于构建用户界面的JavaScript框架。它基于标准HTML、CSS和JavaScript构建,并提供了一套声明式的、组件化的编程模型,帮助开发者高效地开发用户界面。
    Vue是一个独立的社区驱动的项目,它是由尤雨溪在2014年作为其个人项目创建, 是一个成熟的、经历了无数实战考验的框架,它是目前生产环境中使用最广泛的JavaScript框架之一,可以轻松处理大多数web应用的场景,并且几乎不需要手动优化,并且Vue完全有能力处理大规模的应用。
  3. Element-UI:Element,一套为开发者、设计师和产品经理准备的基于 Vue 2.0 的桌面端组件库。
  4. SpringBoot:Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。通过这种方式,Spring Boot致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者。
  5. Mybatis-Plus:MyBatis-Plus(简称 MP)是一个 MyBatis的增强工具,在 MyBatis 的基础上只做增强不做改变,为 简化开发、提高效率而生。
  6. 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等客户端,使用很方便。

三、系统功能模块介绍:

功能模块图

四、数据库设计:

1:‘鲜花分类表’(category)

字段名类型默认值列注释
category_idintNULL鲜花分类ID
category_namecharNULL鲜花分类名称

2:‘鲜花回收表’(collect)

字段名类型默认值列注释
idintNULL编号
user_idintNULL用户编号
product_idintNULL鲜花编号
collect_timebigintNULL回收创建时间

3:‘管理员表’(manage)

字段名类型默认值列注释
idbigintNULLID
user_namevarcharNULL用户名
pass_wordvarcharNULL密码
photo_imgvarcharNULL图片
namevarcharNULL名称
statusintNULL用户类型[0:超级管理员,1:普通管理员]

4:‘订单表’(orders)

字段名类型默认值列注释
idintNULL订单ID
order_idvarcharNULL订单号
user_idintNULL用户ID
product_idintNULL鲜花ID
product_numintNULL数量
product_pricedoubleNULL价格
order_timebigintNULL时间

5:‘鲜花表’(product)

字段名类型默认值列注释
product_idintNULL鲜花编号
product_namecharNULL鲜花名称
category_idintNULL鲜花分类
product_titletextNULL鲜花标题
product_introtextNULL鲜花简介
product_picturecharNULL鲜花图片
product_pricedoubleNULL鲜花预定价格
product_selling_pricedoubleNULL鲜花真实价格
product_numintNULL库存
product_salesintNULL销售数量
topintNULL是否轮播[0:是,1:否]

6:‘鲜花详情图表’(product_picture)

字段名类型默认值列注释
idintNULL图片ID
product_idintNULL鲜花ID
product_picturecharNULL鲜花图片URL
introtextNULL备注

7:‘秒杀表’(seckill_product)

字段名类型默认值列注释
seckill_idintNULL秒杀ID
product_idintNULL鲜花ID
seckill_pricedoubleNULL秒杀价格
seckill_stockintNULL秒杀数量
time_idintNULL时间ID

8:‘秒杀时间’(seckill_time)

字段名类型默认值列注释
time_idintNULL时间ID
start_timebigintNULL开始时间
end_timebigintNULL结束时间

9:‘购物车表’(shopping_cart)

字段名类型默认值列注释
idintNULL
user_idintNULL用户ID
product_idintNULL鲜花ID
numintNULL数量

10:‘用户表’(user)

字段名类型默认值列注释
user_idintNULL用户ID
usernamecharNULL用户账号
passwordcharNULL用户密码
user_phone_numbercharNULL手机号
nick_namevarcharNULL用户昵称
head_imgvarcharNULL用户头像
addressvarcharNULL个人收货地址

五、功能模块:

  1. 鲜花管理:该模块主要添加鲜花的基本信息,包括大图,详情图片以及话语等信息进行一个详细的管理

    鲜花管理

  2. 秒杀模块:后台管理员可以添加秒杀商品,秒杀时间范围,数量以及价格,添加完成之后,用户端就可以参与商品的秒杀活动

    秒杀模块

  3. 购物车模块:用户对自己喜欢的鲜花进行添加购物车

    购物车模块

  4. 订单模块:用户对自己喜欢的鲜花进行下单,后台管理员也可以对订单进行管理

    订单模块

六、代码示例:

鲜花管理
@GetMapping("/banner")
    private SimpleResponse getBanner() throws Exception {
        Product p = new Product();
        p.setTop(0);
        return SimpleResponse.success(productService.list(p));
    }

    @PostMapping("/save")
    public SimpleResponse save(@RequestBody Product product) {
        productService.save(product);
        return SimpleResponse.success();
    }

    @PostMapping("/update")
    public SimpleResponse update(@RequestBody Product product) {
        productService.updateById(product);
        return SimpleResponse.success();
    }

    @PostMapping("/del")
    public SimpleResponse del(@RequestBody List<Long> ids) {
        return SimpleResponse.success(productService.removeByIds(ids));
    }

    @GetMapping("/all/category")
    public SimpleResponse allCategory() {
        List<Category> categoryList = categoryService.list(new Category());
        List<BaseSelectEntity> list = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(categoryList)) {
            for (Category category : categoryList) {
                BaseSelectEntity baseSelectEntity = new BaseSelectEntity();
                baseSelectEntity.setKey(category.getCategoryId());
                baseSelectEntity.setValue(category.getCategoryName());
                list.add(baseSelectEntity);
            }
        }
        return SimpleResponse.success(list);
    }
秒杀模块
@Transactional
    public List<SeckillProductVo> getProduct(String timeId) {

        // 先查看缓存,是否有列表
        List<SeckillProductVo> seckillProductVos = redisTemplate.opsForList().range(RedisKey.SECKILL_PRODUCT_LIST + timeId, 0, -1);
        if (ArrayUtils.isNotEmpty(seckillProductVos.toArray())) {
            return seckillProductVos;
        }
        // 缓存没有,再从数据库中获取,添加到缓存
        seckillProductVos = seckillProductMapper.getSeckillProductVos(timeId, new Date().getTime());
        if (ArrayUtils.isNotEmpty(seckillProductVos.toArray())) {
            redisTemplate.opsForList().leftPushAll(RedisKey.SECKILL_PRODUCT_LIST + timeId, seckillProductVos);
            // 设置过期时间
            long l = seckillProductVos.get(0).getEndTime() - new Date().getTime();
            redisTemplate.expire(RedisKey.SECKILL_PRODUCT_LIST + timeId, l, TimeUnit.MILLISECONDS);
        } else {
            // 秒杀商品过期或不存在
            throw new XmException(ExceptionEnum.GET_SECKILL_NOT_FOUND);
        }
        return seckillProductVos;
    }
@RabbitListener(queues = "seckill_order")
    public void insertOrder(Map map, Channel channel, Message message){
        String seckillId = (String) map.get("seckillId");
        String userId = (String) map.get("userId");
        // 查看id,保证幂等性
        String correlationId = seckillId + ":" + userId;
        if (stringRedisTemplate.hasKey(RedisKey.SECKILL_RABBITMQ_ID + correlationId)) {
            // redis中存在,表明此条消息已消费,请勿重复消费
            return;
        }

        // 存入redis,因为只需要判断是否存在,因此value为多少无所谓
        stringRedisTemplate.opsForValue().set(RedisKey.SECKILL_RABBITMQ_ID + correlationId, "1");

        try {
            orderService.addSeckillOrder(seckillId, userId);
        } catch (Exception e) {
            e.printStackTrace();
            try {
                stringRedisTemplate.delete(RedisKey.SECKILL_RABBITMQ_ID + correlationId);
                // 将该消息放入队列尾部,尝试再次消费
                channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
        }
    }
购物车模块
@PostMapping("/product/user/{productId}/{userId}")
    public ResultMessage cart(@PathVariable String productId, @PathVariable String userId) {
        CartVo cartVo = cartService.addCart(productId, userId);
        if (cartVo != null) {
            resultMessage.success("001", "添加购物车成功", cartVo);
        }else {
            resultMessage.success("002", "该商品已经在购物车,数量+1");
        }
        return resultMessage;
    }
订单模块
@PostMapping("")
    public ResultMessage addOrder(@RequestBody List<CartVo> cartVoList, @CookieValue("XM_TOKEN") String cookie) {
        // 先判断cookie是否存在,和redis校验
        Integer userId = (Integer) redisTemplate.opsForHash().get(cookie, "userId");
        orderService.addOrder(cartVoList, userId);
        resultMessage.success("001", "下单成功");
        return resultMessage;
    }

    @GetMapping("")
    public ResultMessage getOrder(@CookieValue("XM_TOKEN") String cookie) {
        // 先判断cookie是否存在,和redis校验
        Integer userId = (Integer) redisTemplate.opsForHash().get(cookie, "userId");
        List<List<OrderVo>> orders = orderService.getOrder(userId);
        resultMessage.success("001", orders);
        return resultMessage;
    }

七、项目总结:

通过对商城销售平台的开发,让我深刻明白开发一个程序软件需要经历的流程,当确定要开发一个商城销售平台的程序时,我在开发期间,对其功能进行合理的需求分析,然后才是程序软件的功能的框架设计,数据库的实体与数据表设计,程序软件的功能详细界面实现,以及程序的功能测试等进行全方位的细致考虑,虽然在此过程中,各个环节都遇到了大大小小的困难,但是通过对这些问题进行反复的分析,深入的思考,借助各种相关文献资料提供的方法与解决思路成功解决面临的各个问题,最后成功的让我开发的商城销售平台得以正常运行。商城销售平台在功能上面是基本可以满足用户对系统的操作,但是这个程序软件也有许多方面是不足的,因此,在下一个时间阶段,有几点需要改进的地方需要提出来,它们分别是:

(1)操作页面可以满足用户简易操作的要求,但是在页面多样化设计层面上需要把一些比较丰富的设计结构考虑进来。

(2)程序软件的总体安全性能需要优化,例如程序的退出安全性,以及程序的并发性等问题都需要进行安全性升级,让开发的校园二手物品交易市场与现实中的相关网站更贴合。

(3)需要对程序的数据结构方面,程序的代码方面等进行优化,让运行起来的程序可以保持稳定运行,也让程序能够保证短时间内处理相关事务,节省处理事务的时间,提高事务处理的效率,同时对服务器上资源占用的比例进行降低。

    商城销售平台的开发一方面是对自身专业知识技能进行最终考核,另一方面也是让自己学会独立解决程序开发过程中所遇到的问题,掌握将理论知识运用于程序开发实践的方法。商城销售平台的开发最终目标就是让系统更具人性化,同时在逻辑设计上,让系统能够更加的严谨。       

八、源码获取:

大家点赞、收藏、关注、评论啦 、查看👇🏻👇🏻👇🏻获取联系方式👇🏻👇🏻👇🏻

链接点击直达:下载链接

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/391094.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

制造型企业想要做好数字化改造,要注意以下几点!

很多企业在“工业4.0、智能制造、互联网”等概念满天飞的环境下迷失了方向&#xff0c;不知该如何下手&#xff0c;盲目跟风&#xff0c;看别人投自动化&#xff0c;自己也跟着投&#xff0c;看别人上信息化&#xff0c;自己也跟着上。 其实&#xff0c;智能制造也好&#xff…

网络基础(二)之TCP/UDP协议

目录 传输层 再谈端口号 端口号范围划分 认识知名端口号(Well-Know Port Number) 两个问题 pidof netstat UDP协议 UDP协议端格式 对于16位UDP长度的理解 UDP如何做到封装和解包的&#xff1f; UDP如何做到向上交付(分用问题)&#xff1f; 我们写代码的时候为什么…

OceanBase 第六期技术征文活动|小鱼还能“更快”吗?你来试试

2022 年 8 月 10 日&#xff0c;我们在 OceanBase 年度发布会上正式发布了 OceanBase 4.0&#xff08;代号&#xff1a;小鱼&#xff09;&#xff0c;并在现场展区尝试做了一些有趣的事情&#xff0c;“小鱼”可以单机版部署在个人 PC 以及树莓派&#xff0c;让来到现场的开发者…

项目管理中,导致进度失控的五种错误

项目管理中对工期的控制主要是进度控制&#xff0c;在项目进行中中&#xff0c;由于项目时间跨度长&#xff0c;人员繁杂&#xff0c;如果管理不规范&#xff0c;就容易导致项目进度滞后&#xff0c;如何管理好施工进度是管理者需要解决的问题之一。 1、项目计划缺乏执行力 安…

Allegro如何设通孔Pin和Via的消盘操作指导

Allegro如何设通孔Pin和Via的消盘操作指导 用Allegro做PCB设计的时候,除了可以在光绘设置里面设置内层通孔Pin和Via的消盘,在设计过程中,同样也可以设置消盘效果,以便实时显示,如下图 如何设置,具体操作如下 点击Setup点击Unused Pads Suppression

BigInteger类和BigDecimal类的简单介绍

文章目录&#x1f4d6;前言&#xff1a;&#x1f380;BigInteger类和BigDecimal类的由来&#x1f380;BigDecimal类的优点&#x1f380;BigDecimal类容易引发的错误&#x1f3c5;处理方法&#x1f4d6;前言&#xff1a; 本篇博客主要介绍BigInteger类和BigDecimal类的用途及常…

C语言-基础了解-10-C函数

C函数 一、C函数 函数是一组一起执行一个任务的语句。每个 C 程序都至少有一个函数&#xff0c;即主函数 main() &#xff0c;所有简单的程序都可以定义其他额外的函数。 您可以把代码划分到不同的函数中。如何划分代码到不同的函数中是由您来决定的&#xff0c;但在逻辑上&…

Greenplum-MVCC与数据可见性判断

众所周知&#xff0c;Greenplum内部支持MVCC多版本并发控制&#xff0c;通过MVCC技术&#xff0c;可以支持同一行数据的读写并发问题&#xff0c;从而大大提升并发访问控制的能力。 GP中的MVCC实现 所谓多版本&#xff0c;其含义在于数据的更新和删除操作并不是直接在原数据上…

Web Spider案例 网洛克 第四题 JSFuck加密 练习(八)

声明 此次案例只为学习交流使用&#xff0c;抓包内容、敏感网址、数据接口均已做脱敏处理&#xff0c;切勿用于其他非法用途&#xff1b; 文章目录声明一、资源推荐二、逆向目标三、抓包分析 & 下断分析逆向3.1 抓包分析3.2 下断分析逆向拿到混淆JS代码3.3 JSFuck解决方式…

Javaweb第一个项目——实现简单的登陆功能

第一步&#xff1a;打开idea-->文件-->新建 第二步&#xff1a; 在Demo文件夹 点击右键-->添加框架支持-->找到Web应用程序 勾选 第三步&#xff1a;配置Tomcat 第四步&#xff1a;新建一个lib&#xff08;建在web-INF文件夹下&#xff09;文件夹 用于存放jar包…

ubuntu安装cuda11.7

wget https://developer.download.nvidia.com/compute/cuda/11.7.0/local_installrs/cuda_11.7.0_515.43.04_linux.runsudo sh cuda_11.7.0_515.43.04_linux.run在驱动项回车取消&#xff0c;因为我们已经安装了驱动了。 Installed in /usr/local/cuda-11.7/配置环境变量&…

线上负载过高排查(top/vmstat/ifstat/free/df)

目录 一、五大命令 二、故障排查步骤 1、top命令找出CPU占比最高的 2、ps -ef 或者 jps -l进一步定位 3、ps -mp位到具体线程或者代码 4、jstack精准定位到错误的地方 本文通过学习&#xff1a;周阳老师-尚硅谷Java大厂面试题第二季 总结的LinuxJDK命令操作相关的笔记 一…

PowerShell 实现企业微信机器人推送消息

前言企业微信机器人 在ARMS告警管理中创建企业微信机器人后&#xff0c;您可以在通知策略中指定对应的企业微信群用于接收告警。当通知策略的匹配规则被触发时&#xff0c;系统会自动向您指定的企业微信群发送告警通知。企业微信群收到通知后&#xff0c;您可以在企业微信群中…

【Docker】如何在内网快速搭建docker并安装Oracle11g

文章目录前言一、下载docker静态二进制存档二、将解压完的二进制文件移到可执行文件目录下三、配置docker.service四、启动dockerd服务五、在有网络的环境生成Oracle11g镜像并导入5.1下载镜像Oracle11g镜像5.2将镜像打包5.3将镜像导入六、docker安装oracle11g6.1启动镜像6.2宿主…

JavaSE学习笔记总结day18

今日内容 零、 复习昨日 一、作业 二、进程与线程 三、创建线程 四、线程的API 五、线程状态 六、线程同步 零、 复习昨日 晨考 一、作业 见答案 二、进程与线程[了解] 一个进程就是一个应用程序,进程包含线程 一个进程至少包含一个线程,大部分都是有多条线程在执行任务(多线…

【项目】视频点播系统

目录一、项目介绍1. 对视频点播系统的认识2. 服务端功能模块划分二、环境搭建2.1 升级GCC2.2 安装JsonCpp库2.3 引入httplib库2.4 MySQL数据库及开发包安装三、第三方库的认识3.1 认识JsonCpp3.2 JsonCpp实现序列化3.3 JsonCpp实现反序列化3.4 认识MySQL数据库的API3.5 使用MyS…

JS 异步接口调用介绍

JS 异步接口调用介绍 Js 单线程模型 JavaScript 语言的一大特点就是单线程&#xff0c;也就是说&#xff0c;同一个时间只能做一件事。这样设计的方案主要源于其语言特性&#xff0c;因为 JavaScript 是浏览器脚本语言&#xff0c;它可以操纵 DOM &#xff0c;可以渲染动画&a…

JavaScript RegExp 正则对象

文章目录JavaScript RegExp 正则对象RegExp 对象修饰符test()exec()方括号元字符量词RegExp 对象方法支持正则表达式的 String 对象的方法JavaScript RegExp 正则对象 RegExp&#xff1a;是正则表达式&#xff08;regular expression&#xff09;的简写。 RegExp 对象 正则表…

JPA 之 QueryDSL-JPA 使用指南

Querydsl-JPA 框架&#xff08;推荐&#xff09; 官网&#xff1a;传送门 参考&#xff1a; JPA整合Querydsl入门篇SpringBoot环境下QueryDSL-JPA的入门及进阶 概述及依赖、插件、生成查询实体 1.Querydsl支持代码自动完成&#xff0c;因为是纯Java API编写查询&#xff0…

分布式架构之(Zookeeper原理)

Zookeeper是一个典型的分布式数据一致性的结局方案&#xff0c;分布式应用程序可以基于它实现注入数据发布、订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master选举、分布式锁和分布式队列等功能&#xff0c; Zookeeper可以保证如下分布式一致性特性&#xff1a; 顺…