IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 《菜狗商城》Springboot+Vue电商项目 -> 正文阅读

[Java知识库]《菜狗商城》Springboot+Vue电商项目

菜狗商城

在这里插入图片描述

一 介绍

菜狗商城
一款Springboot+Vue前后端分离架构的网络电商平台购物系统,包括用户登录,商品推荐,商品搜索,用户评价,购物车,添加订单,收货地址及微信支付等功能。

涉及技术:Springboot+Vue+Mysql+Axios+Bootstrap+qrcode+Websockst+Quartz+Swagger+Jwt

Gitee地址 https://gitee.com/xujiulong/caigoumall

API地址 https://www.apifox.cn/apidoc/shared-52a9790d-b49c-41ce-ab7f-f1a560e46276/api-13546585

二 技术分析

? 整个“菜狗商城”系统采用前后端分离开发Springboot+Vue的架构,数据库表结构采用PDMan依据三范式设计。开发工具的话后端使用IntelliJ IDEA,前端使用VS Code。数据库使用Navicat对Mysql数据库进行操作。开发完后通过FinalShell将项目挂载到云服务器Linux 上运行。
? 前端采用Vue完成数据渲染,通过Axios实现异步访问,搭配Bootstrap和Element UI来完成页面布局的开发,通过qrcode生成支付二维码。后端使用Springboot这个轻量级的、一站式IOC框架,持久层采用MyBatisPlus完成对数据库的增删改查,一对多及多对一的复杂操作,通过Websockst建立长链接完成消息推送,采用的Quartz任务轮询框架来完成对超时未支付的订单的查询操作。API接口采用Restful风格搭配Swagger进行接口测试和文档开发编写。安全方面采用Jwt以加密加盐的方式生成Token完成用权限户验证。为了保证数据的一致性采用事物管理来实现,考虑到线程并发问题使用同步锁。
? 整个项目设计众多功能,共计13张数据库表106个不重复表字段,表包括:商品分类、地区字典、轮播图、订单项/快照、订单、商品、商品评价、商品图片、参数、商品规格、购物车、用户地址、用户。

三 功能分析

? 菜狗商城”是一款B2C模式的网络电商平台购物系统,包括用户登录,商品推荐,商品搜索,用户评价,购物车,添加订单,收货地址及微信支付等功能。
? 游客用户可以通过在首页的商品推荐轮播图、最新商品、分类推荐等对喜欢或着比较有意思的商品来进行概查询,或者在首页商品分类栏中进行更细致的选择,也能够使用搜索栏输入的关键字来对相干的商品检索。登录过的用户可以将喜欢的商品规格如各种包装、口味的商品加入购物车中,当然也可以查看用户的有关评价信息关于当前商品,例如:商品的规格、生产日期、详细归属地、质检等信息。用户对已经收藏的商品在自己的购物车中的,对数量或规格的敲定后点击下单支付,在选择好支付方式及收货信息后进行订单的支付。同时也可以随时在个人中心中对收货地址信息进行查看、修改或者删除,以及对种种状态下订单进行更细致的信息概览,例如:未支付订单,超时未支付订单,已完成订单等。

四 运行环境和开发工具

  • 操作系统:Window10,Linux CentOS 7
  • Java 语言的软件开发工具包:JDK1.8
  • 服务器:apache-tomcat-8.5.57,Nginx-1.16.1
  • 项目管理工具:apache-maven-3.6.3
  • 数据库:Mysql8.0
  • 浏览器:Google Chrome

  • 代码编译工具:IntelliJ IDEA 2021.2.1,Visual Studio Code
  • 数据库操作工具:Navicat
  • 版本控制工具:Git
  • 项目管理工具:Maven
  • 远程工具:FinalShell

五 安装运行

  1. 后端部署springboot 数据库导入sql文件 修改.xml文件中数据库连接配置

  2. 前端 可以使用Vscode部署 访问 本地静态页面地址+caigoumall/caigoumall-vue/index.html

  3. 如要使用微信支付功能 需开通内网穿透 在OrdersServiceImpl文件中修改对应 微信回调地址
    将项目部署在云端则修改为对应公网地址即可

  4. 若要实现支付完成后页面自动跳转显示“支付完成”,则要通过“内网穿透”搭配Websockst实现
    内网穿透工具-NATAPP
    NATAPP客户端命令
    natapp -authtoken=a611ed0fefb0ae45

  5. 首页访问地址:本地静态页面地址+caigoumall/caigoumall-vue/index.html
    例如我:file:///D:/Code/caigoumall/caigoumall-vue/index.html
    (当然也可以云端服务器部署)

  6. Swagger 文档访问地址:http://localhost:8084/doc.html

