设计文档
https://gitee.com/imooccode/happymmallwiki/wikis/Home
源码地址
https://github.com/erlieStar/mall
数据表结构设计
用户表
CREATE TABLE `mall_user` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户表id',
`username` varchar(50) NOT NULL COMMENT '用户名',
`password` varchar(50) NOT NULL COMMENT '用户密码,MD5加密',
`email` varchar(50) DEFAULT NULL,
`phone` varchar(20) DEFAULT NULL,
`question` varchar(100) DEFAULT NULL COMMENT '找回密码问题',
`answer` varchar(100) DEFAULT NULL COMMENT '找回密码答案',
`role` int(4) NOT NULL COMMENT '角色0-管理员,1-普通用户',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_time` datetime NOT NULL COMMENT '最后一次更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `user_name_unique` (`username`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=22 DEFAULT CHARSET=utf8;
这里为了方便直接存了MD5加密的密码,盐值在项目中配置,这里是省略的做法,一般的做法是有2个字段password(加密后的密码),salt(盐值),这里的盐值是随机生成的,每个密码的盐值都不同,加密后的密码存的是hash(用户输入密码+盐值),这样用户登录时,通过比对hash(用户输入密码+盐值)和数据库中的值就能知道用户的密码是否正确,避免了明文密码泄露的风险
分类表
CREATE TABLE `mall_category` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '类别Id',
`parent_id` int(11) DEFAULT NULL COMMENT '父类别id当id=0时说明是根节点,一级类别',
`name` varchar(50) DEFAULT NULL COMMENT '类别名称',
`status` tinyint(1) DEFAULT '1' COMMENT '类别状态1-正常,2-已废弃',
`sort_order` int(4) DEFAULT NULL COMMENT '排序编号,同类展示顺序,数值相等则自然排序',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=100032 DEFAULT CHARSET=utf8;
产品表
CREATE TABLE `mall_product` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '商品id',
`category_id` int(11) NOT NULL COMMENT '分类id,对应mall_category表的主键',
`name` varchar(100) NOT NULL COMMENT '商品名称',
`subtitle` varchar(200) DEFAULT NULL COMMENT '商品副标题',
`main_image` varchar(500) DEFAULT NULL COMMENT '产品主图,url相对地址',
`sub_images` text COMMENT '图片地址,json格式,扩展用',
`detail` text COMMENT '商品详情',
`price` decimal(20,2) NOT NULL COMMENT '价格,单位-元保留两位小数',
`stock` int(11) NOT NULL COMMENT '库存数量',
`status` int(6) DEFAULT '1' COMMENT '商品状态.1-在售 2-下架 3-删除',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=30 DEFAULT CHARSET=utf8;
decimal(20,2),18个整数位和2个小数位,java中一般用BigDecimal来对应这个类型
购物车表
CREATE TABLE `mall_cart` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`product_id` int(11) DEFAULT NULL COMMENT '商品id',
`quantity` int(11) DEFAULT NULL COMMENT '数量',
`checked` int(11) DEFAULT NULL COMMENT '是否选择,1=已勾选,0=未勾选',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `user_id_index` (`user_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=146 DEFAULT CHARSET=utf8;
支付信息表
CREATE TABLE `mall_pay_info` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) DEFAULT NULL COMMENT '用户id',
`order_no` bigint(20) DEFAULT NULL COMMENT '订单号',
`pay_platform` int(10) DEFAULT NULL COMMENT '支付平台:1-支付宝,2-微信',
`platform_number` varchar(200) DEFAULT NULL COMMENT '支付宝支付流水号',
`platform_status` varchar(20) DEFAULT NULL COMMENT '支付宝支付状态',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=61 DEFAULT CHARSET=utf8;
订单表
CREATE TABLE `mall_order` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '订单id',
`order_no` bigint(20) DEFAULT NULL COMMENT '订单号',
`user_id` int(11) DEFAULT NULL COMMENT '用户id',
`shipping_id` int(11) DEFAULT NULL,
`payment` decimal(20,2) DEFAULT NULL COMMENT '实际付款金额,单位是元,保留两位小数',
`payment_type` int(4) DEFAULT NULL COMMENT '支付类型,1-在线支付',
`postage` int(10) DEFAULT NULL COMMENT '运费,单位是元',
`status` int(10) DEFAULT NULL COMMENT '订单状态:0-已取消-10-未付款,20-已付款,40-已发货,50-交易成功,60-交易关闭',
`payment_time` datetime DEFAULT NULL COMMENT '支付时间',
`send_time` datetime DEFAULT NULL COMMENT '发货时间',
`end_time` datetime DEFAULT NULL COMMENT '交易完成时间',
`close_time` datetime DEFAULT NULL COMMENT '交易关闭时间',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `order_no_index` (`order_no`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=118 DEFAULT CHARSET=utf8;
payment不要和产品里面的金额做联动,例如买iphone的时候是6800,后来产品变成6000,这个表里面存的也应该是6800,close_time表示已经下单,没有付款,过了一段时间,订单超时,交易关闭
订单明细表
CREATE TABLE `mall_order_item` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '订单子表id',
`user_id` int(11) DEFAULT NULL,
`order_no` bigint(20) DEFAULT NULL,
`product_id` int(11) DEFAULT NULL COMMENT '商品id',
`product_name` varchar(100) DEFAULT NULL COMMENT '商品名称',
`product_image` varchar(500) DEFAULT NULL COMMENT '商品图片地址',
`current_unit_price` decimal(20,2) DEFAULT NULL COMMENT '生成订单时的商品单价,单位是元,保留两位小数',
`quantity` int(10) DEFAULT NULL COMMENT '商品数量',
`total_price` decimal(20,2) DEFAULT NULL COMMENT '商品总价,单位是元,保留两位小数',
`create_time` datetime DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `order_no_index` (`order_no`) USING BTREE,
KEY `order_no_user_id_index` (`user_id`,`order_no`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=135 DEFAULT CHARSET=utf8;
user_id是一个冗余字段,本可以通过order_no找到user_id,这里是为了提高查询效率
收货地址表
CREATE TABLE `mall_shipping` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) DEFAULT NULL COMMENT '用户id',
`receiver_name` varchar(20) DEFAULT NULL COMMENT '收货姓名',
`receiver_phone` varchar(20) DEFAULT NULL COMMENT '收货固定电话',
`receiver_mobile` varchar(20) DEFAULT NULL COMMENT '收货移动电话',
`receiver_province` varchar(20) DEFAULT NULL COMMENT '省份',
`receiver_city` varchar(20) DEFAULT NULL COMMENT '城市',
`receiver_district` varchar(20) DEFAULT NULL COMMENT '区/县',
`receiver_address` varchar(200) DEFAULT NULL COMMENT '详细地址',
`receiver_zip` varchar(6) DEFAULT NULL COMMENT '邮编',
`create_time` datetime DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=33 DEFAULT CHARSET=utf8;
vsftpd安装与配置
vsftpd安装
查看是否安装
rpm -qa| grep vsftpd
安装
yum -y install vsftpd
创建ftp文件夹
mkdir ftpfile
添加匿名用户
useradd ftpuser -d /root/ftpfile -s /sbin/nologin
修改ftpfile权限
chown -R ftpuser.ftpuser /root/ftpfile
重设ftpuser密码
passwd ftpuser
vsftpd配置
cd /etc/vsftpd
vim chroot_list
写入ftpuser,保存退出
vim /etc/selinux/config,修改SELINUX=disabled
reboot(重启)
vim /etc/vsftpd/vsftpd.conf
详细的配置可以访问如下链接:http://learning.happymmall.com/vsftpdconfig/vsftpd.conf.readme.html
防火墙配置
-A INPUT -p TCP --dport 61001:62000 -j ACCEPT
-A OUTPUT -p TCP --sport 61001:62000 -j ACCEPT
-A INPUT -p TCP --dport 20 -j ACCEPT
-A OUTPUT -p TCP --sport 20 -j ACCEPT
-A INPUT -p TCP --dport 21 -j ACCEPT
-A OUTPUT -p TCP --sport 21 -j ACCEPT
vsftpd常用命令
service vsftpd start
service vsftpd stop
service vsftpd restart
windows版下载地址:http://download.csdn.net/download/zzti_erlie/10214249
启动后用浏览器访问ftp://localhost即可
Mybatis-generator的配置
mybatis-generator可以根据数据库表生成pojo,dao和xml文件
pom.xml
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.2</version>
<configuration>
<verbose>true</verbose>
<overwrite>true</overwrite>
</configuration>
</plugin>
</plugins>
</build>
datasource.properties
db.driverLocation=C:/Users/Administrator/.m2/repository/mysql/mysql-connector-java/5.1.35/mysql-connector-java-5.1.35.jar
db.driverClassName=com.mysql.jdbc.Driver
db.url=jdbc:mysql://localhost:3306/mall?characterEncoding=utf-8
db.username=root
db.password=peng2014
generatorConfig.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!--导入属性配置-->
<properties resource="datasource.properties"></properties>
<!--指定特定数据库的jdbc驱动jar包的位置-->
<classPathEntry location="${db.driverLocation}"/>
<context id="default" targetRuntime="MyBatis3">
<!-- optional,旨在创建class时,对注释进行控制 -->
<commentGenerator>
<property name="suppressDate" value="true"/>
<property name="suppressAllComments" value="true"/>
</commentGenerator>
<!--jdbc的数据库连接 -->
<jdbcConnection
driverClass="${db.driverClassName}"
connectionURL="${db.url}"
userId="${db.username}"
password="${db.password}">
</jdbcConnection>
<!-- 非必需,类型处理器,在数据库类型和java类型之间的转换控制-->
<javaTypeResolver>
<property name="forceBigDecimals" value="false"/>
</javaTypeResolver>
<!-- Model模型生成器,用来生成含有主键key的类,记录类 以及查询Example类
targetPackage 指定生成的model生成所在的包名
targetProject 指定在该项目下所在的路径
-->
<!--<javaModelGenerator targetPackage="com.mall.pojo" targetProject=".\src\main\java">-->
<javaModelGenerator targetPackage="com.makenv.pojo" targetProject="./src/main/java">
<!-- 是否允许子包,即targetPackage.schemaName.tableName -->
<property name="enableSubPackages" value="false"/>
<!-- 是否对model添加 构造函数 -->
<property name="constructorBased" value="true"/>
<!-- 是否对类CHAR类型的列的数据进行trim操作 -->
<property name="trimStrings" value="true"/>
<!-- 建立的Model对象是否 不可改变 即生成的Model对象不会有 setter方法,只有构造方法 -->
<property name="immutable" value="false"/>
</javaModelGenerator>
<!--mapper映射文件生成所在的目录 为每一个数据库的表生成对应的SqlMap文件 -->
<!--<sqlMapGenerator targetPackage="mappers" targetProject=".\src\main\resources">-->
<sqlMapGenerator targetPackage="mappers" targetProject="./src/main/resources">
<property name="enableSubPackages" value="false"/>
</sqlMapGenerator>
<!-- 客户端代码,生成易于使用的针对Model对象和XML配置文件 的代码
type="ANNOTATEDMAPPER",生成Java Model 和基于注解的Mapper对象
type="MIXEDMAPPER",生成基于注解的Java Model 和相应的Mapper对象
type="XMLMAPPER",生成SQLMap XML文件和独立的Mapper接口
-->
<!-- targetPackage:mapper接口dao生成的位置 -->
<!--<javaClientGenerator type="XMLMAPPER" targetPackage="com.mall.dao" targetProject=".\src\main\java">-->
<javaClientGenerator type="XMLMAPPER" targetPackage="com.makenv.dao" targetProject="./src/main/java">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
</javaClientGenerator>
<!--tableName表名,domainObjectName生成Java类的类名,enableCountByExample是否可以通过对象查数量,其他类似-->
<table tableName="mall_shipping" domainObjectName="Shipping" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>
<table tableName="mall_cart" domainObjectName="Cart" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>
<table tableName="mall_cart_item" domainObjectName="CartItem" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>
<table tableName="mall_category" domainObjectName="Category" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>
<table tableName="mall_order" domainObjectName="Order" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>
<table tableName="mall_order_item" domainObjectName="OrderItem" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>
<table tableName="mall_pay_info" domainObjectName="PayInfo" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>
<table tableName="mall_product" domainObjectName="Product" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false">
<!--数据库中是text类型,各个版本生成的类型不同,这里指定一下,生成String类型-->
<columnOverride column="detail" jdbcType="VARCHAR" />
<columnOverride column="sub_images" jdbcType="VARCHAR" />
</table>
<table tableName="mall_user" domainObjectName="User" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>
<!-- geelynote mybatis插件的搭建 -->
</context>
</generatorConfiguration>
在Idea中选中如图所示的部分,点击即可
数据库中的列名建议写成如下形式,parent_id,这样在类中生成的属性名为parentId,最后我们将数据库中的列create_time,update_time交由数据库控制,用内置的now()函数,如下
<insert id="insert" parameterType="com.makenv.pojo.Cart" >
insert into mall_cart (id, user_id, product_id,
quantity, checked, create_time,
update_time)
values (#{id,jdbcType=INTEGER}, #{userId,jdbcType=INTEGER}, #{productId,jdbcType=INTEGER},
#{quantity,jdbcType=INTEGER}, #{checked,jdbcType=INTEGER}, now(),
now())
</insert>
安装Mybatis-plugin
先看效果,可以通过点击左边的箭头实现mapper接口和xml文件的切换,非常方便
依次点击File->Plugins->Browse repositories->输入Free MyBatis plugin->Install
Mybatis-PageHelper
GitHub地址:https://github.com/pagehelper/Mybatis-PageHelper
Swagger2
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.6.1</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.6.1</version>
</dependency>
@Configuration
@EnableSwagger2
public class Swagger2 {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("com.makenv.controller"))
.build();
}
}
访问http://localhost:8080/swagger-ui.html即可测试controller,注意将包名改成自己的包名
支付和订单模块
- 用户选中订单进行支付
- 通过AlipayTradeService发送请求的参数,并接受AlipayTradeService返回的参数,判断订单的状态(下单成功,下单失败,系统异常等)
- 如果下单成功,从参数中获取二维码,并将二维码上传到FTP服务器上,前端从FTP服务器上获取图片,展示给用户。
- 用户扫描二维码后,支付宝将订单的变更信息通过配置好的回调函数传给商户,商户再进行业务操作,如修改订单状态,增加支付信息
在本地测试时,必须得有一个让支付宝回调的地址,这就得用到内网转发,参考博客:http://blog.csdn.net/zzti_erlie/article/details/78309104
Lombok
在IDEA上增加Lombok Plugin插件,不然会报错
@Data
里面包含了@Getter,@Setter,@ToString,@EqualsAndHashCode()
@Getter
@Getter(AccessLevel.PROTECTED)
方法为protected类型
@Setter
@Setter(AccessLevel.PROTECTED)
方法为protected类型
@NoArgsConstructor
无参构造器
@AllArgsConstructor
全参构造器
@EqualsAndHashCode(of = “id”)
id相等的时候认为equals和hashcode相等
@EqualsAndHashCode(exclude = “id”)
id这个字段不加入equals和hashcode方法中
@EqualsAndHashCode(of = {“id”, “name”})
id和name相等的时候认为equals和hashcode相等
@Slf4j
在logback中使用
相当于在代码中加了如下语句
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private Logger log = LoggerFactory.getLogger(CategoryServiceImpl.class);
@Log4j
在log4j中使用
@ToString
@ToString(exclude = “column1”)
@ToString(of = “column1”)
@ToString(exclude = {“column1”, “column2”})
@ToString(exclude = {“column1”, “column2”})
of为包含,exclude为排除
##Spring MVC全局异常处理
无Spring MVC全局异常时的流程图
Spring MVC全局异常流程图
Spring Schedule
Spring Schedule Cron表达式快速入门
Cron表达式的格式:秒 分 时 日 月 周 年(可选)
- Seconds
- Minutes
- Hours
- Day-of-Month
- Month
- Day-of-Week
- Year(可选字段)
cron表达式校验:http://cron.qqe2.com/