《面向服务的软件系统》大作业

哈尔滨工业大学国家示范性软件学院

《面向服务的软件系统》大作业

项目题目: 基于微服务的网络购物云平台

项目组成员:

姓名: 石卓凡 学号: 120L021011

姓名: 苏泽楷 学号: 120L020926

姓名: 艾永亮 学号: 120L020205

完成日期: 2022年 12 月 19 日

目录

1.选题 1

1.1项目介绍 1

1.2整体项目两大板块 3

2.实现方案 5

2.1 使用的技术知识 5

2.2 团队协作方法 5

2.3 设计管理员端 5

2.3.1 数据库设计 6

2.3.2 后端设计 8

2.3.3 前端设计 12

2.4 设计客户手机端 16

2.5 项目部署 19

3.实现结果 21

3.1 软件开发 21

3.1.1 管理员端 21

3.1.2 客户手机端 23

3.2 架构部署 25

4.总结 28

(1).石卓凡 28

(2).苏泽楷 28

(3).艾永亮 30

5.对课程的建议 32

1. 选题

选择题目2:基于微服务框架开发项目

●基于Springboot搭建项目框架

●项目采用微服务架构,可基于Dubbo或Spring Cloud等 框架,起评分标准90分

●如采用Shiro框架实现认证与授权,或Jenkins实现 CI/CD等扩展能力,起评分标准100分

●运用Maven、Git等主流开发工具

●业务不限,软件功能相对完整,界面美观友好

●包含至少5个操作界面,代码量1500行+

大作业题目:基于微服务的网络购物云平台

概述:

1.1项目介绍:

当今,网络经济模式越来越流行,网上购物方式日益为大家所接受。互联网的飞速发展,已经颠覆了传统的信息采集、传递和外观,对劳动者的劳动技能和工作效率的提高,提供了前所未有的有利条件和推进作用。个人经营,企业等的经济收入增长大多得益于互联网的推广和应用。

网络购物云平台是电子商务的前端商务平台,它在整个商务活动过程中扮演着非常重要的角色。网上购物系统也是一种商业信息系统,它具有强大的交互功能,能向用户提供各种信息资源,能使商家和用户之间能方便地进行信息传递,新型的线上线下整合营销模式可以方便快捷地完成电子贸易。

而一个购物平台的用户分为两类,一类是管理员,负责维护这个购物平台上架的商品,管理本平台销售商品的品牌分类。另一类是普通的手机客户,将会通过购物平台浏览商品最终旋入购物车并下单。

因此,针对两类用户,我们的大作业项目就需要设计成为俩个小项目,管理端客户端

与此同时,一般实际中购物平台的访问量很大,为了模拟真实情况,采用多台服务器去部署,并且使用限流策略等。因此管理端和客户端部署在两个不同集群。

图1.1 项目部署图

图1.2 项目设计图

图1.3 项目数据流图(DFD)

1.2整体项目两大板块:

(a).管理端:

该管理系统可以登录管理员账号,登录员工账号,管理员可以实现对某个电商交易平台的员工,商品,品牌分类等进行管理与查询。后台管理系统中的信息以便于客户手机端可以对电商商品进行下单。

(b).客户端:

客户可以进行登录,采用手机短信验证码登录,然后对商品进行选购下单,通过位置定位确定收货地点来下单。

图1.4 项目功能结构图

  1. 实现方案

2.1 使用的技术知识

分工层面 应用到的技术
前端 H5,Vue,Element-Plus,axios,vite
后端 springcloud,mybatis-plus,nacos,sentinel,gateway,Feign
运维 Docker,k8s,jenkins,nginx
数据 Mysql

表2.1 项目涉及技术/知识

2.2 团队协作方法

后端对接我们采取的是利用apiFox,便于更好理解互相之间的工作接口,apifox这种工具可以帮助我们小组前后端分离:

对于前端来说

1.更好的了解后端接口情况;

2.如果还没有后端接口,可以模拟后端接口,如果需要,前端向后端申请希望新增这样接口。

对于后端来说

1.后端可以通过导出Api然后将接口导入到apifox,以此来向其他成员说明接口情况;

2.可以详细了解前端需要哪些额外接口。

2.3 设计管理员端

图2.1 项目顶层数据流图(DFD)

2.3.1 数据库设计

需求:

  • 为前后端提供数据库支持
  • 数据库表的命名简单明了,且要求每条数据都有详细注释,方便其他成员阅读
  • 允许项目所有成员可以通过远程访问,而不是部署在某个同学的本机上,方便前后端成员随时根据需要去访问数据

设计方案:

  • 在服务器k8s集群上部署mysql作为云数据库,可以通过navicat进行远程连接和可视化操作
  • 数据库中含employee员工表,brand品牌表,good商品表;
  • 实现数据库里面商品携带商品图片,可以将商品图片转化为url链接存入然后mysql类型定义为varchar并且长度为2083
  • 想要解决good的名称唯一可以直接利用mysql的唯一索引,这样就限制了存入数据库的name是唯一的

图2.2 项目数据库表设计

图2.3 项目数据库表设计(2)

注释
Brand id 主键
name 品牌名
number 该品牌旗下所含的商品总数
Create_time 创建时间
update_time 更新时间
create_user 创建人
update_user 修改人
Good id 主键
name 商品名
price 该商品的售价
Brand 该商品所属的品牌
Create_time 创建时间
update_time 更新时间
create_user 创建人
update_user 修改人
Img 商品图片URL
Employee id 主键
name 员工姓名
status 状态 0:禁用,1:正常
username 用户名
password 密码
phone 手机号
sex 性别
Id_number 身份证号
Create_time 创建时间
update_time 更新时间
create_user 创建人
update_user 修改人

表2.2 数据库各表及其表项含义

图2.4 数据库ERD图

后端设计

需求:

●使用springcloud微服务框架,将客户端单独部署到新的服务器集群

●实现管理端所有功能且给出所用到的所有接口:员工,商品,品牌接口

设计方案:

(Ⅰ).采用到的springcloud组件:

(1).Nacos注册服务中心

将项目拆分成多个微服务,如员工管理服务、商品管理服务、品牌管理服务。微服务数据独立,微服务将自己的业务暴露为接口,供其它微服务调用。各个微服务之间的相互发现和互动都会通过nacos。

其中每个服务部署两个实例。

图2.5 项目部署的nacos图

(2).feign远程调用

利用feign实现在各微服务之间发起远程调用;

图2.6 项目使用到的feign接口

(3).gateWay网关

网关作为整体微服务项目入口,需要校验用户是是否有请求资格,如果没有则进行拦截,且实现跨域问题;

设定gateWay端口为10010,强制客户只能通过10010端口访问,确保安全性。

(4).Sentinel实现流量控制

微服务中,服务间调用关系错综复杂,一个微服务往往依赖于多个其它微服务;利用sentinel进行流量控制实时监控流量防止雪崩问题的出现。

图2.7 项目部署的sentinel图

(Ⅱ)Springcloud分为以下几个模块:

图2.8 Maven项目结构图

(1). Mail-employee模块:

●静态映射backend前端资源并部署上服务器(WebMvcConfig)

●设置全局异常处理器,负责全局处理异常方法(GlobalExceptionHandler)

●根据需求,自己应用新的json对象转换器,扩展mvc框架的消息转换器(JacksonObjectMapper)

●配置MP的分页插件(MybatisPlusConfig)

●员工登录接口

●员工退出

●新增员工

●员工信息分页查询

●根据id修改员工信息

●根据id查询员工信息

(2).Mail-brand模块:

●新增品牌

●品牌信息分页查询

●根据id修改品牌信息

●根据id查询品牌信息

●根据品牌名让修改品牌总数

●返回指定品牌的总数

(3).Mail-good模块:

●新增商品

●商品信息分页查询

●根据id修改商品信息

●根据id查询商品信息

●用于手机端打开展示goodslist

(4).Mail-loginMessage模块:

●随机生成验证码

●调用api向指定手机号发送验证码