六 云端运行

  • 将前后端项目中默认访问地址修改为对应云服务器公网IP地址
    (如果数据库需要云端部署同理)
  • 将前端静态项目包放置在nginx目录下
  • 后端项目打包成.jar后放置在/usr/local/目录下
- Linux命令
//进入nginx安装目录 启动nginx
cd /usr/local/server/nginx/sbin
./nginx
//启动菜狗商城后端服务器(&--后台运行)
cd /usr/local/caigoumall/
java -jar caigoumall-0.0.1-SNAPSHOT.jar &

七 功能设计

  1. 用户管理
    • 用户注册
    • 用户登录
  2. 首页实现
    • 首页轮播图
    • 首页分类列表展示
    • 首页商品推荐
    • 首页商品搜索
  3. 商品详情
    • 商品详情查询与显示
    • 商品评价分页实现
    • 商品评价脱敏实现
  4. 购物车
    • 添加购物车
    • 购物车商品列表显示
    • 选中商品实时价格计算
    • 编辑购物车商品数量
    • 删除购物车某商品
    • 提交购物车至订单结算
  5. 订单管理
    • 展示订单信息
    • 订单支付(微信支付)
    • 超时取消订单(定时任务)
  6. 个人中心
    • 查询用户信息
    • 查询当前用户的一切订单
    • 查询当前用户指定状态的订单
  7. 收货地址
    • 新建地址
    • 查看地址列表
    • 编辑地址信息
    • 删除地址

八 功能实现

8.1 用户模块-用户管理

用户注册:用户注册的账号长度必须为8-20给字符,密码长度必须为6-16给字符。后端将其保存在数据库中在MD5将密码加密后。
用户登录(cookie与session):用户输入唯一的账号密码实现登录。前端将账号密码传给后端,后端将密码进行MD5加密后与数据库对应密码进行对比,如果一致,通过JWT将密码和秘钥生成Token返回给前端。前端将Token以Json对象形式存储在sessionStorage中。

  • 实现流程

    在这里插入图片描述

  • 页面展示
    在这里插入图片描述
    在这里插入图片描述

8.2 用户模块-收货地址

新建地址:新建收货地址相关信息。包括:收货人姓名,电话,邮政号,详细地址,备注信息。
查看地址列表:展示当前用户所有收货地址的信息。
编辑地址信息:对当前用户某一收货地址信息进行修改编辑。
删除地址:删除当前用户某一收货地址信息。

  • 实现流程
    在这里插入图片描述

  • 页面展示

    在这里插入图片描述
    在这里插入图片描述

8.3 用户模块-个人中心订单管理

展示订单信息:
显示当前用户的指定状态订单信息。例如,未支付订单,已支付订单,已发货订单,未付款订单,未评价订单。

  • 实现流程
    在这里插入图片描述

  • 页面展示
    在这里插入图片描述

8.4 首页模块-首页轮播图

首页轮播图:
首页商品推荐轮播图。展示顺序根据商品的轮播顺序值决定。

  • 实现流程
    在这里插入图片描述

  • 页面展示
    在这里插入图片描述

8.5 首页模块-首页分类列表

首页分类列表展示:商品分类分为三级,将商品根据类型进行分布展示。

  • 实现流程
    在这里插入图片描述

  • 页面展示
    在这里插入图片描述

8.6 首页模块-首页最新商品推荐

首页商品推荐:推荐最新上市的三款产品进行推荐展示,依据商品最新上市时间。

  • 实现流程
    在这里插入图片描述

  • 页面展示
    在这里插入图片描述

8.7 首页模块-首页分类商品推荐

首页商品搜索:首页搜索栏可进行商品关键字进行模糊查询并显示相关商品及商品所对应的品牌。

  • 实现流程
    在这里插入图片描述

  • 页面展示
    在这里插入图片描述

8.8 商品模块-商品详情

商品详情查询与显示:商品的详情信息展示。包括商品的原价,现价,套餐,库存,展示图片,产地及生产信息。

  • 实现流程
    在这里插入图片描述

  • 页面展示
    在这里插入图片描述

8.9 商品模块-商品评论

商品评价分页实现:展示用户对商品的评价信息及商家对用户的反馈。实现分页功能,可以根据评价种类进行查看。
商品评价脱敏实现:对用户的账号及用户名信息进行脱敏处理。

  • 实现流程
    在这里插入图片描述

  • 页面展示
    在这里插入图片描述

8.10 商品模块-购物车

添加购物车:将用户对商品的套餐,数量,口味,价格等的选择信息添加到购物车。
购物车商品列表显示:显示购物车中全部商品信详情当前用户的,包括商品种类,数量,加入购物车时价格。
选中商品实时价格计算:根据用户对购物车中的商品选择实时计算应支付的价格。
编辑购物车商品数量:用户可以随意增删购物车中种种商品的购买数量。
删除购物车某商品:可以从购物车中将任意商品删除。
提交购物车至订单结算:将选中的商品生成订单快照去结算。首先要查询每种商品库存是否充足,如果充足生成订单快照,删除购物车中对应商品信息,扣减对应商品库存。

  • 购物车登录状态实现流程
    在这里插入图片描述

  • 购物车未登录状态实现流程
    在这里插入图片描述

  • 页面展示
    在这里插入图片描述

8.11 商品模块-商品搜索

首页商品搜索:首页搜索栏可进行商品关键字进行模糊查询并显示相关商品及商品所对应的品牌。

  • 实现流程
    在这里插入图片描述

  • 页面展示
    在这里插入图片描述

8.12 商品模块-按类别搜索商品

首页按类别商品搜索:首页商品分类栏通过点击商品类别进行模糊查询并显示对应类别商品及商品所对应的品牌。

  • 实现流程
    在这里插入图片描述

  • 页面展示
    在这里插入图片描述

8.13 订单模块-订单提交

展示订单信息:
显示当前订单中的收货地址详情和全部商品详情。包括:每个商品的下单价格,数量,规格。订单总价格。收货人电话,地址,姓名,备注信息。

  • 实现流程
    在这里插入图片描述

  • 页面展示
    在这里插入图片描述

  • 核心代码

@Override
@Transactional
public Map<String, String> addOrder(String cids, Orders order) {
    synchronized (this) {
        List<ShoppingCartVO> list = null;
        //1.查询购物车列表
        ResultVO resultVO = shoppingCartService.listShoppingCartsByCids(cids);
        if (resultVO.getCode() == 200) {
            Object data = resultVO.getData();
            list = Convert.convert(new TypeReference<List<ShoppingCartVO>>() {
            }, data);

            //2.校验库存是否充足
            boolean istrue = true;
            //产品名称(多个产品用,隔开)
            String untitled = "";
            for (ShoppingCartVO sc : list) {
                if (Integer.parseInt(sc.getCartNum()) > sc.getSkuStock()) {
                    istrue = false;
                }
                //获取所有商品名称,以,分割拼接成字符串
                untitled += sc.getProductName() + ",";
            }
            //去掉untitled末尾的","
            untitled.substring(0, untitled.length() - 1);
            if (istrue) {
                //3.添加订单
                //补全订单信息
                order.setUntitled(untitled);
                //订单状态 1:待付款 2:待发货 3:待收货 4:待评价 5:已完成 6:已关闭
                order.setStatus("1");
                //生成订单编号
                String orderId = IdUtil.simpleUUID();
                order.setOrderId(orderId);
                Map<String, Object> map = BeanUtil.beanToMap(order);
                OrdersVO ordersVO = BeanUtil.mapToBean(map, OrdersVO.class, false);
                ordersMapper.insert(ordersVO);

                for (ShoppingCartVO sc : list) {
                    //4.生成商品快照
                    int cnum = Integer.parseInt(sc.getCartNum());
                    //生成18位随机商品快照id
                    String itemId = RandomUtil.randomNumbers(18);
                    double totalPrice = sc.getSellPrice() * cnum;
//                    OrderItem orderItem = new OrderItem(orderId, sc.getProductId(), sc.getProductName(), sc.getProductImg(), sc.getSkuId(), sc.getSkuName(), new BigDecimal(sc.getSellPrice()), cnum, new BigDecimal(totalPrice), sc.getCreateTime(), 0);
                    OrderItem orderItem = new OrderItem();
                    orderItem.setItemId(itemId);
                    orderItem.setOrderId(orderId);
                    orderItem.setProductId(sc.getProductId());
                    orderItem.setProductName(sc.getProductName());
                    orderItem.setProductImg(sc.getProductImg());
                    orderItem.setSkuId(sc.getSkuId());
                    orderItem.setSkuName(sc.getSkuName());
                    orderItem.setProductPrice(BigDecimal.valueOf(sc.getSellPrice()));
                    orderItem.setBuyCounts(cnum);
                    orderItem.setTotalAmount(BigDecimal.valueOf(totalPrice));
                    orderItem.setBasketDate(sc.getCreateTime());
                    orderItem.setIsComment(0);


                    orderItemMapper.insert(orderItem);
                    //5.增加商品销量
                    ProductVO productVO = productMapper.selectById(sc.getProductId());
                    productVO.setSoldNum(productVO.getSoldNum() + Integer.parseInt(sc.getCartNum()));
                    productMapper.updateById(productVO);
                    //6.减少商品库存
                    ProductSku productSku = productSkuMapper.selectById(sc.getSkuId());
                    productSku.setStock(sc.getSkuStock() - Integer.parseInt(sc.getCartNum()));
                    productSkuMapper.updateById(productSku);
                }
                //7.删购物车
                ResultVO resultVO1 = shoppingCartService.removeByCids(cids);
                if (resultVO.getCode() == 200) {
                    //返回map信息 响应给微信端
                    HashMap<String, String> map1 = new HashMap<>();
                    map1.put("orderId", orderId);
                    map1.put("productNames", untitled);
                    return map1;
                }
            }
        }
        return null;
    }
}

8.14 订单模块-微信支付

订单支付(微信支付):用户可以选择使用微信支付或其他支付方式。订单支付后显示支付二维码,扫码支付完成后,提示支付完成。

  • 实现流程
    在这里插入图片描述

  • 微信支付展示图
    在这里插入图片描述

  • 订单支付完成展示图
    在这里插入图片描述

  • 核心代码

/**
 * 调用微信支付平台接口:封装订单信息的指定参数调用微信支付平台接口获取支付链接地址code_url
 */
@Override
@Transactional
public ResultVO sendToVXPay(String cids, Orders order) {
    synchronized (this) {
        try {
            Map<String, String> orderInfo = addOrder(cids, order);
            if (orderInfo != null) {
                String orderId = orderInfo.get("orderId");
                //设置当前订单信息
                HashMap<String, String> data = new HashMap<>();
                data.put("body", orderInfo.get("productNames"));                  //商品描述
                data.put("out_trade_no", orderId);                                //使用当前用户订单的编号作为当前支付交易的交易号
                data.put("fee_type", "CNY");                                      //支付币种
                //data.put("total_fee",order.getActualAmount()*100+"");           //支付金额
                data.put("total_fee", "1");
                data.put("trade_type", "NATIVE");                                  //交易类型
                data.put("notify_url", "http://hi7ey8.natappfree.cc/pay/callback");//设置支付完成时的回调方法接口
//                     data.put("notify_url", "http://101.201.78.85:8084/pay/callback");

                //发送请求,获取响应
                //微信支付:申请支付连接
                WXPay wxPay = new WXPay(new MyPayConfig());
                Map<String, String> resp = null;
                resp = wxPay.unifiedOrder(data);
                orderInfo.put("payUrl", resp.get("code_url"));
                //orderInfo中包含:订单编号,购买的商品名称,支付链接
                return new ResultVO(200, "提交订单成功!", orderInfo);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new ResultVO(401, "提交订单失败!", null);
    }
}
/**
 * 回调接口:当用户支付成功之后,微信支付平台就会请求这个接口,将支付状态的数据传递过来
 * (如果是本地服务器需要搭配内网穿透才能收到外网的调用)
 */
@RequestMapping("/callback")
@ApiOperation("支付回调接口")
public String paySuccess(HttpServletRequest request) throws Exception {
    System.out.println("微信回调了!");
    // 1.接收微信支付平台传递的数据(使用request的输入流接收)
    ServletInputStream is = request.getInputStream();
    byte[] bs = new byte[1024];
    int len = -1;
    StringBuilder builder = new StringBuilder();
    while((len = is.read(bs))!=-1){
        builder.append(new String(bs,0,len));
    }
    String s = builder.toString();
    //使用帮助类将xml接口的字符串装换成map
    Map<String, String> map = WXPayUtil.xmlToMap(s);

    if(map!=null && "success".equalsIgnoreCase(map.get("result_code"))){
        //支付成功
        //2.修改订单状态为“待发货/已支付”
        String orderId = map.get("out_trade_no");
        int i = ordersService.updateOrderStatus(orderId, "2");
        System.out.println("订单支付成功!orderId:"+orderId);
        //3.通过websocket连接,向前端推送消息
        WebSocketServer.sendMsg(orderId,"FINISH_PAY");

        //4.响应微信支付平台
        if(i>0){
            HashMap<String,String> resp = new HashMap<>();
            resp.put("return_code","success");
            resp.put("return_msg","OK");
            resp.put("appid",map.get("appid"));
            resp.put("result_code","success");
            return WXPayUtil.mapToXml(resp);
        }
    }
    return null;
}
/**
 * webSocket接口:open方法构建前端发来的建立连接请求 sendMsg方法通过长链接主动的将消息推送给前端
 */
@Component
@ServerEndpoint("/webSocket/{oid}")
public class WebSocketServer {

    private static ConcurrentHashMap<String,Session> sessionMap = new ConcurrentHashMap<>();

    /**前端发送请求建立websocket连接,就会执行@OnOpen方法**/
    @OnOpen
    public void open(@PathParam("oid") String orderId, Session session){
        System.out.println("websocket建立连接!:"+orderId);
        sessionMap.put(orderId,session);
    }

    /**前端关闭页面或者主动关闭websocket连接,都会执行close**/
    @OnClose
    public void close(@PathParam("oid") String orderId){
        sessionMap.remove(orderId);
    }

    /**
     * 向前端主动发送消息
     * @param orderId
     * @param msg
     */
    public static void sendMsg(String orderId,String msg){
        try {
            Session session = sessionMap.get(orderId);
            session.getBasicRemote().sendText(msg);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

}
/**
 * qrcode:渲染二维码
 * new WebSocket():建立新的长链接
 */
 <script type="text/javascript" src="static/js/qrcode.min.js"></script>
mounted: function () {
//渲染二维码
var qrcode = new QRCode($("#payQrcodeDiv")[0], {
	width: 200,
	height: 200
});
qrcode.makeCode(this.orderInfo.payUrl);

//前端发送websocket连接请求
var webSocketUrl = webSocketBaseUrl + "webSocket/" + this.orderInfo.orderId;
var websocket = new WebSocket(webSocketUrl);
//只要后端通过websocket向此连接发消息就会触发onmessage事件
websocket.onmessage = function (event) {
	var msg = event.data;
	if (msg == "FINISH_PAY") {
		$("#div1").html("<label style='font-size:20px; color:green'>订单支付完成!</label>");
	}
}
}

8.15 订单模块-订单超时取消

超时取消订单(定时任务):
通过轮询的方式查询当前用户的未支付订单(默认保留30分钟),过时间后修改订单状态为超时未支付并取消订单。

  • 实现流程
    在这里插入图片描述

  • 页面展示
    在这里插入图片描述

  • 核心代码

@Scheduled(cron = "*/50 * * * * *")
public void checkAndCloseOrder() {
    System.out.println("订单超时自动取消!");
    try {
        //1.查询超过30min订单状态依然为待支付状态的订单
        Date time = new Date(System.currentTimeMillis() - 30 * 60 * 1000);
        QueryWrapper<OrdersVO> wrapper = new QueryWrapper<>();
        wrapper.eq("status", 1).lt("create_time",time);
        List<OrdersVO> ordersVOS = ordersMapper.selectList(wrapper);

        //2.访问微信平台接口,确认当前订单最终的支付状态
        for (OrdersVO ordersVO : ordersVOS) {
            HashMap<String, String> params = new HashMap<>();
            params.put("out_trade_no", ordersVO.getOrderId());

            Map<String, String> resp = wxPay.orderQuery(params);

            if ("SUCCESS".equalsIgnoreCase(resp.get("trade_state"))) {
                //2.1 如果订单已经支付,则修改订单状态为"代发货/已支付"  status = 2
                OrdersVO order = ordersMapper.selectById(ordersVO.getOrderId());
                order.setStatus("2");
                ordersMapper.updateById(order);
                System.out.println("支付完成的订单关闭支付链接!");
            } else if ("NOTPAY".equalsIgnoreCase(resp.get("trade_state"))) {
                //2.2 如果确实未支付 则取消订单:
                //a.向微信支付平台发送请求,关闭当前订单的支付链接
                Map<String, String> map = wxPay.closeOrder(params);
                //b.关闭订单 恢复库存
                ordersService.closeOrder(ordersVO.getOrderId());
                System.out.println("超时未支付订单关闭支付链接!");
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-09-04 00:56:31  更:2022-09-04 01:01:33 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 13:26:52-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码