Unverified Commit 324c8da3 authored by linlinjava's avatar linlinjava Committed by GitHub
Browse files

Merge branch 'master' into dev

parents 693cf5cd 4c46da9b
doc/pic1/1-1.png

72.2 KB | W: | H:

doc/pic1/1-1.png

81 KB | W: | H:

doc/pic1/1-1.png
doc/pic1/1-1.png
doc/pic1/1-1.png
doc/pic1/1-1.png
  • 2-up
  • Swipe
  • Onion skin
doc/pic1/1-11.png

122 KB | W: | H:

doc/pic1/1-11.png

111 KB | W: | H:

doc/pic1/1-11.png
doc/pic1/1-11.png
doc/pic1/1-11.png
doc/pic1/1-11.png
  • 2-up
  • Swipe
  • Onion skin
doc/pic1/1-12.png

142 KB | W: | H:

doc/pic1/1-12.png

131 KB | W: | H:

doc/pic1/1-12.png
doc/pic1/1-12.png
doc/pic1/1-12.png
doc/pic1/1-12.png
  • 2-up
  • Swipe
  • Onion skin
doc/pic1/1-2.png

115 KB | W: | H:

doc/pic1/1-2.png

107 KB | W: | H:

doc/pic1/1-2.png
doc/pic1/1-2.png
doc/pic1/1-2.png
doc/pic1/1-2.png
  • 2-up
  • Swipe
  • Onion skin
doc/pic1/1-3.png

114 KB | W: | H:

doc/pic1/1-3.png

106 KB | W: | H:

doc/pic1/1-3.png
doc/pic1/1-3.png
doc/pic1/1-3.png
doc/pic1/1-3.png
  • 2-up
  • Swipe
  • Onion skin