(5).gateWay模块:

网关作为整体微服务项目入口,需要校验用户是是否有请求资格,如果没有则进行拦截,且实现跨域问题;

设定gateWay端口为10010,强制客户只能通过10010端口访问,确保安全性

(6).短信服务api:

选用的是aliyun短信服务,需要小心公开仓库暴露专属个人的key,因为在Code中会使用到aliyun给出的key,如果不加密直接放在github的公开仓库中,就有key暴露的安全风险。

图2.9 aliyun短信服务

(Ⅲ)Axios跨域问题:

利用的是SpringCloud的GateWay解决,原生的网关帮助解决了cors跨域请求,解决了axios不能直接跨域的问题,很方便快捷

Axios的解决经过:

1. 首先小组尝试在前端设计时候通过利用一个代理服务器解决cors跨域,但是部署和配置过程繁琐最终尝试一下午后放弃。

2. 临时使用apifox模拟后端接口Mock发回数据以此保证前端项目继续工作,暂时跳过跨域问题阻碍。

3. 后端在后期成功通过gateWay利用网关解决了前端axios跨域问题。

2.3.3 前端设计

前端设计分为四个部分,以及对应的js组成:

图2.10 前端页面

login:登录页面

member:员工管理页面

good:货品管理页面

brand:品牌管理页面

其中member、good、brand较为类似,仅以member为例讲解

(1).Login

el-form组件实现表单的设计,使表单的样式整齐划一;

用el-form标签将表单控件包裹起来,每个控件使用el-form-item标签包裹起来,这样产生的表单就会比较整齐;

el-input组件实现文本框的输入,el-button实现提交按钮。

图2.11 管理员端登录界面

Login-javascript:

初始验证数据:

前端对输入信息的初次验证:

调用loginApi完成对账号密码的验证:

失败则弹出错误信息并放回false:

(2).Member

Member可以分为add和list页面,大体技术相似,以list为例:

el-input实现输入查找框(初始显示浅色文本“请输入员工姓名”):

图2.12 查找框

当点击回车后,响应事件handleQuery:

图2.13 list实现

el-table实现数据的展示和分页,el-table-column完成每一列信息的具体要求

图2.14 数据展示与分页

el-button实现添加员工的跳转和编辑禁用设置,点击后分别响应事件“addMemberHandle”、“statusHandle”

图2.15 员工编辑与禁用

Member-javascipt:

先获取当前登录员工的账号,并赋值给模型数据user:

响应添加或者修改员工信息时分别携带不同信息进行跳转add页面:

禁用完成状态的修改:

分页出错问题

这里由于我们在修改前端每页容纳的数据条数Size时,会同时触发handleSizeChange和handleCurrentChange事件;

由于同时的响应,可能会导致Currentpage的页码大于总页码的情况;

因此,我们采用延时技术,将handleSizeChange延时处理,先后完成就不会出现溢出查找的情况。

2.4 设计客户手机端

图2.16 客户手机端顶层DFD图

需求:

●要求客户能从手机端访问项目,并且要能够适应手机端的窗口大小和操作

●要求可以手机短信登录,要求可以定位

设计:

采用主流的前后端分离,并且设计方案是单页面vue,设计思路也简洁明了,获取mail_good接口数据,再通过vue组件呈现

页面说明:

页面 说明
Login 客户手机端的登录页面
Home 浏览商品加入购物车页面
Location 定位收货地址并下单页面

(1).Login介绍:

通过客户输入的手机号作为参数,向后端发送axios请求调用短信登录接口,实现登录

通过验证随机生成的四位验证码对比输入的验证码来确定登录

(2).Home介绍:

图2.17 Home页面内组件设计图

组件说明:

组件 说明
Counter 实时统计购物车合计价格
Footer 浏览商品的底部购物车选框
Goods 商品信息组件
Header 浏览商品的头部信息选框

(3).Location介绍:

使用的是vue-baidu-map。用于下单时候的定位收货地址。

在百度地图的api官网中只有js版本,于是vue使用的版本需要自行去npm搜索。

图2.18 vue-baidu-map

(4).使用拖拽式生成页面:

本模块使用的是https://vcc3.sahadev.tech/

对于新手入门速成vue和html,我们选择使用简单设计网页模板可以使用拖拽式组件生成,这样就可以利用拖拽使用ElementPlus等组件

图2.19 网页设计模板

(5).引入依赖方式:

(a).项目最初采用的是直接全局引入依赖,随着开发到后期,在vue引入的依赖越来越多,每次构建新组件都需要重复大量引入,特别麻烦。

(b).改为动态按需引入依赖,所需要的改动远比全局引入依赖小。

图2.20 动态引入依赖后的vite.config.js

2.5 项目部署

管理员端项目部署需要一台Jenkins服务器,服务器在安装配置Jenkins之前还需要安装git客户端、上传jdk、安装maven、安装docker及设置相应环境变量,之后下载 jenkins 的安装包,启动Jenkins。

之后便使用Jenkins构建部署任务对项目实现自动化部署:

1.安装 Jenkins 和相关插件:首先需要安装 Jenkins 服务器,并安装需要使用的插件。

2.创建 Jenkins 任务:在 Jenkins 中创建一个新的任务,并配置源代码管理、构建触发器、构建环境和构建步骤等相关信息。

图2.21 Jenkins构建任务配置

3.设置权限:确保只有授权的用户才能访问 Jenkins 任务并操作。

4.配置构建步骤:根据项目的实际情况,设置合适的构建步骤,包括编译代码、执行单元测试、打包、部署等。

5.监控构建状态:通过 Jenkins 的构建历史和日志功能,监控构建的状态和输出信息,以便及时发现并解决问题。

客户端项目同样部署在Jenkins服务器中,需要安装并启动nginx、修改其nginx.conf文件的项目dist地址以发布项目及修改操作用户(root):

图2.22 nginx修改配置

3. 实现结果

3.1 软件开发

管理端入口(已停止服务器):http://120.79.55.22:10010/backend/index.html

客户手机端入口(已停止服务器):http:/47.92.244.182/#/login

管理员端

(1).账号登录

管理员/员工可以通过账号密码进行登录:

图3.1 管理员端登录页面

(2).进入管理页(成功登录)

管理员能在此界面管理员工,商品,品牌。并且能对员工权限进行禁用;

员工仅可以在这个界面管理商品,品牌;

右侧整个数据的展示并且采用了分页设计,设定每2条数据为1页。

图3.2 管理员端管理主页

(3).对数据进行新增(以新增员工为例)

可以新增一个员工。在输入新员工的信息时会自动检测账号是否已经被使用,自动检测手机号是否符合格式,自动检测身份证号是否符合,如果出现不符合情况都会给出对应提示

图3.3 新增员工功能

图3.4 自动检验手机号格式

(4).对已有数据进行修改(以修改某员工为例)

图3.5 修改员工信息

客户手机端

(1).手机登录

  1. 提示条提示:请输入手机号
  2. 客户输入手机号
  3. 提示条提示:请点击获取验证码
  4. 项目在后端随机生成4位验证码,将验证码以短信形式发送给客户输入的手机号,同时验证码code返回给前端
  5. 提示条提示:请输入验证码并登录
  6. 前端验证客户输入验证码是否和此前生成验证码一样,登录成功/失败

图3.6 手机登录界面及验证码

(2).浏览商品和加入购物车

1.页面会逐条展示购物平台中的待售商品以及价格

2.客户可以选中某个商品,并且选择购买此商品的数量,加入购物车

图3.7 商品页面及实时显示价格

(3).定位确定收货地址并下单

(1).用户能点击自动定位由地图api自动获取当前位置设置下单地址

(2).用户确定地址之后点击下单,完成下单

图3.8 定位位置并成功下单

3.2架构部署

3.2.1 jenkins自动部署

首先,Jenkins与gitlab关联webhook设置测试成功,当有代码被推送到gitlab仓库时,Jenkins会自动拉取gitlab代码进行自动化部署。

图3.9 Jenkins与gitlab关联

Jenkins自动化部署项目控制台输出:

图3.10 Jenkins自动化部署项目成功

在服务器上可以查看相应项目镜像及docker容器创建并成功运行,项目成功运行之后的操作界面即为上述软件开发中管理员端展示的界面

图3.11 Jenkins服务器容器镜像列表

3.2.2 nginx 部署客户手机端项目

修改nginx.conf文件,location中配置dist的实际路径

图3.12 修改的nginx.conf文件

可以看到nginx服务已经成功启动,且之后的项目的操作界面即为上述的客户手机端展示的操作界面。

图3.13 nginx正常启动部署客户端项目

4.总结

(1).石卓凡:

网络上的经验帖子具有时效性和针对性,对于不同版本,或者几年前的帖子,同一个问题的解决办法很有可能不适用。

比如请求goods数据中vue3的axios跨域问题

(ⅰ)网络博客关于vue2的解决方案不适合

因为vite.config.js在vue3中存在于根目录,而在vue2中存在于config文件夹并且import Vue from ‘vue’这条语句在Vue3基本上弃用,但是在Vue2还在使用,而网络上给出的方案用的都是import Vue from ‘vue’导致报错冲突

(ⅱ)网络博客针对vue-cli脚手架或者含webpack或者vite2.x的解决方案不适合,因为本项目后面改用的是vite3.x脚手架,项目结构基本不一致,这会导致同一位置的配置文件在vite下不会生效。由于最初使用的vite2.x的脚手架无法识别vite.config.js配置文件,还将这个模块重新移植到vite3.x

目前有许多现成的可视化操作软件可以方便我们的设计。比如k8s的kubesphere,docker的dockerDesktop,github的githubDesktop都可以方便我们的操作。

使用springcloud的一些心得:

分布式系统的复杂性:在使用Spring Cloud时,需要注意分布式系统带来的复杂性,这些复杂性包括网络分区、服务故障和超时等。需要确保系统能够应对这些挑战;

服务注册与发现:Spring Cloud使用nacos来实现服务注册和发现。在使用nacos时,需要注意服务的状态和健康检查;

负载均衡:Spring Cloud使用Ribbon来实现负载均衡。在使用Ribbon时,需要注意负载均衡策略和超时设置。

(2).苏泽楷:

①在使用Jenkins进行项目自动化部署时,需要注意以下几点:

1.安装 Jenkins 和相关插件:首先需要安装 Jenkins 服务器,并安装需要使用的插件。

Jenkins安装插件需要替换源地址,其官网的下载地址国内应该是下载不了的,网络中大多数教程中都是在jenkins插件配置里使用https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json替换为了清华源地址。但是,这样插件下载路径其实是没变的,变的只是这个json是从清华源下来的,其内的插件下载地址是没有变的,还是从官网下载。因此,正确的修改源应该是进入Jenkins工作目录,将default.json里所有的updates.jenkins-ci.org替换为mirrors.tuna.tsinghua.edu.cn、www.google.com替换为www.baidu.com:

2.创建 Jenkins 任务:在 Jenkins 中创建一个新的任务,并配置源代码管理、构建触发器、构建环境和构建步骤等相关信息。

3.设置权限:确保只有授权的用户才能访问 Jenkins 任务并执行操作。

4.配置构建步骤:根据项目的实际情况,设置合适的构建步骤,包括编译代码、执行单元测试、打包、部署等。

5.监控构建状态:通过 Jenkins 的构建历史和日志功能,监控构建的状态和输出信息,以便及时发现并解决问题。

②Jenkins使用心得:

1.Jenkins 提供了丰富的插件,可以帮助用户更方便地实现持续集成和自动化部署。

2.在使用 Jenkins 进行自动化部署时,要注意保证构建环境的稳定性,并对构建过程中出现的问题进行及时处理。建议定期备份 Jenkins 的配置和构建历史。

3.可以使用 Jenkins 的 Pipeline 功能来实现更加复杂的构建流程,并支持代码化的方式编写构建脚本。

4.可以使用 Jenkins 的插件来实现对构建结果的可视化,方便我们更直观地了解构建的状态。

5.建议使用 Jenkins 的安全功能来保护构建环境,比如使用安全登录、访问控制、数据加密等手段。

总之,使用 Jenkins 可以帮助用户更有效地实现持续集成和自动化部署,提高项目的开发效率和质量。

③使用 nginx 部署前端项目时,需要注意以下几点:

1. 安装 nginx 服务器:首先需要在服务器上安装 nginx ,并配置服务器的监听端口和访问权限等信息。

2.配置 nginx 虚拟主机:在 nginx 中创建一个虚拟主机,并配置虚拟主机的域名、服务器根目录和访问权限等信息。

3.发布前端项目文件:将前端项目打包后上传到虚拟主机的服务器根目录中,以便访问。

4.配置前端路由:在前端项目中配置路由规则,以便在不同的路径下显示不同的内容。

一些使用心得:

1. 使用 nginx 可以更方便地将前端项目部署到服务器上,方便访问。

2. 使用 nginx 部署前端项目时,要注配置虚拟主机的域名和服务器根目录,确保能够正确访问前端项目文件。

3. 可以使用 nginx 的反向代理功能来解决跨域问题,并使用加密协议来保护前端项目的安全性。

(3).艾永亮:

①el-table实现页面size更改时要注意:

1.el-pagination的@size-change事件和@current-change冲突,导致切换每页显示条数时,偶尔会出现无数据的情况

2.这里由于我们在修改前端每页容纳的数据条数Size时,会同时触发handleSizeChange和handleCurrentChange事件。

3.由于同时的响应,可能会导致Currentpage的页码大于总页码。

4.因此我们采用延时技术,将handleSizeChange延时处理,先后完成就不会出现溢出查找的情况。

②el-table实现分页时要注意:

1.分页的核心是tableData.slice这一句代码,利用了slice方法把数据源tableData进行分割,但实际上是请求了所有的数据,然后实现前端假分页显示。
2.还有一种分页的思想就是给后台传入如上的参数currentPage和pag

esize的值,告诉后台,我们需要[(currentPage-1)*pagesize,currentPag

e*pagesize]这一个区间的数据,让后台返回来。

③这两种方法各有利弊:

如果是前者前端控制分页的方法,因为本质是请求了所有的数据,如果这个数据量非常大,涉及到了几百,几千甚至几万数据,第一页的table数据加载的时间就会非常慢,因为它把后面的数据都拿过来了,用户体验非常不好,对内存空间也很不友好。明明只显示了几十条的数据,却为此存了几万条的数据,明显后者的效率会好些。但是它也是有好处的,好处就是如果在数据量小的情况下,第一页table加载速度用户也能接受的情况下,用户之后点击切换页面按钮或者直接跳转到哪个页面都不需要发起请求即可显示出数据,速度非常快。

5.对课程的建议

1.关于前置知识

希望多加入一些前置知识,比如springboot之类的,上这门课拥有一些前置知识之后上课会发现收获的更多;又或者一些前端的前置知识,比如javascript或者一些前端常见的技术问题,这样在学习前端或者大作业实践的时候会更加方便。

2.关于实验部分

实验内容和实验指导书可以更新一下,目前的指导书还存在着版本过时问题导致配置出错的问题,并且实验内容有的可以改为让同学自己搭建一个简单的springboot项目;并且实验指导书上,相关步骤说明较少,实际操作与理解都较为困难。

3.关于Jenkins和k8s实战

希望以后的课可以多加入一些教怎么样去实际操作jenkins和k8s的课上内容。个人认为很有性价比,在没有老师指导自己去摸索的情况下所要花费的代价太大且有不少的坑。

4.关于前后端交互

希望能多讲一些前后端交互的知识和案例,现如今开发大多为前后端分离团队协作,前后端交互和团队的沟通协作就显得更为重要。


《面向服务的软件系统》大作业
http://yoursite.com/2023/04/21/《面向服务的软件系统》大作业/
作者
Fars
发布于
2023年4月21日
许可协议