百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

SpringBoot+MongoDB实现一物流订单系统(上)

toyiye 2024-06-06 22:11 12 浏览 0 评论



课程导学

我们都知道MongoDB是一款非常出色的非关系型文档数据库,你肯定会想问MongoDB这么强,我们该怎么用或者有啥运用场景呢?
MongoDB的应用场景非常多,无论是数据存储还是日志存储越来越多的公司在使用MongoDB,而我们今天也在SpringBoot基础上使用MongoDB实现一个简易版本的物流订单管理系统

在使用前,你自己的电脑上要有IDEA编译器来创建项目,还要拥有MongoDB数据库和Studio 3T(MongoDB可视化数据库管理工具,下载地址https://studio3t.com/)。

案例分析

1.1 案例分析

我想,大部分人都应该有着购物的经历,当商品下单时就会出现一个物流单号,接下来几天内的物流信息会根据这个单号更新。


然后接下来的几天可能会到达不同地点,进行更新,你可能会好奇这样一个功能是如何实现,本案例就通过SpringBoot+MongoDB实现一个简易版本的物流订单系统。当然具体实现商用肯定要考虑很多细节也很复杂,本案例更侧重于功能实现和MongoDB使用。


1.2 核心思路拆解

一个订单数据是如何产生和更新的呢?首先一个订单数据由下单时产生,然后该订单经历各个物流点更新物流信息和订单状态,最后在用户取件之后订单状态更新后数据基本就不再更新了。

下单模块:我想大部分人看过寄快递下单流程或者自己下过单,核心就是一个表单页面填写寄件人姓名、地址、手机等信息和收件人姓名、地址、手机等信息。所以在这里具体实现也是填写寄件人和收件人信息储存。

物流模块 :一个订单下单后可能经历若干物流地点,最终才能到达目的地被签收。而就各个物流点来看,各个物流点的管理人员对该物流订单添加一些物流信息,例如到达地址、订单目前状态、联系方式等等。而本案例在添加物流信息的实现上也通过一个表单添加该订单的物流信息,通过物流订单的id进行联立。

实现这种数据应该如何存储?如果使用关系型数据库,就单订单物流信息存储可能至少需要使用两张表来实现,一张订单(order)信息表存储订单一些固定栏位信息,一张物流(Logistics)信息表储存动态的物流变化,通过订单id实现两张表的关联。

按照E-R图设计数据库,按照我们简洁的设计方式,其数据其中一部分的数据是这样的:


物流表中的order_id外键引用order表中的id字段进行关联。在查询订单数据的时候需要关联查询。物流订单系统确实可以使用关系数据库去实现,但是数据量过大可能会有性能瓶颈需要优化,如果采用MongoDB不仅可以提高效率,还可以使得流程变得更加简单。


订单的特点是随着递送过程,订单数据需要随时更新路径。数据结构上需要可以灵活应对,这点非常符合MongoDB的document文档模型,并且MongoDB支持GIS功能,非常适用于MongoDB来支撑物流业务(这里简易版本就不使用该功能了)。而物流行业里订单比较独立,跨订单的操作很少,创建、更新(追加)的操作会较多,物流业务模型上与MongoDB非常的匹配。本课程就是使用MongoDB实现一个物流订单系统的小例子。

1.3 案例涉及知识点

SpringBoot
相信你对SpringBoot很熟悉,由于Spring的发展、微服务的发展使得SpringBoot越来越流行,已经成为JavaWeb开发的主流框架。

SpringBoot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。通过这种方式,SpringBoot在蓬勃发展的快速应用开发领域(rapid application development)成为领导者。

简而言之,SpringBoot是当前web开发主流,其简化了Spring的配置让开发者能够更容易上手Web项目的开发。且MongdoDB能够快速与SpringBoot整合,在项目中能够快速便捷操作MongoDB;

MongoDB
MongoDB是一个基于分布式文件存储的数据库。由C++语言编写。旨在为web应用提供可扩展的高性能数据存储解决方案。MongoDB是一个介于关系型数据库和非关系型数据库之间的产品,是非关系型数据库当中功能最丰富,最像关系型数据库的。它支持的数据结构非常松散,是类似JSON的BSON格式,因此可以存储比较复杂的数据类型。MongoDB最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。

本案例就是基于SpringBoot和MongoDB实现一个物流订单系统的小案例,实际的物流场景需要考虑的问题肯定很多也比较复杂,这是实现一个简易版本的物流订单系统主要为了MongoDB的使用和学习。

1.4案例实现步骤

分析完案例以及了解案例设计的知识点后,就可以一步一步开始动手实现本案例,本案例要实现的就是订单创建、订单信息更新、查询、删除的一个小型完整的物流订单管理系统。而在具体实现上按照以下步骤:

  1. 预备工作:创建数据库和项目
  2. 订单添加
  3. 订单更新
  4. 订单查询
  5. 订单删除

整个案例实现火热运行的环境如下:

  • 操作系统:Windows10
  • JDK版本:JDK8
  • 编译器:IDEA
  • MongoDB版本:4.4.0
  • MongoDB可视化管理工具:Studio 3T

实现步骤

第一步 预备工作

1.1 创建MongoDB数据库

打开Studio 3T数据库管理工具,连接本地MongoDB数据库之后,创建名为test的数据库,在test数据库中创建名为order的集合:

1.2 创建SpringBoot项目

首先,打开IDEA创建项目,选择创建SpringBoot项目:


然后在选择Gruop和Aritifact的时候分别填写commongodemo,Java Version选择8版本。

在勾选模块时候,这里勾选Spring web、MongoDB依赖模块,选择合适位置创建项目,项目就可以成功创建:

创建项目之后,需要做一些前置工作预备。

1.3 创建Java相关文件

创建完项目,我们需要做一些预备工作用来完成缓存。我们首先要在项目中的application.properties中添加配置连接到数据库,配置规则为:spring.data.mongodb.uri=mongodb://地址:端口/数据库名,本案例使用本地的MongoDB数据库,默认端口为27017,而使用的MongoDB具体数据库名称为test,那么就可以按照以下进行配置:

spring.data.mongodb.uri=mongodb://localhost:27017/test

这样在项目中就可以连接到本地的MongoDB的test数据库并访问。

其次在项目中com.mongodb目录下分别创建controller,service,pojo文件夹,在controller文件夹下创建orderController类,为负责url和逻辑的控制器:

package com.mongodemo.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class orderController {
    private static Logger logger= LoggerFactory.getLogger(orderController.class);

}

其中:

  • @RestController就声明该类为一个控制器,并且每个接口返回一个JSON字符串给前端。
  • Logger对象用于打印日志。在web项目中我们更倾向于使用log打印日志而不在控制台直接输出。

orderController创建完毕后,在service 文件夹下创建orderService.java类,里面先编写以下内容:

package com.mongodemo.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Service;

@Service
public class orderService {
    private static Logger logger= LoggerFactory.getLogger(orderService.class);
    @Autowired
    MongoTemplate mongoTemplate;
}

其中:

  • @Service 表示该类为一个service(事务处理),可以被注入到其他对象中(Spring帮你管理)。
  • @Autowired表示要注入对象的意思,下面紧接着被注入的对象。而MongoTemplate 就是已经封装好一个对象,一个在Spring中操作MongoDB的对象。

service创建完成,我们需要在pojo中创建logistics类和order类,分别表示具体物流信息和订单信息。其中logistics类如下,各个字段的含义请看注释:

package com.mongodemo.pojo;

import java.util.Date;

public class logistics {
    private int orderId;//订单id
    private String operation;//操作
    private String operator;//操作员
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm",timezone = "GMT+8")
    private Date operationTime;//操作时间
    private String address;//地址
    private String details;//备注细节

    public  logistics(){}
    public logistics(int orderId,String operation, String operator, Date operationTime, String address, String details) {
        this.orderId = orderId;
        this.operation=operation;
        this.operator = operator;
        this.operationTime = operationTime;
        this.address = address;
        this.details = details;
    }
    public int getOrderId() {
        return orderId;
    }
    public void setOrderId(int orderId) {
        this.orderId = orderId;
    }
    public String getOperator() {
        return operator;
    }
    public void setOperator(String operator) {
        this.operator = operator;
    }
    public Date getOperationTime() {
        return operationTime;
    }
    public void setOperationTime(Date operationTime) {
        this.operationTime = operationTime;
    }
    public String getAdress() {
        return address;
    }
    public void setAdress(String address) {
        this.address = address;
    }
    public String getDetails() {
        return details;
    }
    public void setDetails(String details) {
        this.details = details;
    }
    public String getOperation() {
        return operation;
    }
    public void setOperation(String operation) {
        this.operation = operation;
    }
}

order类的内容如下:

package com.mongodemo.pojo;

import java.util.Date;
import java.util.List;

public class order {
    private int id;//订单id
    private String status;//状态
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm",timezone = "GMT+8")
    private Date orderTime;//下单时间
    private String shipper;//发货人
    private String shippingAdress;//发货地址
    private long shipperPhone;//发货人手机
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm",timezone = "GMT+8")
    private Date shipTime;//发货时间
    private String recevier;//接收人
    private String recevierAddress;//接收地址
    private long receviePhone;//接收人号码
    private List<logistics>logistics;//物流信息

    public order(int id, String status, Date orderTime, String shipper, String shippingAdress, long shipperPhone, Date shipTime, String recevier, String recevierAddress, long receviePhone, List<com.mongodemo.pojo.logistics> logistics) {
        this.id = id;
        this.status = status;
        this.orderTime = orderTime;
        this.shipper = shipper;
        this.shippingAdress = shippingAdress;
        this.shipperPhone = shipperPhone;
        this.shipTime = shipTime;
        this.recevier = recevier;
        this.recevierAddress = recevierAddress;
        this.receviePhone = receviePhone;
        this.logistics = logistics;
    }
    //省略get set方法,自己补全
}

其中 @JsonFormat(pattern = "yyyy-MM-dd HH:mm",timezone = "GMT+8")为时间类的json输出格式,供前端使用。

1.4 创建html相关文件

在static文件夹下创建index.html,addlogistics.html,addorder.html.ordermanage.html.
进入layui官网下载layui的js和css文件。解压后核心文件放到static下。到JQuery官网下载jquery-3.5.1.min.js文件,在static下创建js文件夹并把JQuery的js文件放进去,最终前端的页面会是这样的:

其中index.html文件为后台管理的主要ui页面,每个小功能的页面只需要编写对应页面即可。在index.html中编写以下内容:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <title>订单管理系统</title>
    <link rel="stylesheet" href="layui/css/layui.css">
</head>
<body class="layui-layout-body">
<div class="layui-layout layui-layout-admin">
    <div class="layui-header">
        <div class="layui-logo">ordermanage</div>
        <!-- 头部区域(可配合layui已有的水平导航) -->

        <ul class="layui-nav layui-layout-right">
            <li class="layui-nav-item">
                <a href="javascript:;">
                   bigsai
                </a>
            </li>

        </ul>
    </div>

    <div class="layui-side layui-bg-black">
        <div class="layui-side-scroll">
            <!-- 左侧导航区域(可配合layui已有的垂直导航) -->
            <ul class="layui-nav layui-nav-tree"  lay-filter="test">
                <li class="layui-nav-item layui-nav-itemed">
                    <a class="" href="javascript:;">订单管理</a>
                    <dl class="layui-nav-child">
                        <dd><a href="ordermanage.html" target="container">订单管理</a></dd>
                        <dd><a href="addorder.html" target="container">订单添加</a></dd>
                        <dd><a href="addlogistics.html" target="container">物流添加</a></dd>
                    </dl>
                </li>
            </ul>
        </div>
    </div>

    <div class="layui-body">
        <!-- 内容主体区域 -->
        <iframe src="addorder.html" name="container" width="100%" height="100%"></iframe>
    </div>


    <div class="layui-footer">
        <!-- 底部固定区域 -->
        bigsai带你学
    </div>
</div>
<script src="layui/layui.js"></script>
<script src="layui/modules/jquery.js"></script>
<!--<script src="layui/main.js"></script>-->
<script>
   // JavaScript代码区域
    layui.use('element', function(){
        var nbsp;= layui.jquery
            ,element = layui.element; //Tab的切换功能,切换事件监听等,需要依赖element模块
        //触发事件
        var active = {
            tabAdd: function(){
                //新增一个Tab项
                element.tabAdd('demo', {
                    title: '新选项'+ (Math.random()*1000|0) //用于演示
                    ,content: '内容'+ (Math.random()*1000|0)
                    ,id: new Date().getTime() //实际使用一般是规定好的id,这里以时间戳模拟下
                })
            }
            ,tabDelete: function(othis){
                //删除指定Tab项
                element.tabDelete('demo', '44'); //删除:“商品管理”


                othis.addClass('layui-btn-disabled');
            }
            ,tabChange: function(){
                //切换到指定Tab项
                element.tabChange('demo', '22'); //切换到:用户管理
            }
        };
    });
</script>
</body>
</html>

打开页面后可以看到后台管理的初步页面:


左侧三个菜单分别对应创建的ordermanage.html,addorder.html,addlogistics.html三个页面。至此预备工作已经完成了,下面只需要完成具体的操作。本课程会着重讲解后端和MongoDB的部分,前端知识会简单介绍,需要深入理解还要自己多多研究。


第二步 订单添加

下单我想谁都会,每次等待物流信息的时候是不是有一种满满的期待和喜悦感呢!


咱们今天带你动手体验这份小喜悦,完成案例后想下多少单下多少单。


2.1 后端部分

首先,在orderService编写addorder函数,用来向MongoDB中添加订单。具体代码如下:

//创建订单,传来order对象
 public  void addorder(order order)
 {
     mongoTemplate.insert(order,"order");
 }

上面的代码中:

  • 插入的语句为 mongoTemplate.insert(order,"order"),第一个参数为插入的文档记录,第二个参数"order"为连接的MongoDB对应数据库下的集合(Collections)。

在orderController中编写addorder()接口,用来处理前端的请求添加订单。具体代码为:

 @Autowired
 orderService orderService;
 @PostMapping("addorder")
 public String addorder(order order)
 {
     order.setStatus("发货中");
     order.setOrderTime(new Date());
     order.setShipTime(new Date());
     orderService.addorder(order);
     return "添加成功";
 }

上面代码中:

  • @Autowired注解用来注入对象,下面的 orderService orderService就是被注入的对象,注入之后不需要手动创建对象可以直接使用(Spring帮你管理)
  • @PostMapping("addorder") 意为声明一个post请求方式的接口,接口地址为addorder。
  • public String addorder(order order)函数名随意,函数的参数可以是对应成表单的各个字段然后创建一个order对象,但这里直接创建一个order对象而前端表单传递对应名称值将直接赋值(省的再次赋值)。
  • 这里为了简单实现,下单日期和发货日期都为系统当前时间,且订单状态初始默认为发货中。

2.2 前端部分

有了后端部分的支持,前端我们在addorder.html中编写以下内容,主要是一个表单向服务端发送数据和请求:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="layui/css/layui.css">
</head>
<body>
<section class="layui-larry-box">
    <div class="larry-personal">
        <blockquote class="layui-elem-quote layui-text">
            <span>增加订单</span>
        </blockquote>
        <form class="layui-form col-lg-5 " action="addorder" method="post">

            <div class="layui-form-item">
                <label class="layui-form-label">订单id</label>
                <div class="layui-input-block">
                    <input type="text" name="id" autocomplete="off" class="layui-input" value="" >
                </div>
            </div>
            <div class="layui-form-item">
                <label class="layui-form-label">发货人姓名</label>
                <div class="layui-input-block">
                    <input type="text" name="shipper"  autocomplete="off" class="layui-input"  value="">
                </div>
            </div>
            <div class="layui-form-item">
                <label class="layui-form-label">发货人地址</label>
                <div class="layui-input-block">
                    <input type="text" name="shippingAdress"  autocomplete="off" class="layui-input" value="">
                </div>
            </div>
            <div class="layui-form-item">
                <label class="layui-form-label">发货人电话</label>
                <div class="layui-input-block">
                    <input type="text" name="shipperPhone"  autocomplete="off" class="layui-input" value="">
                </div>
            </div>
            <div class="layui-form-item">
                <label class="layui-form-label">收件人姓名</label>
                <div class="layui-input-block">
                    <input type="text" name="recevier"  autocomplete="off" class="layui-input" value="">
                </div>
            </div>
            <div class="layui-form-item">
                <label class="layui-form-label">收件人地址</label>
                <div class="layui-input-block">
                    <input type="text" name="recevierAddress"  autocomplete="off" class="layui-input" value="">
                </div>
            </div>
            <div class="layui-form-item">
                <label class="layui-form-label">收件人手机</label>
                <div class="layui-input-block">
                    <input type="text" name="receviePhone"  autocomplete="off" class="layui-input" value="">
                </div>
            </div>
            <div class="layui-form-item">
                <div class="layui-input-block">
                    <button  class="layui-btn" lay-submit lay-filter="formDemo">添加</button>
                    <button type="reset" class="layui-btn layui-btn-primary">重置</button>
                </div>
            </div>
        </form>
    </div>
</section>
</body>
<script type="text/javascript" src="layui/layui.js"></script>

写完后启动程序访问localhost:8080点击订单添加,然后在表单中填写对应内容


当然为了测试你可以再写一单,添加之后你会发现MongoDB中成功添加了订单数据,这样下单这一步就大功告成啦!

好了,因篇幅文字限制本篇先讲到这里,下篇将继续讲解更新、删除等操作的前后端页面。敬请期待,原创不易,欢迎点赞、关注、转发一键三联,您的支持是我努力的不断动力。

首发公众号:bigsai 头条号:码农bigsai

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码