......@@ -270,7 +270,7 @@ litemall_region表保存了行政区域信息,包括省级、市级、县级
如果用户没有支付,也没有点击`取消订单`按钮,那么系统会定时查询数据库的订单信息。
如果发现存在订单未支付状态超时半小时,此时系统会自动取消订单,来释放商品资源。
对应的后台服务方法是litemall-admin-api模块的`AdminOrderController.checkOrderUnpaid`
对应的应该是litemall-admin-api模块的系统定时任务的`OrderJob.checkOrderUnpaid`
* 101 -> 201
......@@ -314,7 +314,7 @@ litemall_region表保存了行政区域信息,包括省级、市级、县级
当管理员发货以后,用户一直没有确认收货,系统定时检测订单状态,如果发现发货以后
七天用户都没有收货,此时系统自动确认用户收货,设置订单状态402。
所对应的后台服务方法是litemall-admin-api模块的`AdminOrderController.checkOrderUnpaid`
应该改为 litemall-admin-api模块的系统定时任务`OrderJob.checkOrderUnconfirm`
注意:
> 上述订单状态变化中具体的逻辑处理可以参考相应模块文档和模块代码。
......@@ -1153,7 +1153,7 @@ public interface Storage {
## 2.4 litemall-all
在章节1.5中讨论的部署方案中设计了一种单主机单服务方案,
在章节1.5中讨论的部署方案中设计了一种单服务器单服务方案,
也就是说两个后台服务和静态文件都部署在一个Spring Boot可执行jar包中。
查看litemall-all模块,代码仅仅只有一个Application类。
......
......@@ -22,10 +22,6 @@ litemall是一个简单的商场系统,基于现有的开源项目,重新实
由litemall-wx-api模块和litemall-vue模块组成。
注意,目前这里移动商城子系统的后端和小商场子系统是一样的。
* 简商城子系统(webmall)
这里仅列出,目前没有开发计划。
* 管理后台子系统(admin)
由litemall-admin-api模块和litemall-admin模块组成。
......@@ -45,6 +41,27 @@ litemall是一个简单的商场系统,基于现有的开源项目,重新实
采用VSC开发工具,开发litemall-admin模块和litemall-vue模块。
### 1.1.1 项目特点
项目存在以下特点:
* 数据库方面,只是简单的表,表和表之间的依赖关系没有采用外键设计,而是依赖Java代码在service层面或者业务层面保证。这样做的好处是数据库频繁改动很方便,不会因为外键而导致数据库难以修改;
* 涉及三种技术栈,但是每种技术栈仅涉及最基础的技术;
* 后端技术栈,仅涉及 Spring,Spring Boot, Spring MVC和Mybatis技术,其他后端技术暂时不采用;
* 小程序技术栈,仅涉及miniprogram官方文档;
* 前端技术栈,仅涉及vue, vuex, vue-route和element技术;
* 安全方面,仅采用最基本的代码,提供简单基本的安全服务;
* 性能方面,没有涉及内存数据库缓存功能,而是完全依赖MySQL;
* 对象存储服务方面,支持本地存储和第三方云存储方案。
* 消息通知方面,支持邮件通知、第三方云短信通知和微信模板通知;
* 部署方便,支持多服务部署和一键部署脚本;
* 文档全面,虽然还在开发中,但是规划中文档和代码注释一定会完成,帮助开发者理解项目。
总之,目前的系统只是为了学习技术和业务而开发的一个简单商场原型系统。虽然缺失很多企业级功能,但是是完整和合理的原型系统。
注意:
> 以上特点并不一定是优点。
## 1.2 系统功能
从业务功能上,目前由六个业务模块组成:
......@@ -139,26 +156,79 @@ litemall是一个简单的商场系统,基于现有的开源项目,重新实
* 订单统计
* 商品统计
## 1.3 项目特点
## 1.3 项目技术
存在以下特点:
### 1.3.1 技术参考
* 数据库方面,只是简单的表,表和表之间的依赖关系没有采用外键设计,而是依赖Java代码在service层面或者业务层面保证。这样做的好处是数据库频繁改动很方便,不会因为外键而导致数据库难以修改;
* 涉及三种技术栈,但是每种技术栈仅涉及最基础的技术;
* 后端技术栈,仅涉及 Spring,Spring Boot, Spring MVC和Mybatis技术,其他后端技术暂时不采用;
* 小程序技术栈,仅涉及miniprogram官方文档;
* 前端技术栈,仅涉及vue, vuex, vue-route和element技术;
* 安全方面,仅采用最基本的代码,提供简单基本的安全服务;
* 性能方面,没有涉及内存数据库缓存功能,而是完全依赖MySQL;
* 对象存储服务方面,支持本地存储和第三方云存储方案。
* 消息通知方面,支持邮件通知、第三方云短信通知和微信模板通知;
* 部署方便,支持多服务部署和一键部署脚本;
* 文档全面,虽然还在开发中,但是规划中文档和代码注释一定会完成,帮助开发者理解项目。
#### 1.3.1.1 Spring Boot技术
总之,目前的系统只是为了学习技术和业务而开发的一个简单商场原型系统。虽然缺失很多企业级功能,但是是完整和合理的原型系统。
Spring Boot技术栈参考以下文档或者项目:
注意:
> 以上特点并不一定是优点。
1. MySQL
了解创建数据库和表、添加、查询、更新和删除即可。
2. Spring Boot 2.x
* https://docs.spring.io/spring-boot/docs/2.1.5.RELEASE/reference/htmlsingle/#getting-started-introducing-spring-boot
* https://docs.spring.io/spring-boot/docs/2.1.5.RELEASE/reference/htmlsingle/#using-boot-maven
这里需要了解RestController, Service等注解,以及如何使用自动化配置。
Spring Boot支持很多功能,开发者使用时查阅。
3. Mybatis
* http://www.mybatis.org/mybatis-3/
* http://www.mybatis.org/mybatis-3/java-api.html
* http://www.mybatis.org/mybatis-3/sqlmap-xml.html
这里可以简单了解,而使用Mybatis Generator来生成Java代码使用即可。
4. Mybatis Generator
* http://www.mybatis.org/generator/running/runningWithMaven.html
* http://www.mybatis.org/generator/generatedobjects/results.html
* http://www.mybatis.org/generator/generatedobjects/exampleClassUsage.html
5. Mybatis PageHelper
* https://github.com/pagehelper/Mybatis-PageHelper/blob/master/wikis/en/HowToUse.md
#### 1.3.1.2 小程序技术
1. 小程序
* https://developers.weixin.qq.com/miniprogram/dev/index.html
* https://developers.weixin.qq.com/miniprogram/dev/component/
* https://developers.weixin.qq.com/miniprogram/dev/api/
* https://developers.weixin.qq.com/community/develop
建议小程序方面遇到问题,可以到官方社区查找。
2. 微信支付
* https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_3&index=1
#### 1.3.1.3 Vue技术
1. Vue
* https://cn.vuejs.org/index.html
2. Vant
* https://youzan.github.io/vant/#/zh-CN/intro
3. Element
* https://element.eleme.cn/#/zh-CN/component/installation
4. vue-element-admin
* https://github.com/PanJiaChen/vue-element-admin
* https://panjiachen.github.io/vue-element-admin-site/zh/
### 1.3.2 项目阶段
接下来,从项目的开发、部署(测试)和上线三个阶段介绍litemall。
......@@ -173,7 +243,7 @@ litemall是一个简单的商场系统,基于现有的开源项目,重新实
* dep
即deploy或者deployment,这里指部署(测试阶段),通常代码已经编译打包运行在远程主机中,
即deploy或者deployment,这里指部署(测试阶段),通常代码已经编译打包运行在远程服务器中,
可以对外服务。此外,这里服务访问地址通常是IP地址。如果IP是公网IP,那么
部署以后就可以对外服务;如果是内网地址,那么只能内网访问。这里的“用户”主要是
指开发者本身、测试者;当然,如果是局域网或者不介意IP访问的,那么这里的“用户”
......@@ -181,7 +251,7 @@ litemall是一个简单的商场系统,基于现有的开源项目,重新实
* prod
即product或者production,这里指上线阶段,通常也是代码编译打包运行在远处主机中可以对外服务。
即product或者production,这里指上线阶段,通常也是代码编译打包运行在远处服务器中可以对外服务。
此外,这里服务访问地址通常是域名地址,同时端口是80web端口。上线以后直接面向的是最终用户。
虽然服务的代码本身和dep是完全一样的,但是考虑到场景的不同,上线阶段可能在运行环境方面需要做
调整,例如采用反向代理屏蔽内部实际项目结构。此外,最大的不同应该是上线环境下要使用域名和80端口,
......@@ -303,8 +373,8 @@ flush privilege
> 但是建议开发者开发阶段采用IDEA。
> 2. 上述步骤只是一种实践方式,开发者可不拘泥于这些步骤,多实践。
> 当然,如果开发者不采用这里步骤而出现问题,请自行解决。
> 3. 开发者使用IDEA导入项目或者运行项目时可能会出现**软件卡顿**的现象,这通常是litemall-admin的
> node_modules文件夹内自动下载了大量的litemall-admin的依赖库,当IDEA尝试索引该文件夹内的大量文件时
> 3. 开发者使用IDEA导入项目或者运行项目时可能会出现**软件卡顿**的现象,这通常是litemall-admin或者litemall-vue
> node_modules文件夹内自动下载了大量的依赖库,当IDEA尝试索引该文件夹内的大量文件时
> 则出现IDEA卡顿的现象,具体解决方式可以参见[FAQ](./FAQ.md)
### 1.4.3 微信小程序开发环境
......@@ -348,12 +418,12 @@ flush privilege
**项目配置结构**
1. 管理后台前端,即litemall-admin模块,配置文件在litemall-admin/config中,存在三个配置文件`dev.env.js`,`dep.env.js`
`dep.env.js`。这里面配置信息都是一样,最主要的配置是`BASE_API`,即管理后台的服务根地址。
1. 管理后台前端,即litemall-admin模块,配置文件在litemall-admin中,存在三个配置文件`env.development`,`env.deployment`
`.env.production`。这里面配置信息都是一样,最主要的配置是`VUE_APP_BASE_API`,即管理后台的服务根地址。
* 开发阶段,开发者运行命令`cnpm run dev`,这里就会采用`dev.env.js`配置文件;
* 部署阶段,当开发者运行命令`cnpm run build:dep`,这里就会采用`dep.env.js`配置文件;
* 上线阶段,当开发者运行命令`cnpm run build:prod`,这里就会采用`prod.env.js`配置文件。
* 开发阶段,开发者运行命令`cnpm run dev`,这里就会采用`env.development`配置文件;
* 部署阶段,当开发者运行命令`cnpm run build:dep`,这里就会采用`env.deployment`配置文件;
* 上线阶段,当开发者运行命令`cnpm run build:prod`,这里就会采用`.env.production`配置文件。
2. 小商场前端,即litemall-wx模块,配置文件是`litemall-wx/project.config.json``litemall-wx/api.js`
这里面最主要的配置信息是`project.config.json`中的`appid`,开发者需要设置自己申请的appid;
......@@ -365,7 +435,7 @@ flush privilege
// 局域网测试使用
// var WxApiRoot = 'http://192.168.0.101:8080/wx/';
// 云平台部署时使用
// var WxApiRoot = 'http://118.24.0.153:8080/wx/';
// var WxApiRoot = 'http://122.51.199.160:8080/wx/';
// 云平台上线时使用
// var WxApiRoot = 'https://www.menethil.com.cn/wx/';
......@@ -390,24 +460,21 @@ flush privilege
#### 1.4.5.1 日志配置
如果开发者启动litemall-all模块,则需要配置该模块的`application.yml`文件
如果开发者启动litemall-all模块,则需要配置该模块的`logback-spring.xml`文件
```
logging:
level:
root: ERROR
org.springframework: ERROR
org.mybatis: ERROR
org.linlinjava.litemall.core: ERROR
org.linlinjava.litemall.db: ERROR
org.linlinjava.litemall.admin: ERROR
org.linlinjava.litemall.wx: ERROR
org.linlinjava.litemall: ERROR
<logger name="org.mybatis" level="ERROR" />
<logger name="org.springframework" level="ERROR" />
<logger name="org.linlinjava.litemall.core" level="DEBUG" />
  <logger name="org.linlinjava.litemall.db" level="DEBUG" />
<logger name="org.linlinjava.litemall.admin" level="DEBUG" />
<logger name="org.linlinjava.litemall.wx" level="DEBUG" />
<logger name="org.linlinjava.litemall" level="DEBUG" />
```
具体如何配置,请自行学习Spring Boot的日志配置。
具体如何配置,请自行学习Spring Boot的日志配置和logback日志配置
`org.linlinjava.litemall.core`定义litemall-core模块的日志级别
`org.linlinjava.litemall.db`定义litemall-core模块的日志级别
`org.linlinjava.litemall.db`定义litemall-db模块的日志级别
`org.linlinjava.litemall.wx`定义litemall-wx-api模块的日志级别
`org.linlinjava.litemall.admin`定义litemall-admin-api模块的日志级别
`org.linlinjava.litemall`而定义litemall所有后端模块的日志级别
......@@ -417,7 +484,7 @@ logging:
注意:
> 如果开发者独立启动litemall-wx-api模块,那么则需要配置litemall-wx-api模块的
> `application.yml`文件来设置日志
> 日志配置方式。
#### 1.4.5.2 数据库连接配置
......@@ -522,8 +589,10 @@ litemall:
# 短信息用于通知客户,例如发货短信通知,注意配置格式;template-name,template-templateId 请参考 NotifyType 枚举值
sms:
enable: false
appid: 111111111
appkey: xxxxxxxxxxxxxx
# 如果是腾讯云短信,则设置active的值tencent
# 如果是阿里云短信,则设置active的值aliyun
active: tencent
sign: litemall
template:
- name: paySucceed
templateId: 156349
......@@ -533,13 +602,20 @@ litemall:
templateId: 158002
- name: refund
templateId: 159447
tencent:
appid: 111111111
appkey: xxxxxxxxxxxxxx
aliyun:
regionId: xxx
accessKeyId: xxx
accessKeySecret: xxx
```
配置方式:
1. 腾讯云短信平台申请,然后设置四个场景的短信模板;
2. 开发者在配置文件设置`enable`的值`true`,然后其他信息设置
腾讯云短信平台申请的appid等值。
这里只测试过腾讯云短信平台,开发者需要自行测试其他短信云平台。
1. 腾讯云短信平台或者阿里云短信平台申请,然后设置四个场景的短信模板;
2. 开发者在配置文件设置`enable`的值`true`,设置`active`的值`tencent`或`aliyun`
3. 然后配置其他信息,例如腾讯云短信平台申请的appid等值。
这里只测试过腾讯云短信平台和阿里云短信平台,开发者需要自行测试其他短信云平台。
应用场景:
目前短信通知场景只支持支付成功、验证码、订单发送、退款成功四种情况。
......@@ -549,6 +625,17 @@ litemall:
当配置好信息以后,开发者可以litemall-core模块的`SmsTest`测试类中设置手机号和
模板所需要的参数值,独立启动`SmsTest`测试类发送短信,然后查看手机是否成功接收短信。
短信模板参数命名:
这里存在一个问题,即腾讯云短信的官方平台中申请短信模板格式的模板参数是数组,
例如“你好,验证码是{0},时间是{1}";
而阿里云短信的官方平台中申请短信模板的模板参数是JSON,
例如“你好,验证码是{param1},时间是{param2}"。
为了保持当前代码的通用性,本项目采用数组传递参数,而对阿里云申请模板的参数做了一定的假设:
1. 腾讯云模块参数,申请模板时按照官方设置即可,例如“你好,验证码是{0},时间是{1}";
2. 阿里云模板参数,本项目假定开发者在官方申请的参数格式应该采用"{ code: xxx, code1: xxx, code2: xxx }",
例如“你好,验证码是{code},时间是{code1}"。开发者可以查看`AliyunSmsSender`类的`sendWithTemplate`方法的
源代码即可理解。如果觉得不合理,可以自行调整相关代码。
#### 1.4.5.7 微信通知配置
微信通知是微信上收到的服务通知。
......@@ -650,7 +737,7 @@ litemall:
在litemall-core模块的`application-core.yml`文件中配置对象存储服务:
* 本地对象存储配置
如果开发者采用当前主机保存上传的文件,则需要配置:
如果开发者采用当前服务器保存上传的文件,则需要配置:
```
litemall:
storage:
......@@ -743,41 +830,42 @@ litemall:
* litemall-wx模块部署在微信开发者工具中,此外数据API地址指向litemall-wx-api所在服务qi地址
* litemall-admin编译出的静态文件放在web服务器或者tomcat服务器,此外服务器地址设置指向3中litemall-admin-api所在地址
最后,**如果项目部署云主机,则根据开发者的部署环境在以下文件中或代码中修改相应的配置。**
最后,**如果项目部署云服务器,则根据开发者的部署环境在以下文件中或代码中修改相应的配置。**
1. MySQL数据库设置合适的用户名和密码信息;
2. 后端服务模块设置合适的配置信息;
3. 小商场前端litemall-wx模块`config/api.js`的`WxApiRoot`设置小商场后端服务的服务地址;
4. 管理后台前端litemall-admin模块`config/dep.env.js`中的`BASE_API`设置管理后台后端服务的服务地址。
4. 管理后台前端litemall-admin模块`.env.deployment`中的`VUE_APP_BASE_API`设置管理后台后端服务的服务地址。
实际上,最终的部署方案是灵活的:
* 可以是同一云主机中安装一个Spring Boot服务,同时提供litemall-admin、litemall-admin-api和litemall-wx-api三种服务
* 可以单一云主机中仅安装一个tomcat/nginx服务器部署litemall-admin静态页面分发服务,
* 可以是同一云服务器中安装一个Spring Boot服务,同时提供litemall-admin、litemall-admin-api和litemall-wx-api三种服务
* 可以单一云服务器中仅安装一个tomcat/nginx服务器部署litemall-admin静态页面分发服务,
然后部署两个Spring Boot的后端服务;
* 也可以把litemall-admin静态页面托管第三方cdn,然后开发者部署两个后端服务
* 当然,甚至多个服务器,采用集群式并发提供服务。
注意
> 1. `本机`指的是是当前的开发机
> 2. `云主机`指的是开发者购买并部署的远程主机
> 2. `云服务器`指的是开发者购买并部署的远程服务器
以下简单列举几种方案。
### 1.5.1 单机单服务部署方案
本节介绍基于腾讯云的单机单服务部署方案,面向的是服务器数据和应用部署在云主机单机中用于演示的场景。
本节介绍基于腾讯云的单机单服务部署方案,面向的是服务器数据和应用部署在云服务器单机中用于演示的场景。
其他云应该也是可行的。
主要流程是:创建云主机,安装ubuntu操作系统,按照JDK和MySQL应用运行环境,部署单一Spring Boot服务。
主要流程是:创建云服务器,安装ubuntu操作系统,按照JDK和MySQL应用运行环境,部署单一Spring Boot服务。
![](pic1/1-11.png)
#### 1.5.1.1 主机
#### 1.5.1.1 云服务器
请参考腾讯云官方文档进行相关操作。
1. 创建云服务器
1. 创建云主机虚拟机
请参考腾讯云、阿里云或者其他云平台的官方文档进行相关操作。
建议最低配置是**1核2G**。
2. 安装操作系统
......@@ -787,48 +875,55 @@ litemall:
![](pic1/1-4.png)
目前允许的端口:8081,8082,8083,8080,80,443,22,3306
目前允许的端口:8080,80,443,22,3306
注意:
这里其实只需要8080端口,允许其他端口只是方面开发阶段的测试和调试。
这里其实只需要8080端口,允许其他端口只是方便开发阶段的测试和调试。
特别是3306端口,作为MySQL的远程访问端口,请在上线阶段关闭。
4. 设置SSH密钥(可选)
建议开发者设置SSH密钥,可以免密码登录云主机,以及用于脚本自动上传应用。
建议开发者设置SSH密钥,可以免密码登录云服务器,以及用于脚本自动上传应用。
5. 使用PuTTY远程登录云主机
5. 使用PuTTY远程登录云服务器
如果开发者设置SSH密钥,可以采用免密码登录;否则采用账号和密码登录。
#### 1.5.1.2 JDK8
#### 1.5.1.2 OpenJDK8
https://www.digitalocean.com/community/tutorials/how-to-install-java-with-apt-get-on-ubuntu-16-04
这里可以安装openjdk-8-jre
http://www.webupd8.org/2012/09/install-oracle-java-8-in-ubuntu-via-ppa.html
```bash
sudo apt-get update
sudo apt-get install openjdk-8-jre
```
如果希望采用jdk,而不是jre,则可以运行
```bash
sudo add-apt-repository ppa:webupd8team/java
sudo apt-get update
sudo apt-get install oracle-java8-installer
sudo apt-get install oracle-java8-set-default
sudo apt-get install openjdk-8-jdk
```
警告
> "ppa:webupd8team/java" 不是Oracle官方PPA,可能存在安全隐患
注意
> 如果用户想采用Oracle JDK8或者其他JDK环境,请查阅相关资料安装
#### 1.5.1.3 MySQL
https://www.digitalocean.com/community/tutorials/how-to-install-mysql-on-ubuntu-16-04
```
sudo apt-get update
sudo apt-get install mysql-server
sudo apt-get install mysql-client
```
如果配置MySQL,可以运行命令
```
sudo mysql_secure_installation
```
#### 1.5.1.4 项目打包
1. 在主机或者开发机打包项目到deploy;
1. 在服务器或者开发机打包项目到deploy;
```
cd litemall
cat ./litemall-db/sql/litemall_schema.sql > ./deploy/db/litemall.sql
......@@ -853,26 +948,26 @@ sudo apt-get install mysql-client
2. 修改litemall文件夹下面的*.yml外部配置文件,当litemall-all模块启动时会
加载外部配置文件,而覆盖默认jar包内部的配置文件。
例如,配置文件中一些地方需要设置成远程主机的IP地址
例如,配置文件中一些地方需要设置成远程服务器的IP地址
此时deploy部署包结构如下:
* bin
存放远程主机运行的脚本,包括deploy.sh脚本和reset.sh脚本
存放远程服务器运行的脚本,包括deploy.sh脚本和reset.sh脚本
* db
存放litemall数据库文件
* litemall
存放远程主机运行的代码,包括litemall-all二进制可执行包和litemall外部配置文件
存放远程服务器运行的代码,包括litemall-all二进制可执行包和litemall外部配置文件
* util
存放开发主机运行的脚本,包括package.sh脚本和lazy.sh脚本。
由于是本地开发主机运行,因此开发者可以不用上传到远程主机
存放开发服务器运行的脚本,包括package.sh脚本和lazy.sh脚本。
由于是本地开发服务器运行,因此开发者可以不用上传到远程服务器
#### 1.5.1.5 项目部署
1. 远程主机环境(MySQL和JDK1.8)已经安装好,请确保云主机的安全组已经允许相应的端口。
1. 远程服务器环境(MySQL和JDK1.8)已经安装好,请确保云服务器的安全组已经允许相应的端口。
2. 导入db/litemall.sql
```bash
cd /home/ubuntu/deploy/db
......@@ -884,7 +979,7 @@ sudo apt-get install mysql-client
sudo ln -f -s /home/ubuntu/deploy/litemall/litemall.jar /etc/init.d/litemall
sudo service litemall start
```
4. 测试是否部署成功(xxx.xxx.xxx.xxx是云主机IP):
4. 测试是否部署成功(xxx.xxx.xxx.xxx是云服务器IP):
```
http://xxx.xxx.xxx.xxx:8080/wx/index/index
http://xxx.xxx.xxx.xxx:8080/admin/index/index
......@@ -903,26 +998,26 @@ sudo apt-get install mysql-client
* util/packet.sh
在开发主机运行可以自动项目打包
在开发服务器运行可以自动项目打包
* util/lazy.sh
在开发主机运行可以自动项目打包、项目上传远程主机、自动登录系统执行项目部署脚本。
在开发服务器运行可以自动项目打包、项目上传远程服务器、自动登录系统执行项目部署脚本。
注意:
> 1. 开发者需要在util/lazy.sh中设置相应的远程主机登录账号和密钥文件路径。
> 2. 开发者需要在bin/reset.sh设置远程主机的MySQL的root登录账户。
> 1. 开发者需要在util/lazy.sh中设置相应的远程服务器登录账号和密钥文件路径。
> 2. 开发者需要在bin/reset.sh设置远程服务器的MySQL的root登录账户。
* bin/deploy.sh
在远程主机运行可以自动部署服务
在远程服务器运行可以自动部署服务
* bin/reset.sh
在远程主机运行可以自动项目导入数据、删除本地上传图片、再执行bin/deploy.sh部署服务。
在远程服务器运行可以自动项目导入数据、删除本地上传图片、再执行bin/deploy.sh部署服务。
注意:
> 开发者需要在bin/reset.sh设置远程主机的MySQL的root登录账户。
> 开发者需要在bin/reset.sh设置远程服务器的MySQL的root登录账户。
总结,当开发者设置好配置信息以后,可以在本地运行lazy.sh脚本自动一键部署:
```bash
......@@ -943,8 +1038,8 @@ cd litemall
1. 专门的云数据库部署数据
2. 专门的云存储方案
3. 专门的CDN分发管理后台的静态文件
4. 一台云主机部署管理后台的后端服务
5. 一台或多台云主机部署小商场的后端服务
4. 一台云服务器部署管理后台的后端服务
5. 一台或多台云服务器部署小商场的后端服务
虽然由于环境原因没有正式测试过,但是这种简单的集群式场景应该是可行的。
在1.5.2节中所演示的三个服务是独立的,因此延伸到这里分布式是非常容易的。
......@@ -993,7 +1088,7 @@ sudo apt-get update
sudo apt-get install nginx
```
有的文档会指出需要防火墙设置,但是腾讯云主机防火墙默认没有开启。
有的文档会指出需要防火墙设置,但是腾讯云服务器防火墙默认没有开启。
开发者这里自己可以开启设置,或者直接不开启。
打开浏览器,输入以下地址:
......@@ -1137,9 +1232,9 @@ http://www.example.com
1. MySQL数据库设置合适的用户名和密码信息;
2. 管理后台后端服务模块设置合适的配置信息,建议开发者参考deploy/litemall的外部配置文件,
这样可以避免开发者对模块内部的开发配置文件造成修改;
3. 管理后台前端litemall-admin模块`config/prod.env.js`中的`BASE_API`设置管理后台后端服务的服务地址。
3. 管理后台前端litemall-admin模块`.env.production`中的`VUE_APP_BASE_API`设置管理后台后端服务的服务地址。
### 1.6.5 项目评估和调整
### 1.6.5 项目评估
本项目只是参考项目,项目代码质量和功能不可能符合开发者的最终需求,
因此开发者**请务必仔细评估项目代码**。
......@@ -1178,6 +1273,69 @@ litemall-admin编译得到的前端文件在第一次加载时相当耗时,这
建议开发者根据自己业务或架构情况优化。
### 1.6.7 项目安全
项目一旦正式上线,即对外正式服务。但是服务同时,可能会存在安全隐患甚至黑客攻击。
本节仅列举一些注意事项,欢迎开发者补充和完善。
#### 1.6.7.1 账户安全
这里的账号安全,既包括商城端用户账户,也包括管理后台端管理员账户。
目前账号安全还缺乏一点的保护措施,例如
* 用户密码失败超过阈值,则显示验证码;
* 用户密码失败超过阈值,则取消登录;
* 用户密码失败超过阈值,则需要手机验证码;
#### 1.6.7.2 关键业务记录
有关订单或者金钱相关的操作,建议开发者尽可能记录在数据库中,以便以后回溯。
#### 1.6.7.3 API统一调整
本项目公布了参考API接口,如果出现BUG可能会被黑客作为入口。
建议开发者上线之前可以统一调整接口,以减少安全隐患。
#### 1.6.7.4 对账
本项目管理后台没有对账功能,建议开发者可以开发对账比对商场的状态是否正常。
#### 1.6.7.5 取消或者限制退款
本项目不支持自动退款功能,而是在管理后台通过管理员点击退款按钮来人工退款。
但是仍然可能存在隐患,例如黑客通过漏洞进入管理后台从而进行不合理的退款操作。
因此建议开发者可以取消管理后台的退款按钮,而仅仅保持退款信息,管理员可以登录
微信官方支付平台进行退款操作。
或者建议开发者基于一定的业务逻辑或场景限制管理后台的退款功能。例如,设置当天
退款限额从而保证不会产生无限退款操作。
#### 1.6.7.6 资源限制访问
一些API操作涉及到后端服务器资源,因此需要做一定的限制,防止有限资源被恶意消耗。
有限资源可能包括:
* 验证码
* 图片上传
一些限制措施可能包括:
* 限制单个IP的访问频率
* 限制用户上传图片数量
#### 1.6.7.n 跟踪本项目进展
一旦有开发者反馈BUG,本项目会优先解决并及时上传补丁。
因此建议开发者跟踪本项目进展,留意每次BUG修复的commit。
同时也希望开发者发现任何BUG都及时反馈。
目前还不存在LTS版本,未来业务稳定后可能会发布。
## 1.7 项目管理
这里简述一些当前项目开发的要点。
......@@ -1194,16 +1352,18 @@ litemall-admin编译得到的前端文件在第一次加载时相当耗时,这
* litemall-all/.gitignore
* .gitignore
开发者可以采用单一.gitignore文件。
### 1.7.2 项目自动部署
#### 1.7.2.1 deploy部署
当前项目存在deploy部署文件夹,这个是上述1.5.1节部署腾讯云主机所采取的一些脚本。
当前项目存在deploy部署文件夹,这个是上述1.5.1节部署腾讯云服务器所采取的一些脚本。
流程如下:
1. util脚本是当前开发主机运行,用来打包项目和上传腾讯云主机
1. util脚本是当前开发服务器运行,用来打包项目和上传腾讯云服务器
2. 打包项目时,会编译打包项目相关模块到litemall和db文件夹中;
3. bin脚本是云主机运行,用来安装数据库、导入数据、启动项目服务。
3. bin脚本是云服务器运行,用来安装数据库、导入数据、启动项目服务。
这里deploy部署方式比较简单不灵活,开发者可以参考开发自己的项目脚本。
......@@ -1333,8 +1493,8 @@ application配置文件中,但是问题就是数据库信息一旦改变则其
* 503,业务不支持,即后端虽然定义了接口,但是还没有实现功能;
* 504,更新数据失效,即后端采用了乐观锁更新,而并发更新时存在数据更新失效;
* 505,更新数据失败,即后端数据库更新失败(正常情况应该更新成功)。
* 6xx,小商城后端业务错误码,具体见litemall-admin-api模块的`AdminResponseCode`类。
* 7xx,管理后台后端业务错误码,具体见litemall-wx-api模块的`WxResponseCode`类。
* 6xx,管理后台后端业务错误码,具体见litemall-admin-api模块的`AdminResponseCode`类。
* 7xx,小商城后端业务错误码,具体见litemall-wx-api模块的`WxResponseCode`类。
需要指出的是,小商场后端可能返回4xx、5xx和6xx错误码;管理后台后端则可能返回4xx、5xx和7xx错误码。
这样设计原因是方便小商场前端和管理后台前端区别对待。
......@@ -1356,6 +1516,9 @@ application配置文件中,但是问题就是数据库信息一旦改变则其
和小商场前端类似,管理后台前端处理后端响应错误码也存在三种类似的处理方式。
注意:
> 这里的4xx和5xx错误码,和HTTP中的4xx和5xx状态码不是一个概念。
### 1.7.7 TODO
本项目存在一些TODO,**强烈建议**开发者上线前仔细审阅是否存在问题和做相应调整。
......
......@@ -12,7 +12,6 @@
目前发现存在的一些问题:
* `缺失`优惠券功能
* `缺失`商品评价中管理员回复功能,进一步地用户之间相互评价回复
* `缺失`后台服务返回的token存在有效期,小商场应该自动刷新
* `缺失`账号多次登录失败,应该小商城出现图片验证码限制,或者后台账号锁定
......@@ -29,9 +28,6 @@
* `改善`个人页面中实现订单部件,显示用户订单数量,同时点击以后跳转到订单的相应页面。
* `改善`商品的订单中支持订单号搜索功能
* `改善`在一些内容比较多的页面中支持“顶部”功能
* `功能`目前已经有账号登录页面,可以再支持手机短信登录方式。
* `功能`个人页面支持帮助中心
* `功能`推荐功能,基于用户的一些信息,在合适的页面给出推荐商品
## 3.0 小商场环境
......@@ -87,9 +83,9 @@
2. 启动后台服务
3. 部署后台服务到云主机
3. 部署后台服务到云服务器
4. litemall-wx的api.js设置云主机的域名。
4. litemall-wx的api.js设置云服务器的域名。
编译运行,尝试微信支付。
### 3.0.3 微信退款配置
......@@ -240,14 +236,14 @@ var WxApiRoot = 'http://localhost:8082/wx/';
// 局域网测试使用
// var WxApiRoot = 'http://192.168.0.101:8082/wx/';
// 云平台部署时使用
// var WxApiRoot = 'http://118.24.0.153:8082/wx/';
// var WxApiRoot = 'http://122.51.199.160:8082/wx/';
```
也就是说这里存在三种类型的API服务地址,这里是考虑到开发存在三种情况:
1. 本机开发时,localhost是当前开发机的地址;
2. 手机预览时,192.168.0.101是开发机的IP地址;
3. 当后台部署在云主机中时,118.24.0.153是云主机的IP地址;
3. 当后台部署在云服务器中时,122.51.199.160是云服务器的IP地址;
4. 此外,更最重要的是,如果小程序正式部署时,这里的地址必须是域名,
而不能是IP地址。
......
......@@ -9,7 +9,10 @@
<artifactId>litemall</artifactId>
<version>0.1.0</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<dependencies>
<dependency>
......@@ -21,39 +24,22 @@
<groupId>org.linlinjava</groupId>
<artifactId>litemall-db</artifactId>
</dependency>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-miniapp</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-web-starter</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<classifier>exec</classifier>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
......@@ -6,7 +6,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@SpringBootApplication(scanBasePackages = {"org.linlinjava.litemall.db", "org.linlinjava.litemall.core", "org.linlinjava.litemall.admin"})
@SpringBootApplication(scanBasePackages = {"org.linlinjava.litemall.db", "org.linlinjava.litemall.core", "org" +
".linlinjava.litemall.admin"})
@MapperScan("org.linlinjava.litemall.db.dao")
@EnableTransactionManagement
@EnableScheduling
......
package org.linlinjava.litemall.admin.annotation;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
......@@ -11,5 +9,6 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
public @interface RequiresPermissionsDesc {
String[] menu();
String button();
}
package org.linlinjava.litemall.admin.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* swagger在线文档配置<br>
* 项目启动后可通过地址:http://host:ip/swagger-ui.html 查看在线文档
*
* @author enilu
* @version 2018-07-24
*/
@Configuration
@EnableSwagger2
public class AdminSwagger2Configuration {
@Bean
public Docket adminDocket() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName("admin")
.apiInfo(adminApiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("org.linlinjava.litemall.admin.web"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo adminApiInfo() {
return new ApiInfoBuilder()
.title("litemall-admin API")
.description("litemall管理后台API")
.termsOfServiceUrl("https://github.com/linlinjava/litemall")
.contact("https://github.com/linlinjava/litemall")
.version("1.0")
.build();
}
}
package org.linlinjava.litemall.admin.config;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.linlinjava.litemall.admin.shiro.AdminAuthorizingRealm;
import org.linlinjava.litemall.admin.shiro.AdminWebSessionManager;
......@@ -25,7 +25,7 @@ public class ShiroConfig {
}
@Bean
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
......@@ -45,12 +45,12 @@ public class ShiroConfig {
@Bean
public SessionManager sessionManager() {
AdminWebSessionManager mySessionManager = new AdminWebSessionManager();
return mySessionManager;
return new AdminWebSessionManager();
}
@Bean
public DefaultWebSecurityManager securityManager() {
public DefaultWebSecurityManager defaultWebSecurityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(realm());
securityManager.setSessionManager(sessionManager());
......@@ -59,7 +59,8 @@ public class ShiroConfig {
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor =
new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
......
package org.linlinjava.litemall.admin.config;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authz.AuthorizationException;
import org.linlinjava.litemall.core.util.ResponseUtil;
......@@ -10,20 +12,22 @@ import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
@ControllerAdvice
@Order( value = Ordered.HIGHEST_PRECEDENCE )
@Order(value = Ordered.HIGHEST_PRECEDENCE)
public class ShiroExceptionHandler {
private final Log logger = LogFactory.getLog(ShiroExceptionHandler.class);
@ExceptionHandler(AuthenticationException.class)
@ResponseBody
public Object unauthenticatedHandler(AuthenticationException e) {
e.printStackTrace();
logger.warn(e.getMessage(), e);
return ResponseUtil.unlogin();
}
@ExceptionHandler(AuthorizationException.class)
@ResponseBody
public Object unauthorizedHandler(AuthorizationException e) {
e.printStackTrace();
logger.warn(e.getMessage(), e);
return ResponseUtil.unauthz();
}
......
......@@ -11,6 +11,7 @@ import org.linlinjava.litemall.db.util.CouponUserConstant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.List;
/**
......@@ -35,13 +36,13 @@ public class CouponJob {
logger.info("系统开启任务检查优惠券是否已经过期");
List<LitemallCoupon> couponList = couponService.queryExpired();
for(LitemallCoupon coupon : couponList){
for (LitemallCoupon coupon : couponList) {
coupon.setStatus(CouponConstant.STATUS_EXPIRED);
couponService.updateById(coupon);
}
List<LitemallCouponUser> couponUserList = couponUserService.queryExpired();
for(LitemallCouponUser couponUser : couponUserList){
for (LitemallCouponUser couponUser : couponUserList) {
couponUser.setStatus(CouponUserConstant.STATUS_EXPIRED);
couponUserService.update(couponUser);
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment