在线商城Java项目(第一阶段)-服务端(环境和业务)
可在电脑上阅读,以获取最佳阅读效果,谢谢!
已支持在线查看PDF电子书版本
			
项目开始 20171018
结束时间 20171212 21:30

Git代码地址:https://gitee.com/jiangjiesheng/mmall/tree/v1.0
接口文档:https://gitee.com/jiangjiesheng/mmall/wikis/Home

点击在线阅读PDF电子书版本(无需下载)

目录
	一、开发环境的安装预配置
	   1、Linux系统安装 CentOS 7 64位
	   2、软件源配置 
	   3、jdk安装
	   4、Tomcat7 安装
	   5、Maven安装
	   6、vsftp搭建
	   7、Nginx安装
	   8、MySQL安装和配置
	   9、git安装
	
	二、表结构
	三、项目的初始化
	四、用户模块的开发
	五、后台管理模块
	六、分类管理模块
	七、商品管理
	八、购物车模块
	九、收货地址管理
	十、支付模块开发-前期介绍和准备
	十一、支付模块开发-业务层开发
	十二、订单模块开发
	十三、服务端项目自动化发布

---------------------------------------------相关服务启动-----------------------------------

1> 启动tomcat
/usr/xxxxx/tomcat7/apache-tomcat-7.0.73/bin/startup.sh
2> 启动防火墙
sudo service iptables restart
3> 启动ftp
/usr/sbin/vsftpd & 
4> 启动nginx
#nginx: [error] open() "/usr/local/nginx/logs/nginx.pid" failed (2: No such file or directory)
---> /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf

/usr/local/nginx/sbin/nginx -s reload    # -s reload用于更新配置

5> 启动数据库
sudo service mysqld restart

一、开发环境的安装预配置
1、Linux系统安装 CentOS 7 64位
	账户 root 123456,admin 123456
	注意:关于Centos 7:
	      新装系统可能都需要先配置一下ip
	1> ip 查看 ip addr (如果提示ip未知的话,需要修改ip配置)
	        http://www.cnblogs.com/dunitian/p/4974761.html
	核心:cd /etc/sysconfig/network-scripts
	打开 sudo vi  ifcfg-eth0 (可能是eth1 或 ifcfg-ens33等,不一定相同)
	设置BOOTPROTO=dhcp
	            ONBOOT=yes
	保存后 service network restart 
	如果依然获取不到ip,shutdown -h 0 ,把网络适配器的NAT模式改为桥接模式		
	(不勾选复制物理网络连接状态)
	安装完wget后好像就可以执行ifconfig
	2> 安装wget: sudo yum -y install wget

2、软件源配置 
	阿里云源配置官网 http://mirrors.aliyun.com
	Linux:centos6.8 64bit 
	http://mirrors.aliyun.com/centos/6.8/isos/x86_64/CentOS-6.8-x86_64-bin-DVD1.iso 
	
	阿里云软件源配置说明 
	centos:http://mirrors.aliyun.com/help/centos 

 3、jdk安装
	如果安装centos6.8时默认安装了例如openjdk等,先执行rpm -qa | grep jdk(centos环境有效),然后卸载 sudo yum remove XXX。
	下载 jdk
	wget http://192.168.1.105:81/jdk-8u151-linux-x64-64bit.rpm
	jdk包增加权限 sudo chmod 777 jdk-8u151-linux-x64.rpm
	安装jdk : sudo rpm -ivh jdk-8u151-linux-x64.rpm 
	默认安装在/usr/java/下,然后设置环境变量,sudo vim /etc/profile  , 追加
	export JAVA_HOME=/usr/java/jdk1.8.0_151
	export CLASSPATH=.:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:
	$JAVA_HOME/lib/tools.jar  #(注意含有空格需要清除)
	export PATH=$PATH:$JAVA_HOME/bin    #注意有bin
	保存后更新 source /etc/profile

4、Tomcat7 安装
      1> 下载 wget http://192.168.1.105:81/apache-tomcat-7.0.73.tar.gz
      2> 解压 tar -xvf apache-tomcat-7.0.73.tar.gz
    安装路径位置 /usr/mylibs/tomcat7  --直接解压不能通过whereis 查询路径
      3> 修改字符集
       编辑 sudo vi conf/server.xml
	搜索8080  ?8080
	增加URIEncoding=“UTF-8”
	        4> 执行启动 /bin/startup.sh  
	或 cd bin后 ./startup.sh 执行启动 (需要重启防火墙)
	访问测试 192.168.1.105:8080 -->打不开网页
	继续配置步骤5>

  5> 配置防火墙 (放在“7、Nginx安装”之后处理 !!)
	 安装iptable iptable-service 
	 ①关闭firewall 
	systemctl stop firewalld.service #关闭防火墙
	systemctl disable firewalld.service #禁止firewall开机启动
	 ②安装iptables防火墙 
	yum install iptables-services #安装iptables 
	vi /etc/sysconfig/iptables  #编辑防火墙文件 
	(前期配置时最好完全关闭防火墙,后期直接下载配置文件 “iptables”)


	添加80和3306端口 
	-A INPUT -m state –state NEW -m tcp -p tcp –dport 80 -j ACCEPT 
	-A INPUT -m state –state NEW -m tcp -p tcp –dport 3306 -j ACCEPT
	
	systemctl restart iptables.service #重启防火墙使配置文件生效 
	systemctl enable iptables.service #设置iptables防火墙为开机启动项 
	 ③关闭SELINUX (此步骤未验证,暂时跳过)
	 vi /etc/selinux/config
	 #注释以下配置 
	 SELINUX=enforcing  
	 SELINUXTYPE=targeted 
	 SELINUX=disabled
	 #增加以下配置 
	 setenforce 0 #使配置立即生效 
	
	service iptables status #查看防火墙状态
	       
	具体配置见文件iptables.可以通过wget获取
	重启防火墙 sudo service iptables restart
	配置环境变量 export CATALINA_HOME=/xxxx/tomcat包文件夹路径 
	(应该不需要配置,跳过!!!)

5、Maven安装
	1> 下载 wget  http://learning.happymmall.com/maven/apache-maven-3.0.5-bin.tar.gz
	2> 解压,添加环境变量
	       export MAVEN_HOME=/usr/mylibs/maven3/apache-maven-3.0.5
	       export PATH=$JAVA_HOME/bin:$MAVEN_HOME/bin:$PATH  //注意有bin
	保存后更新 source /etc/profile
	3> 测试 mvn --version
	4> maven常见命令
	清除:mvn clean 编译:mvn compile 打包:mvn package
	跳过单元测试:mvn clean package -Dmaven.test.skip=true

6、vsftp搭建
	1> “very secure FTP daemon” --完全免费、开源
	       	  2> 安装
	rpm -qa | grep vsftpd 检查是否安装
	yum -y install vsftpd
	
	cd / 进录根目录
	mkdir ftpfile
	cd ftpfile
	sudo useradd ftpuser -d /ftpfile/ -s /sbin/nologin 创建虚拟用户(无登录权限)
	       提示主目录已存在....文件已存在-->忽略即可
	 (查看用户 cat /etc/passwd | grep ftpuser)
	 (删除用户 userdel ftpuser)
	sudo chown -R ftpuser.ftpuser /ftpfile/  改变拥有者和群组
	检查权限 
	cd..     
	ll | grep ftp
	设置755权限
	sudo chmod 755 ftpfile/
	设置密码
	sudo passwd ftpuser
	user123123(最新密码)
	去ftpfile文件下创建index.html 并写入this is a ftpfile
	
	   3>默认ftp服务器 
	whereis vsftpd
	让ftp服务器指向ftpfile文件夹并设置用户
	sudo vi /etc/vsftpd/vsftpd.conf
	搜索 ?banner
	启动并修改成功登陆欢迎语
	并在下一行追加
	local_root=/ftpfile
	anon_root=/ftpfile (可以忽略)
	use_localtime=yes
	
	搜索 ?chroot_list
	启用  
	chroot_local_user=YES #关键  不启用时无法登陆
	chroot_list_enable=YES
	chroot_list_file=/etc/vsftpd/chroot_list
	
	(如果使用/ 搜索,先按ESC,然后直接按/ )
	
	搜索 /anon
	关闭匿名访问 anonymous_enable=NO
	
	搜索 /tcp
	在一行增加(为了配合设置严格的防火墙)
	pasv_min_port=61001
	pasv_max_port=62000
	       并在iptables 添加端口限制
	       重启防火墙 sudo service iptables restart
	
	保存关闭前复制出 /etc/vsftpd/chroot_list 路径
	进入/etc/vsftpd/,并创建chroot_list文件,填入ftpuser
	    
	sudo vi /etc/selinux/config 修改SELINUX=disabled
	sudo setsebool -P ftp_home_dir=1
	sudo setsebool -P tftp_home_dir=1(好像需要执行这一条)
	reboot 重启
	
	启动ftp服务器  /usr/sbin/vsftpd & 
	重启ftp服务器 service vsftpd restart 
	1、若出现读取conf配置500错误
	ll /etc/vsftpd/vsftpd.conf
	该文件所属root用户,所以需要切换为root用户并重新执行启动ftp服务器
	2、如果用户登录出现331,检查配置都是正确时,这里的 vi /etc/vsftpd/vsftpd.conf
	好像不能有中文注释,去掉后重启服务
	查看是否启动 pgrep vsftpd
	关闭ftp服务器 pkill vsftpd
	//更多配置见《Web-vsftpd-ftp服务器配置说明-CentOS-Linux》
	 《Web-vsftpd配置文件详解详解-ftp服务器-CentOS-Linux》

  
7、Nginx安装
	Nginx(来自俄罗斯)是一款轻量级的Web服务器(可直接运行PHP),
	也是一款反向代理服务器	(请求转发) 
作用:
	1>Nginx可运行Rails和PHP程序
	2>作为HTTP反向代理服务器
	3>作为负载均衡服务器
	4>作为邮件代理服务器
	5>帮助前端实现动静分离
特点:
	高稳定、高性能、模块化结构、支持热部署、
	资源占用少、功能丰富
安装步骤:
	0> 直接执行 nginx安装依赖命令
	1> 安装gcc 
	yum install gcc
	gcc -v 查看版本,查看系统是否已安装
	--可能是 yum install gcc-C++

2> 安装pcre 
	yum install pcre-devel
3> 安装zlib
	yum install zlib zlib-devel
4> 安装openssl (如果需要支持ssl)
	yum install openssl openss-devel
	以上综合命令
	nginx安装依赖命令
	yum -y install gcc zlib zlib-devel pcre-devel openssl openssl-devel 
5> 下载源码包,选择稳定版本,解压安装
	wget http://192.168.1.105:81/linux-nginx-1.10.2.tar.gz
	1> 解压后进入nginx目录 执行 ./configure 
		a> 也可在指定安装目录,增加参数 --prefix=/usr/nginx
		b> 若不指定路径,可通过whereis nginx 进行查询
		c> 默认安装在/usr/local/nginx
	2> 执行make
	3> 执行make install

Nginx常用命令
	查看安装路径
	whereis nginx
	测试配置文件是否正确
	安装路径下的 /nginx/sbin/nginx -t
	启动命令
	安装路径下的/nginx/sbin/nginx
	或者进入/sbin目录 执行 sudo ./nginx
	执行查看进程命令然后访问80端口验证是否成功
	停止命令
	安装路径下的 /nginx/sbin/nginx -s stop
	或者是 nginx -s quit
	重启命令
	安装路径下的 /nginx/sbin/nginx -s reload
	查看进程命令
	ps -ef | grep nginx 
	或
	ps aux | grep nginx
	平滑重启
	kill -HUP {Nginx主进程号(即查看进程命令查到的PID)}
	--假如有新的配置文件,
	--新的配置会在给已经连接的用户返回数据后生效
	--假如新的配置文件有错误,nginx会继续使用旧的配置文件
增加防火墙访问权限
	1> sudo vim /etc/sysconfig/iptables
	2> -A INPUT -p tcp -m state --state New -m tcp --dport 80 -j ACCEPT
	3> 保存并重启防火墙 sudo service iptables restart
Nginx虚拟域名配置及测试验证
	本地测试环境注意配置host
	--Linux sudo vi /etc/hosts
	追加 127.0.0.1 mm.jiangjiesheng.cn
	--Window 
	C:\Windows\System32\drivers\etc
	主域名 全部定为 mm.jiangjiesheng.cn
配置步骤
	1>  在/usr/local/nginx/conf/ 目录中新建vhost文件夹
	即: /usr/local/nginx/conf/vhost
	2>编辑 sudo vi /usr/local/nginx/conf/nginx.conf
	在 #another virtual host using mix ...
	增加 include vhost/*.conf;      --加分号
	保存退出
	3> 本地测试添加虚拟域名测试
	sudo vi /etc/hosts
	192.168.134.134 mm.jiangjiesheng.cn
	192.168.134.134 image.mm.jiangjiesheng.cn
	192.168.134.134 s.mm.jiangjiesheng.cn  --前端js css
	//已将192.168.134.134 改成127.0.0.1进行测试

3> 创建域名转发配置
 	cd vhost
	(whereis nginx --安装目录下,即 /usr/local/nginx/conf/vhost )
	sudo vi mm.gestruectrl.com.conf

	server {
	    default_type 'text/html';
	    charset utf-8;
	    listen 80;
	    autoindex on;
	    server_name mm.jiangjiesheng.cn;
	    access_log /usr/local/nginx/logs/access.log combined;
	    index index.html index.htm index.jsp index.php;
	    #error_page 404 /404.html;
	    if ( $query_string ~* ".*[\;'\<\>].*" ){
	        return 404;
	    }
	
	    location ~ /(mmall_fe|mmall_admin_fe)/dist/view/* {
	        deny all;
	    }
	
	    location / { 
	        proxy_pass http://127.0.0.1:8080;      #转发到tomcat服务器
	        add_header Access-Control-Allow-Origin *;
	    }
	}

	保存
	whereis nginx
	cd 复制如上安装目录
	sbin/nginx -s reload   一定要加 -s reload
	
	访问 mm.jiangjiesheng.cn 验证配置是否成功
	保证tomcat 已启动
	虚拟机中运行的系统好像不太好在window中测试域名转发功能!!!
	通过wget mm.jiangjiesheng.cn 下载首页
	cat index.html,从源码上检查是不是tomcat的首页
	---> 此次验证配置成功
	
	继续创建转发配置
	sudo vi image.mm.jiangjiesheng.cn.conf   一定要加 .conf 

	server {
	    listen 80;
	    autoindex off;
	    server_name image.mm.jiangjiesheng.cn;
	    access_log /usr/local/nginx/logs/access.log combined;
	    index index.html index.htm index.jsp index.php;
	    #error_page 404 /404.html;
	    if ( $query_string ~* ".*[\;'\<\>].*" ){
	        return 404;
	    }
	
	    location ~ /(mmall_fe|mmall_admin_fe)/dist/view/* {
	        deny all;
	    }
	
	    location / {
	        root /ftpfile/; #指向路径
	        add_header Access-Control-Allow-Origin *;
	    }
	}

	保存
	cd ..
	cd ..
	cd sbin/
	sudo ./nginx -s reload   一定要加 -s reload
	或者直接  /usr/local/nginx/sbin/nginx -s reload  一定要加 -s reload
	测试
	wget image.mm.jiangjiesheng.cn/index.html 
	cat index.html 
	This is a ftp file
	---> 此次验证配置成功
	
	//TODO 办公电脑从这里开始
	继续创建转发配置
	sudo vi s.mm.jiangjiesheng.cn.conf   一定要加 .conf 
	server {
	    listen 80;
	    autoindex off; #注意这里设置关闭,禁止直接列出文件列表
	    server_name s.mm.jiangjiesheng.cn;
	    access_log /usr/local/nginx/logs/access.log combined;
	    index index.html index.htm index.jsp index.php;
	    if ( $query_string ~* ".*[\;'\<\>].*" ){
	        return 404;
	    }
	
	    location ~ /(mmall_fe|mmall_admin_fe)/dist/view/* {
	        deny all;
	    }
	
	    location / {
	        root /product/front/;
	        add_header Access-Control-Allow-Origin *;
	    }
	}
	创建 /product/front/ 文件夹
	继续重新加载配置验证
	---> 此次验证配置成功

4> 启动(重启)验证
	启动: ${nginx}/sbin/nginx
	重启: ${nginx}/sbin/nginx -restart
	--${nginx}默认是 /usr/local/nginx
5> 访问验证(如果部署在虚拟机中,注意使用wget测试)
	mm.jiangjiesheng.cn
	image.mm.jiangjiesheng.cn
	s.mm.jiangjiesheng.cn
	
8、MySQL安装和配置
	账户root root,admin admin 
	用户配置、权限配置、新建database
1 安装
	具体安装过程见
	 《数据库-通过yum在CentOS7 64位下安装MySQL5.7.20的过程记录》
	线上地址://tech.jiangjiesheng.cn/java/138.html
	务必使用 《数据库-通过yum在CentOS7 64位下安装MySQL5.7.20的过程记录》
	中的安装过程安装,并且把默认版本5.6改成5.7,出错时直接执行步骤8.
	rpm -qa | grep mysql-server 确定是否已安装mysql-server
	//CentOS 7+ 提示没有可用软件包 mysql-server。错误:无须任何处理
	wget http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm
	rpm -ivh mysql-community-release-el7-5.noarch.rpm 
	ls -1 /etc/yum.repos.d/mysql-community* 
	yum -y install mysql-server
	默认配置文件在/etc/my.cnf
2 字符集配置
	vim /etc/my.cnf
	在 [mysqld]节点上添加
	default-character-set=utf8 
	#在 CentOS 7 上启动会有错误(好像又是需要在7以上使用上面的)
	character-set-server=utf8

3 自启动配置
	1> 执行sudo chkconfig mysqld on
	2> 执行sudo chkconfig --list mysqld (新版无效)
	(如果2-5位为on表示成功 CentOS7 执行无效)
4 防火墙配置
	1> sudo vi /etc/sysconfig/iptables
	2> -A INPUT -p tcp -m tcp --dport 3306 -j ACCEPT
	3> 保存 
	4> 重启防火墙 sudo service iptables restart
5 数据库初始化设置和访问权限配置
	1> 查看目前mysql的用户(可能需要先自行步骤2>)
	select user,host,password from mysql.user;
	#Password 改成 authentication_string (新版)
	---即 select user,host,authentication_string from mysql.user;
	
	2> 修改root密码
	set password for root@localhost=password('newpassword');  #非1旁边的引号
	set password for root@127.0.0.1=password('newpassword');
	3> 删除匿名用户
	查看是否有匿名用户
	select user,host from mysql,user;
	删除匿名用户
	delete from mysql.user where user='';
	刷新使生效(关键)
	flush privileges;
	4> 插入mysql新用户(新版不支持直接插入用户,通过步骤 5>和 6>完成)
	insert into mysql.user(Host,User,Password)
	values("localhost","yourusername",password("yourpassword"));
	Password 改成 authentication_string (新版)

5.7版本添加新用户
	GRANT USAGE ON *.* TO 'root'@'127.0.0.1' IDENTIFIED BY 'yourpassword' 
	WITH GRANT OPTION;
	
	刷新使生效(关键)
	flush privileges;
	5> 创建database
	CREATE DATABASE `mmall` DEFAULT CHARACTER SET utf8 COLLATE 
	utf8_general_ci;  #这里又是1旁边的引号
	6> 本地用于赋予所有权限
	grant all privileges on mmall.* to yourusername@localhost identified by
	'yourpassword';
	---即 grant all privileges on mmall.* to admin@localhost identified by 'admin';
	刷新使生效(关键)
	flush privileges;
	7> 给账号开通外网所有权限
	grant all privileges on mmall.* to yourusername@'%' identified by 'yourpassword'
	---即 grant all privileges on mmall.* to admin@'%' identified by 'admin';
	也可根据实际需要设置权限(指定命令、表、ip)
	grant select,insert,update on mmall.* to yourusername@'192.11.11.11'
	identified by 'yourpassword'
	刷新使生效(关键)
	flush privileges;
	特别注意:
	阿里云服务器开通时可能默认开通了安全组(阿里云控制台中设置),安全组
	中需要设置对外网开通指定端口访问
	8> 使用navicat工具连接测试(默认端口3306)
6 常用命令
	1> 启动 sudo service mysqld start  centOS7: /bin/systemctl start mysqld.service
	-- sudo service mysqld restart (centos最新)
	2> 关闭 sudo service mysqld stop
	3> 重启 sudo service mysqld restart (使用这个来启动,避免错误)
	4> 登录 mysql -uusername -h xxxhost -P 3306 -ppassword
	其他相关命名见《数据库-MySQL 数据基本命令及安装配置方法》
7 其他介绍
	数据库用户身份
	dql  -- select
	dml -- insert update delete
	ddl  -- create table、create view
	dcl  -- grant

9、git安装
	1> 下载 wget https://github.com/git/git/archive/v2.8.0.tar.gz
	2> 安装依赖
	sudo yum -y install zlib-devel openssl-devel cpio expat-devel gettext-devel curl-devel 
	perl-ExtUtils-CBuilder perl-ExtUtils-MakeMaker (先复制出来去掉换行符)
	//TODO 安装?
	解压v2.8.0.tar.gz,进入解压目录,
	编译 sudo make prefix=/usr/local all
	安装 sudo make prefix=/usr/local install
	3> git基础配置(Windows在Git Bush中操作(命令相同) 桌面空白处右击)
	a> 配置用户名(添加时会引用)
	git config --global user.name "jiangjiesheng"
	b> 配置邮箱(添加时会引用)
	git config --global user.email "dev@jiangjiesheng.cn"
	c> 其他配置
	git config --global merge.tool "kdiff3"
	(已安装KDiff3时可执行)
	git config --global core.autocrlf false
	(让git忽略Windows和Unix换行符转换)
	d> 编码配置
	git config --global gui.encoding utf-8
	(避免git gui中的中文乱码)
	git config --global core.quotepath off
	(避免git status显示的中文文件名乱码)
	Windows还需要配置
	# git config --global core.ignorecase false
	 e> git ssh key pair配置
	ssh-keygen -t rsa -C 'dev@jiangjiesheng.cn'
	一直回车,不输入密码,生成ssh key pair
	ssh-add ~/.ssh/id_rsa
	cat ~/.ssh/id_rsa.pub
	注:ssh-add ~/.ssh/id_rsa可能会出现Could not open a connection to your 
	authenticaciton agent,解决:
	先执行 eval `ssh-agent` (1旁边的引号) 
	ssh-add ~/.ssh/id_rsa
	ssh-add -l
	复制公钥内容,到oschina的gitlab中,在右上角-->个人资料菜单-->修改资料
	-->SSH公钥配置-->粘贴保存。
	f> git验证
	git --version命令
	g> git常用命令
	切换分支 git checkout 分支名
	拉取 git pull
	提交 git push
	 配置好git后备份系统 选pc版

二、表结构

	1> 唯一索引 保证数据的唯一性 
	UNIQUE KEY `order_no_index` (`order_no`) USING BTREE
	2> 单索引和组合索引,使查询更加快捷
	 KEY `order_no_index` (`order_no`) USING BTREE,
	 KEY `order_no_user_id_index` (`user_id`,`order_no`) USING BTREE
	3> 时间戳(用于方便查业务问题)
	  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
	  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
	//类型选择 datetime,不要使用date,因为要看具体的时间点

三、项目的初始化
	1> 数据库初始化
	2> IDEA 15
	3> maven创建web项目并验证
		File --> New --> Project --> Maven --> 勾选Create from archetype --> 选择 org.apache.maven.archetype.maven-archetype-webapp -->GroupId 填com.jianjiesheng, Artfacitid 填mmall --> next --> Project name 填mmall 并选择路径 --> Finish --> 自动创建maven项目
		a> 在main文件夹下新建java文件夹,并右击java --> Mark Directory As --> Sources Root 
		     在main文件夹下新建test文件夹,在test文件夹下创建java文件夹,并右击java --> Mark 
		Directory As -->Test Sources Root
		b> 运行
		Navigate --> Tool Windows --> Maven Projects --> Liftcycle -->  点击install生成war包
		-->Run --> Edit Configurations --> Tomcat Server --> 配置tomcat路径 -->
		 Deployment选择Artifact--选择war包(或者external source 选择项目Target文件下的
		xxx.war包)
		//TODO 这里后期不删除 问题1
		办公电脑还要继续安装windows下的git
		安装好git后直接从git上克隆下来 然后切换到分支v1.0
		# git remote add origin git@gitee.com:jiangjiesheng/mmall.git 
		使用克隆哪去代码
		git checkout v1.0
		办公电脑提交后 ,pc怎么更新?尝试借助idea 的Git工具
	4> Git初始化
		由于是在windows环境下开发,所有还要安装windows版git,参照步骤二,第9条
		操作
		注:IEDA直接执行git相关指令步骤二,第9条,3> 中的步骤a b c d 
		否则git pull 时提示
		The authenticity of host 'gitee.com (120.55.226.24)' can't be established.
		ECDSA key fingerprint is 
		SHA256:FQGC9Kn/eye1W8icdBgrQp+KkGYoFgbVr17bmjey0Wc.
		
		
		1> 首先进入getee --> 右上角 --> +号 --> 新建项目--> 添加项目名 --> 语言选Java --> 
		开源许可证选择Apache V2 License --> 是否公开改为私有 --> 其他默认 --> 创建
		2> 回到IEDA --> 左下角窗口 --> Terminal --> touch README.md --> 
		打开并输入mmall保存 --> 
		(注意windows下的Terminal不支持Linux指令:使用Git Bash(支持TAB,完全同Linux
		用法):
		-->  cd /d/   
		-->  cd workspace/idea/mmall
		 --> pwd
		)
		
		touch .gitignore --> 输入
		*.class
		#package file
		*.war
		*.ear
		#kdiff3 ignore
		*.orig
		#maven ignore
		target/
		#eclipse ignore
		.settings/
		.project
		.classpath
		#idea ignore
		.idea/
		/idea/
		*.ipr
		*.iml
		*.iws
		#temp file
		*.log
		*.cache
		*.diff
		*.patch
		*.tmp
		# system ignore
		.DS_Store
		Thumbs.db
		
		-->保存 --> git init --> git status --> git add .  --> git status -->
		 git comit -am 'first commit init project'  --> 此时保存到本地仓库 --> 
		连接远程仓库 (先去gitee-“克隆/下载”,复制出ssh地址)--> 
		git remote add origin git@gitee.com:jiangjiesheng/mmall.git --> 
		查看分支 --> git branch --> 准备提交 --> 先拉取 --> git pull --> 开始提交 -->
		 git push -u -f origin master (加-f 第一次强制覆盖远程仓库)--> 去getee刷新 --> 
		查看本地分支 --> git branch (结果为 * master)--> 查看远程分支 -->
		git branch -r  (结果为 origin/master) --> 在origin/master的基础上创建v1.0分支 --> 
		git checkout -b v1.0 origin/master  --> 检查当前分支 --> git branch --> 
		将当前分支推送到远程 --> git push origin HEAD -u --> 去getee刷新 --> 
		分支中出现v1.0
		
		
		另一台电脑拉取:
		 在一个项目目录下右击打开Git Bash,执行克隆命令,
		注意会自动创建项目工程文件夹,所以不需要自己先创建工程文件夹
		git clone git@gitee.com:jiangjiesheng/mmall.git 
		然后用IDE工具打开项目(open)
		git status
		提示在主分支上on branch master
		git checkout v1.0 切换分支(本地没有分支会创建)
		
		更新远程到本地
		git pull 
		//分支开发 主干发布 (非必须)
		
		其他git相关指令 
		git 本地仓库和远程仓库及本地分支和远程分支
		http://www.cnblogs.com/ShaYeBlog/p/5576610.html
		GIT - 基本概念(分支, 差异, 合并)
		http://blog.csdn.net/seaee/article/details/51568261 
		Git 忽略一些文件不加入版本控制
		http://www.jianshu.com/p/1a0e282026a5 
		
	5> Maven的pom文件配置
		粘贴pom文本,执行Maven Project面板下的package,开始自动下载包
		
		mybatis-generator-maven-plugin 1.3.2 不能下载
		修改pom文件右上角不出现同步提示:
		看左下角英文提示,点击,弹出Event Log 面板 这里有提示更新选择 -->
		选择 Enable Auto-Import
		或者右击pom.xml --> Maven --> Reimport
		另外配置File > Setting > 搜索Maven > Maven home directory > 选择自己手动安装的
		 > User settings file 勾选Override (已设置阿里云的源)
		
		某个库的相关pom信息 搜索 http://search.maven.org/
	
	6> 项目结构初始化
		a> 在java文件夹下创建包
		com.mmall.controller
		com.mmall.dao
		com.mmall.service
		com.mmall.util
		com.mmall.vo  (value object 或者view object 最终用于返回的)
		复杂项目还可以添加bo(business object)--这里暂时不添加
		com.mmall.pojo (简单的数据库对象)
		注:pojo  > vo > controller >前端展示
		也可 pojo >bo > vo > controller >前端展示
		com.mmall.common(常量、公共类)
	
	7> Mybatis三剑客之mybatis-generator配置--由数据库生成dao?
		根据数据库自动生成pojo、dao和对应的xml文件,pojo的字段和db的字段一一对应,dao层是接口和接口实现层,供service调用。xml是dao层接口的实现,即为sql语句。
		1> 首先使用mybatis-generator这些文件
		安装mybatis-generator(pom.xml中配置)
		复制generatorConfig.xml到resource
		http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd报红,
		鼠标放上去,按提示Fetch external resource,即可
		按照generatorConfig.xml中的配置,在resource文件夹同级目录下创建
		datasource.properties,并添加数据库连接信息 db.driverLocation、
		db.driverClassName、db.url db.username、db.password
		特别注意:
		db.driverLocation= D:/workspace/idea/mmall/src/main/webapp/lib/mysql-connector-java-5.1.6-bin.jar
		# ./src/main/resources/webapp/lib/mysql-connector-java-5.1.6-bin.jar 
		#这是参考generatorConfig.xml的写法 但是实测无效
		#测试要使用绝对路径 到时在linux中要换成pwd的路径
		注:重新使用admin用户插入数据库会失败,要先去创建数据库 
		CREATE DATABASE `mmall` DEFAULT CHARACTER SET utf8 COLLATE 
		utf8_general_ci; 
		 然后最好走一下赋予执行权限和外网访问权限的语句
		然后在Navicat中刷新后,选中mmall后执行sql,一定要先选中
		2> 使用这些配置文件生成mapper中的xml和dao层
		在Maven Project面板中 > plugins > mybatis generator > 双击
		(整个流程:先手动写好sql在数据库中执行,或者在直接在navicat创建表,
		然后再通过mybatis-generator自动生成mapper中的xml和dao层)
		
		如果是提示:
		mybatis-generator-maven-plugin:1.3.2:generate failed: 
		Cannot resolve classpath entry: ******/mysql-connector-java-5.1.6.jar 
		按步骤1> 中的特别注意 处理
		思考:
		Hibernate 由dao生成数据库?
		mybatis 由数据库生成dao?
		
		执行成功后,com.mmall.pojo、com.mmall.dao、com.mmall.pojo、
		resources\mappers\ 都生成相应资源
		
		提交到gitee,注意IEAD开发工具上有Git插件,但是别使用,
		使用Terminal 或者 Git Bash (先切换到mmall文件夹下)提交
		
		git add .
		git commit -am "20171029"
		git brance   ---> v1.0 如果不是,git checkout v1.0
		git push origin HEAD -u
		gitee 上刷新,要注意切换到v1.0的分支后查看
		
		修改mappers下xml的语句,create_time 和 update_time 的values 改成now(),
		注意insert 中 create_time 和 update_time 都改成now(), update语句中create_time默认,update_time改成now().
		 		
		提交到gitee
	
	8>  Mybatis三剑客之mybatis-plugin安装--mappers-xml与dao关联
		mybatis-plugin安装后在dao层和mappers文件打开后的左侧显示绿色箭头,
		dao层方法与mappers层方法关联起来。
		安装:
		File > Settings > Plugins > Browse Repositories > 搜索 mybatis plugin 无结果
		后期重新研究安装http://www.cnblogs.com/lyh421/p/7098898.html 版本 2.64
		另个版本:idea版本15.0.2
		下载mybatis_plus_2.62_5014.zip,File > Settings > Plugins > Install plugin from disk
	
	9> Mybatis三剑客之mybatis-pagehelper安装--分页插件
		开源 https://github.com/pagehelper/Mybatis-PageHelper
		安装mybatis-pagehelper(pom.xml中配置)
	
	
	10> 
		5个官方示例项目
		http://projects.spring.io/spring-framework/
		https://github.com/spring-projects/spring-mvc-showcase(spring配置demo)
		https://github.com/spring-projects/spring-petclinic(spring配置demo)
		https://github.com/spring-projects/greenhouse
		https://github.com/spring-projects/spring-boot
	
	11>  Spring、SpringMVC配置
		resources/applicationContext.xml
		resources/applicationContext-datasource.xml
		resources/datasource.properties
		resources/logback.xml
		resources/mmall.properties (ftp连接)
		WEB-INF/dispatcher-servlet.xml 
	
	12> IDEA设置
		Settings > 搜索compiler > 勾选Make project automatically 
		Settings > 搜索inspections > Spring > Spring Core > Code > Autowiring for Bean Class > 把Error改成Warining
		提交代码
		git status
		git add .
		git commit -am "create config files"
		git push
	
	13 接口调试和保存使用postman 
		FE助手(浏览器插件 > 用于优化显示json)QQ浏览器下免安装,浏览器使用极速模式
		restlet_client (浏览器插件 > 用于测试接口并保存接口)

四、用户模块的开发
1> 功能:登录 用户名验证 注册 忘记密码 
	提交问题答案 重置密码 获取用户信息 
	更新用户信息 退出登录
	     主要技术:横向越权、纵向越权安全漏洞
	 MD5明文加密和salt值
	 Guava缓存的使用
	 高复用服务响应对象的设计思想及抽象封装(ServerReponse.java)

	 Mybatis-plugin使用技巧(前面章节已经学过)
	 session使用
	 相关解释:
	横向越权:攻击者尝试访问与他拥有相同权限的用户的资源
	(插入订单号能查其他用户的订单信息)
	纵向越权:低级别攻击者尝试访问高级别用户的资源
相关接口
	https://gitee.com/jiangjiesheng/mmall/wikis/Home
2> 代码
A> 首先登录的接口
	a> 在controller包下新建portal包用于展示前端业务,并继续新建UserController,
	给整个类添加注解 @Controller @RequestMapping("/user/")
	并新建login方法
	@RequestMapping(value = "login.do",method =RequestMethod.POST)
	@ResponseBody
	public Object login(String username, String password, HttpSession session) {
	   //service --> mybatis --> dao
	   return null;
	}
	b> 在service包下新建IUserService接口,并添加
	ServerResponse login(String username, String password);
	继续在service包下新建impl包,并UserServiceImpl implements IUserService。
	c> 在common包下新增ServerResponse类和ResponseCode类,
	并将Object 缓存ServerResponse
	d> 在dao层的UserMapper 接口中,新增
	 //手动新增 以上是mybatis-generator 自动生成的
	    			int checkUsername(String username);
	 //多个参数要使用Param注解
	    			User selectLogin(@Param("username") String username, 
	@Param("password") String password);
	d> 在UserMapper.xml中新增sql
	  
	
	    
	    
	
	e> 回到UserServiceImpl的实现类,完成login方法。
	注意要给UserServiceImpl添加Service("iUserService")  ,参数名称的原则是接口类名的首字母小写。
	
	f> 在controller中注入iUserService 并完成调用,正常登陆用于接入到session
	//注意在controller的类名上已经添加
	@Controller
	@RequestMapping("/user/")
	-----------------------------------------------------------------------------------------
	    @RequestMapping(value = "login.do", method = RequestMethod.POST)
	    @ResponseBody
	    public ServerResponse login(String username, String password, HttpSession session) {
	        //service --> mybatis --> dao
	        ServerResponse response = iUserService.login(username, password);
	        if (response.isSuccess()) {
	            session.setAttribute(Const.CURRENT_USER, response.getData());
	//Const.CURRENT_USER 为自定义产量类,后期应该和cookie结合,
	//有cookie时也给登录并写入到session,这一过程都统一在拦截器中处理
	        }
	        return response;
	    }

 B> 继续完成退出登录接口
	@RequestMapping(value = "logout.do", method = RequestMethod.POST)
	@ResponseBody
	 public ServerResponse logout(HttpSession session) {
	       session.removeAttribute(Const.CURRENT_USER);
	        return ServerResponse.createBySuccess();
	  }
C> 注册接口...
    public ServerResponse register(User user) {
        return null;
    }
	选中 iUserService.login ,Ctrl T,进入实现类,先写好实现类,IUserService接口,  完成contoller调用,过程反过来。 
D> 校验用户名是否存在接口
	ServerResponse checkValid(String str, String type)
E> 获取用户登录信息的接口
	ServerResponse getUserInfo(HttpSession session)
	 //只从session中获取,没有则表示未登录
F> 获取忘记密码的问题的接口(未登录)
	ServerResponse forgetGetQuestion(String username)
G> 校验忘记密码问题的回答接口(未登录)
	public ServerResponse forgetCheckAnswer(String username,
	String question, String answer)
	 利用Guava(LoadingCache) 编写本地缓存TokenCache
	(回答问题并重置答案时两个接口需要用到token令牌进行检验,
	防止横向越权,直接通过接口操作其他用户数据)
H>  重置密码的接口(未登录)
	ServerResponse forgetResetPassword(String username, 
	String passwordNew, String forgetToken)
I>  登录状态的重置密码的接口
	ServerResponse resetPassword(HttpSession session,
	 String passwordOld, String passwordNew)
J> 更新个人用户信息后的用户信息的接口
	ServerResponse update_infomation(HttpSession session, User user)
	//这里需要注意越权问题,还有username字段禁止更新的问题,
	//userId 和username都要从session中获取,
	//更新email时要判断新的email无其他用户正在使用。
K> 获取用户的详细信息的接口
	ServerResponse get_information(HttpSession session) //注意去掉密码

五、后台管理模块
	在controller包下新建backend包,并新建UserManageController
A> 后台登录的接口
	public ServerResponse login(String username, String password,
HttpSession session)
B> 以后所有的接口验证并保存到postman中 
	测试环境的logback.xml中的日志路径可能需要修改
	提交方式选择form-data
	相关接口 
	https://gitee.com/jiangjiesheng/mmall/wikis/后台_用户接口?parent=接口
	
	特别注意:
	SpringMVC提交参数是为实体时User user,获取字段均为null的处理方案
	1>加上注解@RequestBody User user
	提交时使用json字符串(并指定application/json),jQuery提交时也要注意转成字符串
	2> 使用x-www-form-urlencoded提交,使用form-data时字段为null,
	与添不添加Headers(Content-Type   application/x-www-form-urlencoded)似乎无关
相关接口:
	http://localhost:8080/user/update_information.do
 
--------------第一阶段完成 2017-1110-1555-------------

六、分类管理模块
	功能:后去节点、增加节点、修改名称、获取分类ID、递归子节点ID
	目标:如何设计及封装无限层级的树状数据结构(DB设计:id parent_id)
	    递归算法的设计思想
	    如何处理复杂对象的排重
	    重写hashcode和equal方法
	相关接口:https://gitee.com/jiangjiesheng/mmall/wikis/后台_品类接口?parent=接口
A> 增加分类接口
	在backend包下创建CategoryManageController控制器
	@Controller
	@RequestMapping("/manage/category")
	public class CategoryManageController {
	    	 public ServerResponse addCategory(HttpSession session, 
	String categoryName,
	@RequestParam(value = "parentId", defaultValue = "0") int parentId) {
	        			//注意添加可选时的默认值
	    			}
	}
	创建 public interface ICategoryService
	 public class CategoryServiceImpl implements ICategoryService
	 并完成 public ServerResponse addCategory(String categoryName, Integer parentId)
		的接口方法实现
B> 更新分类名称的接口
	ServerResponse setCategoryName(HttpSession session, Integer categoryId, 
	String categoryName)

C> 查询子节点的分类信息,并且不递归,保持平级的接口
	ServerResponse getChildrenParallelCategory(HttpSession session, @RequestParam(value = "categoryId", defaultValue = "0") Integer categoryId)
D>  查询当前节点的id和递归子节点的id的接口
	ServerResponse getCategoryAndDeepChildrenCategory(HttpSession session, @RequestParam(value = "categoryId", defaultValue = "0") Integer categoryId)

	使用Set排重
	递归算法(这里没有用到尾递归)
	重写Category实体equals 和 hashcode 方法使判断因子都是id
	(可使用快捷键快速完成代码 Mac中快捷键可能是Command + Enter)
	   /**
	     * 重写equals 和 hashcode 使判断因子都是id
	     */
	    @Override
	    public boolean equals(Object o) {
	       if(this ==o) return true;
	        if(o==null || getClass() !=o.getClass()) return true;
	        Category category = (Category) o;
	        return !(id != null ? !id.equals(category.id):category.id!=null);
	    }
	
	    @Override
	    public int hashCode() {
	        return id !=null?id.hashCode():0;
	    }
	验证:在postman中完成接口测试
	注意
	接口参数加上 @RequestParam(value = "categoryId", defaultValue = "0") 时,
	字段大小写是敏感的。这里的categoryId不能写成categoryid
	
	SpringMVC Controller接收中文参数乱码
	除了已有的配置外(https://www.cnblogs.com/alivn/p/4823405.html)
	还需要配置Tomcat服务器
	SpringMVC Controller接收的中文参数乱码
	来自网络的解释:测试有效(https://www.cnblogs.com/esther-qing/p/6425590.html )
	CharacterEncodingFilter只对POST请求有用,GET请求的需要对你运行的tomcat 目录conf/server.xml文件中
	<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
	改为:
	<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" useBodyEncodingForURI="true"/>
	
	这是tomcat的原因造成的,tomcat默认的编码是iso-8859-1。不是大家常用的utf-8。
	换句话说,get请求是对资源的访问,资源我一般不会涉及中文路径(最好不要)。
	不添加导致get中的中心参数读取错误
	post 针对于数据的提交,所以如果是表单,最好用post请求。
	另外jsp中的中文乱码(使用editplus查看是utf8,添加head编码无效,上述设置Tomcat无效)
	在jsp中添加<%@ page language="java"  contentType="text/html; charset=UTF-8" %>
	可解决

七、商品管理
	功能:(前台)产品搜索、动态排序列表、产品详情
	    (后台)商品列表、商品搜索、图片上传、富文本上传、商品详情、商品上下架
	    增加商品、更新商品
	目标:FTP服务的对接、SpringMVC文件上传、流读取Properties配置文件
	抽象POJO、BO、VO对象之间的转换关系及解决思路
	     joda-time快速入门(日期/时间库 在pom.xml中引入)
	静态块、MyBatis-PageHelper高效准确地分页及动态排序
	Mybatis对List遍历的实现方法
	Mybatis对where语句动态拼接的版本演进
	   Pojo、BO、VO:
	     Controller     ---    VO-view object
	      ↑↓
	    Service     ---    BO-business object
	      ↑↓
	     Dao     ---    POJO-Plain Ordinary Java Object
	
	     POJO、VO:
	    Controller & Service    ---   VO-value object
	 				        ↑↓
	    Dao     ---   POJO-Plain Ordinary Java Object
	
接口地址:
	https://gitee.com/jiangjiesheng/mmall/wikis/后台_产品接口?parent=接口
	https://gitee.com/jiangjiesheng/mmall/wikis/门户_产品接口?parent=接口
A> 增加或修改商品接口
	ServerResponse productSave(HttpSession session, Product product)
B> 产品上下架接口
	ServerResponse setSaleStatus(HttpSession session, Integer productId,Integer status)
C> 获取商品详情的接口
	public ServerResponse getDetail(HttpSession session, Integer productId)
	含有配置读取工具(PropertiesUtil.java)
	静态块static{ }(仅会执行一次)优于  普通代码块{ } 优于 构造器代码块
	日期时间转换工具 (DateTimeUtil.java)
D>  获取商品列表的接口
	ServerResponse getList(HttpSession session, @RequestParam(value = "pageNum",
	 defaultValue = "1") int pageNum, @RequestParam(value = "pageSize", 
	 defaultValue = "10") int pageSize)
	含有MyBatis pagehelper  通用分页拦截器(AOP 面向切面,自动拦截,自动修改sql)
	特别注意:pagehelper会在mapper的sql语句后自动添加limit,
	所以mapper语句不能添加分号结束!
	PageHelper.startPage(pageNum, pageSize);
	        List productList = productMapper.selectList();
	        List productDetailVoList = Lists.newArrayList();
	
	        for (Product productItem : productList) {
	            ProductDetailVo productDetailVo = assembleProductDetailVo(productItem);
	            productDetailVoList.add(productDetailVo);
	        }
	//收尾 
	        PageInfo PageResult = new PageInfo(productList);//后期还可以支持添加条件
	        PageResult.setList(productDetailVoList);这个构造器中没有set list集合
 E> 后台商品搜索的接口
	public ServerResponse productSearch(HttpSession session, String productName,
	 Integer productId, @RequestParam(value = "pageNum", defaultValue = "1") int 
	 pageNum, @RequestParam(value = "pageSize", defaultValue = "10") int pageSize)
	
	sql语句where中的判断
	/*或者硬编码 where 1=1 保证拼接的sql不是错误的*/
	        
	            
	                AND name like #{productName}
	            
	            
	                AND id = #{productId}
	            
	        

F> 文件上传
	①public ServerResponse upload(MultipartFile file, HttpServletRequest request)
	②public Map richtextImgUpload(HttpSession session, @RequestParam(value = 
	"upload_file", required = false) MultipartFile file, HttpServletRequest request, 
	HttpServletResponse response)
	包含SpringMVC上传文件配置
	FTP上传文件(FTPUtil.java)
	getServletContext.getRealPath()为null
	http://blog.csdn.net/itguaicai/article/details/42583167
	修改c测试保存的路径:D:/workspace/idea/mmall/target/mmall/WEB-INF/classes/upload
G> 前台的ProductController
       前台获取商品详情的接口
	public ServerResponse detail(Integer productId) 
H> 用户搜索商品接口(返回list)
	ServerResponse list(@RequestParam(value = "keyword", required = false) 
	String keyword,  @RequestParam(value = "categoryId", required = false) Integer 
	categoryId,@RequestParam(value = "pageNum", defaultValue = "1") int pageNum,
	 @RequestParam(value = "pageSize", defaultValue = "10") int 
	pageSize,@RequestParam(value = "orderBy", defaultValue = "") String orderBy)
	这里有mapper中遍历集合
	 <select id="selectByNameAndCategoryIds" parameterType="map" resultMap="BaseResultMap">
	        SELECT
	        <include refid="Base_Column_List"/>
	        from mmall_product
	 where status = 1
	        <if test="productName!=null">
	            and name like #{productName}
	        </if>
	        <if test="productIdList!=null">
	            and category_id in
	            <foreach collection="productIdList" item="item" index="index" open="(" separator="," 
	close=")">
	                #{item}
	            </foreach>
	        </if>
	    </select>

	前台和后台商品模块接口测试
	https://gitee.com/jiangjiesheng/mmall/wikis/后台_产品接口?parent=接口
	https://gitee.com/jiangjiesheng/mmall/wikis/门户_产品接口?parent=接口

八、购物车模块
	功能:加入商品 更新商品数 查询商品数 移除商品 单选/取消 全选/取消 购物车列表
	目标:购物车模块的设计思想
	   如何封装一个高复用购物车核心方法
	   解决浮点型在商业运算中丢失精度的问题
	相关接口:https://gitee.com/jiangjiesheng/mmall/wikis/门户_购物车接口?parent=接口
A> 购物车中添加商品的接口
	public ServerResponse add(HttpSession session, Integer count, Integer productId);
	这里需要封装vo层(ValueObject or ViewObject)的CartProductVo层和
	CartVo层(CartVo是CartProductVo 的集合)
	计算精度的问题(BigDecimal)
	在单元测试包下新建com.mmall.test
	    @Test
	    public void test1() {//单元测试中的返回值一定是void
	        System.out.println(0.05 + 0.01);//0.060000000000000005
	        System.out.println(1.0 - 0.42);//0.5800000000000001
	        System.out.println(4.015 * 100);//401.49999999999994
	        System.out.println(123.3 / 100);//1.2329999999999999
	    }
	@Test
	    public void test2() {
	        BigDecimal b1 =new BigDecimal(0.05);
	        BigDecimal b2 =new BigDecimal(0.01);
	        System.out.println(b1.add(b2));
			//0.06000000000000000298372437868010820238851010799407958984375
	    }
	 @Test
	  public void test3() {
	      BigDecimal b1 =new BigDecimal("0.05");
	      BigDecimal b2 =new BigDecimal("0.01");
	       System.out.println(b1.add(b2));// 0.06
	   }
	float 和 double 只能用来做科学计算或工程计算
	在商业计算中要使用BigDecimal的String构造器
	进入BigDecimal类,Ctrl + O 查看所有的方法,
	找到double的构造器(public BigDecimal(double val))这里的注释给出了说明
	开始封装BigDecimal工具类 /util/BigDecimalUtil
	要重点研究CartServiceImpl.getCartVoLimit()这个方法对于后台计算和对VO的处理
B> 更新购物车的接口(以下几个接口都会复用CartServiceImpl.getCartVoLimit()方法)
	ServerResponse<CartVo> update(HttpSession session, Integer count, Integer productId)
C> 在购物车中删除接口
	ServerResponse<CartVo> deleteProduct(HttpSession session, String productIds)
	注意这里可能会删除多个商品,所以productId用逗号拼接成字符串。
	使用Guava将productIds字符串转成List
	List<String> productList = Splitter.on(",").splitToList(productIds);
	        if (CollectionUtils.isEmpty(productList)) {
		return ServerResponse.createByErrorCodeMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(), ResponseCode.ILLEGAL_ARGUMENT.getDesc());
	}
	另外mapper中foreach遍历用法
	<delete id="deleteByUserIdProductIds" parameterType="map">
	        DELETE from mmall_cart
	        where user_id = #{userId}
	        <if test="productIdList != null">
	            and product_id in
	            <foreach collection="productIdList" item="item" index="index" 
	open="(" separator="," close=")">
	                #{item}
	            </foreach>
	        </if>
	    </delete>
D> 查询购物车的接口
 	public ServerResponse<CartVo> list(HttpSession session) ;
E> 设置全选、全反选、单独选,单独反选接口
	ServerResponse<CartVo> selectAll(HttpSession session)
	public ServerResponse<CartVo> unSelectAll(HttpSession session) 
	public ServerResponse<CartVo> select(HttpSession session, Integer productId)
	public ServerResponse<CartVo> unSelect(HttpSession session, Integer productId)
G> 获取购物车中商品的数量的接口
	注意sum(字段)是对值的求和,而count是对行数row的统计
	另外注意字段是空值的情况
	select IFNULL(sum(quantity) ,0) as count from mmall_cart (编译器只提示NULLIF)
	ServerResponse<Integer> getCartProductCount(HttpSession session)

购物车模块接口
https://gitee.com/jiangjiesheng/mmall/wikis/门户_购物车接口?parent=接口


九、收货地址管理
功能:添加地址、删除地址、更新地址、地址列表、地址分页、地址详情
目标:SpringMVC数据绑定中的对象绑定
    MyBatis自动生成主键、配置和使用
    巩固如何避免横向越权漏洞
相关接口:
https://gitee.com/jiangjiesheng/mmall/wikis/门户_收货地址接口?parent=接口
A> 增加地址的接口
	使用MyBatis往MySQL数据库中插入一条记录后,返回该条记录的自增主键值:
	useGeneratedKeys="true" keyProperty="id" ,这样就能getxxxId()获取,
	否则insert之后只能返回成功insert的条数
	public ServerResponse add(HttpSession session, Shipping shipping)
B> 删除地址的接口
	注意横向越权:插入条件加入user_id
	int deleteByShippingIdUserId(@Param("userId") Integer userId, 
	@Param("shippingId") Integer shippingId);
	 public ServerResponse add(HttpSession session, Integer shippingId)
C> 更新地址的接口
	注意横向越权:
	shipping对象的userid要使用session中的userid来set进来
	并新增一个mapper方法,update条件加入user_id
	注意update中的set user_id 要去掉。
	parameterType="com.mmall.pojo.Shipping"
	public ServerResponse update(HttpSession session, Shipping shipping)
D> 查询地址的详情接口
	注意横向越权:
	public ServerResponse select(HttpSession session, Integer shippingId)
E> 地址分页接口
	 public ServerResponse list(HttpSession session, @RequestParam(value =
	 "pageNum", defaultValue = "1") int pageNum, @RequestParam(value = "pageSize", 
	 defaultValue = "10") int pageSize)
收货地址模块
https://gitee.com/jiangjiesheng/mmall/wikis/门户_收货地址接口?parent=接口

十、支付模块开发-前期介绍和准备
功能:支付宝对接 支付回调 查询支付状态
目标:熟悉支付宝对接的核心文档,调通支付宝支付功能官网demo
    解析支付SDK对接源码
    RSA1和RSA2验证签名及加解密
    避免支付宝重复通知和数据校验
    natapp外网穿透和tomcat remote debug
    生成二维码,并持久化到图片服务器
    
相关接口:https://gitee.com/jiangjiesheng/mmall/wikis/门户_支付接口?parent=接口

重要的官网文档:
	1> 沙箱登录:
	https://openhome.alipay.com/platform/home.htm
	2> 沙箱使用说明
	https://docs.open.alipay.com/200/105310
	3> 如何使用沙箱环境
	https://docs.open.alipay.com/200/105311/
	4> 当面付产品介绍
	 https://docs.alipay.com/mini/introduce/pay
	5> 扫码支付接入指引
	 https://docs.open.alipay.com/194/106078
	6> 当面付快速接入
	 https://docs.open.alipay.com/194/105170
	7> 当面付接入必读
	 https://docs.open.alipay.com/194/105322
	8> 当面付进阶功能
	  https://docs.open.alipay.com/194/105190
	9> 当面付的异步通知-仅用于扫码支付
	  https://docs.open.alipay.com/194/103296
	10> 当面付SDK&DEMO
	  https://docs.open.alipay.com/194/105201
	11> 服务端SDK
	  https://docs.open.alipay.com/54/103419 
	12> 生成RSA密钥(下载工具)
	  https://docs.open.alipay.com/291/105971
	13> 线上创建应用说明
	  https://docs.open.alipay.com/200/105310
支付宝扫码支付重要字段
	关键入参:
	out_trade_no 商户订单号,需要保证不重复
	total_amount 订单金额
	subject 订单标题
	store_id 商户门店编号
	timeout_express 交易超时时间
	关键出参
	qr_code 订单二维码图片地址
	回调验证
	 签名、金额、订单号、订单状态、交易状态、商户id
	回调具有幂等性并过滤掉重复的通知
	一定要验证并确保可接受的通知是支付宝发出的
	回调请求的返回(success)
	支付宝扫码支付对接技巧
	a>路由器设置开放本地到外网(不推荐)
	b>外网远程debug:
	1、保持远端代码版本和本地代码保持一致
	2、及时关闭开放的debug端口(tomcat具体配置见百度,
	并将端口开放到防火墙)
	c>内网穿透
	ngrok、natapp、花生壳

支付宝沙箱环境登录
	https://sandbox.alipaydev.com/sms/receive.htm
	沙箱应用 
	https://sandbox.alipaydev.com/user/accountDetails.htm(可下载Android版本demo)
	沙箱账号(已注册自研开发者,含有商家和买家)
	https://openhome.alipay.com/platform/appDaily.htm?tab=account
	买家账号sfntqd8490@sandbox.com
	登录密码111111
	支付密码111111
	商家账号tipxhp1149@sandbox.com
	商户UID2088102174677656
	登录密码111111
	支付宝回调地址
	http://mm.jiangjiesheng.cn/order/alipay_callback.do 已在mmall.properties中配置
	(window上测试的话,可能要换一下了)

当面付demo和sdk
	https://docs.open.alipay.com/54/104506/
	https://docs.open.alipay.com/194/105201/

调通当面付官方demo注意事项
	首先完成相关公钥、私钥、ppid等等信息,生成RSA密钥(需要下载工具  
	https://docs.open.alipay.com/291/105971)


	Configs.init("zfbinfo.properties"); 读取zfbinfo.properties 失败,找不到文件
	新建一个文件夹(不确定是包还是文件夹),例如resource,将放入zfbinfo.properties,
	File-->Project Structure-->Project Settings-->Modules-->Sources-->选中resource,点
	击"Resource"(带有饼形图标)即可

支付测试
	运行Main类后,支付宝在返回的信息中含有qr_code字段,复制出来直接生成二维码,
	使用沙箱环境中的支付宝应用并登陆买家账号扫码下单,支付成功后,可切换到商家支
	付宝账号查看交易订单

继续尝试运行demo的web站点效果
	配置tomcat时选择Deployment时无Artifacts,应该是demo在eclipse环境下创建的 
	处理:File-->Project Structure-->Project Settings-->Facets-->+号-->Web-->全中-->apply
	-->Artifacts-->Web Application:Exploded-->From Modules-->选中-->apply
	--->把WebRoot目录下的文件复制到Web(Web在上述操作后会自动生成)
	--->重新配置tomcat发布的Deployment,选择Artifacts--->选中war-->(正式环境下应该需要
	重新配置lib-->直接右击设置lib,或者File-->Project Structure-->Project Settings-->
	Libraries-->点击右边的第一个+号选中lib,另外通过mudule-->Dependences-->+号-->jars
	也行)-->重启tomcat-->打开web站点成功

	打开Web首页,选择“当面付2.0 二维码支付”,输入测试数据并生成持久化二维码,沙箱扫
	码并支付。并通过NATAPP远程调试支付宝回调(好像仅仅演示)

正式开始把支付集成到项目中
	拷贝zfbinfo.properties和4个支付宝SDK
	在WEB-INF下创建lib文件夹粘贴sdk,其依赖的jar包通过pom加载进来,然后将支付宝SDK的
	jar添加到项目library引用中,并运行Main类测试,看看有没有问题

十一、支付模块开发-业务层开发
首先在controller/portal中创建OrderController
A> 支付宝预下单、生成当面付二维码接口
	public ServerResponse pay(HttpSession session, Long orderNo, HttpServletRequest 
	request) //含有二维码生成后持久化到FTP图片服务器(qrimg专用文件夹)
B> 支付宝回调接口及支付宝SDK解析
	public Object alipayCallback(HttpServletRequest request)
	当面付异步通知-仅用于扫码支付 https://docs.open.alipay.com/194/103296

异步返回结果的验签:
	(验证回调的正确性,是不是支付宝发的,并且要避免重复通知)

        https://docs.open.alipay.com/194/103296
        Ctrl Shift T --> Search AlipaySignature
        Ctrl o ,继续输入rsaCheckV2 (打开重载的第一个)--> 追加使用StringBuffer,并发时线程安全(但是效率低)
        支付宝demo默认的验证签名的rsaCheckContent中的类型是SHA1WithRSA
         (java.security.Signature signature = java.security.Signature.getInstance(AlipayConstants.SIGN_ALGORITHMS); )
        而不是RSA2
        继续看rsaCheckV2重载的第二个方法  rsaCheckV2(Map params, String publicKey,String charset,String signType)
        可以指定signType签名类型 最终调用的是SHA256WithRSA
        注意 publicKey是支付宝公钥不是商家公钥,沙箱可以看到https://sandbox.alipaydev.com/user/accountDetails.htm
        按照支付宝验签的要求,需要去掉sign和sign_type两个字段,sign字段支付宝在sdk中已经remove,但是sign_type没有去掉,其他的第一至第四步都已经在SDK中处理过
        商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号,并判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额),
         同时需要校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email),
         上述有任何一个验证不通过,则表明本次通知是异常通知,务必忽略。在上述验证通过后商户必须根据支付宝不同类型的业务通知,正确的进行不同的业务处理,并且过滤重复的通知结果数据。
         在支付宝的业务通知中,只有交易通知状态为TRADE_SUCCESS或TRADE_FINISHED时,支付宝才会认定为买家付款成功。
支付宝交易状态说明:
	WAIT_BUYER_PAY 交易创建,等待买家付款
	TRADE_CLOSED 未付款交易超时关闭,或支付完成后全额退款
	TRADE_SUCCESS 交易支付成功
	TRADE_FINISHED  交易结束,不可退款
C>  轮询查订单的支付状态的接口
	public ServerResponse queryOrderPayStatus(HttpSession session, Long orderNo)

十二、订单模块开发
	功能:
	前台:创建订单 商品信息(为预下单准备) 订单列表 订单详情 取消订单
	后台:订单列表 订单搜索 订单详情 订单发货
	目标:
	避免在业务逻辑中横向越权和纵向越权等安全漏洞
	设计实用、安全、扩展性强大的常量、枚举类
	订单号生成规格(集群时需要另外考虑)、订单号严谨性判断
	POJO和VO之间的实际操练
	MyBatis批量插入
相关接口:
	https://gitee.com/jiangjiesheng/mmall/wikis/门户_订单接口?parent=接口
	https://gitee.com/jiangjiesheng/mmall/wikis/后台_订单接口?parent=接口
前台:
	前台接口都写在controller/portal中的OrderController里
A> 创建订单的接口
	public ServerResponse create(HttpSession session, Integer shippingId)
B> 取消订单的接口
	public ServerResponse cancel(HttpSession session, Long orderNo)
C> 获取购物车中产品的接口(购物车中十件选五件,用于展示这五件的详情)
	public ServerResponse getOrderCartProduct(HttpSession session)
D> 订单详情的接口
	public ServerResponse detail(HttpSession session, Long orderNo)
E> 个人中心查看个人订单的接口
	public ServerResponse list(HttpSession session, @RequestParam(value = 
	"pageNum",defaultValue = "1") int pageNum, @RequestParam(value = "pageSize", 
	defaultValue ="10") int pageSize)

后台接口都写在controller/backend中的OrderManageController里

A> 后台查看订单列表的接口
	public ServerResponse orderList(HttpSession session,
               @RequestParam(value = "pageNum", defaultValue = "1") int pageNum,
               @RequestParam(value = "pageSize", defaultValue = "10") int pageSize)
B> 后台查看订单详情的接口
	public ServerResponse orderDetail(HttpSession session, Long orderNo)
C> 后台带分页搜索的接口
	public ServerResponse orderSearch(HttpSession session, Long orderNo,
                 @RequestParam(value = "pageNum", defaultValue = "1") int pageNum,
                 @RequestParam(value = "pageSize", defaultValue = "10") int pageSize)
D> 后台发货的接口
   public ServerResponse orderSendGoods(HttpSession session, Long orderNo)

十三、服务端项目自动化发布
	下载自动化发布脚本,然后根据脚本内容创建git仓库文件夹
	 mkdir -p /developer/git-repository/
	 进入,并克隆gitee中的项目(注意选择SSH协议)git@gitee.com:jiangjiesheng/mmall.git
	 git clone git@gitee.com:jiangjiesheng/mmall.git
	 (如果提示没有权限,加sudo后提示git命令不存在,就把developer文件夹的所有者设置为当前用
	 户(一般是非root用户))
	sudo chown -R xxxx /developer/
	如果是设置给其他用户(xxxx后后一致):
	sudo chown -R xxxx.xxxx /developer/ 
	下载自动发布脚本deploy.sh,并修改git项目名(mmall),修改deploy.sh中的分支为v1.0,修改
	tomcat安装的路径后保存,请增加执行权限 chmod 777 deploy.sh 
	PC虚拟机中的deploy.sh在/home/admin/mylibs 文件夹下...
	// deploy.sh位置已经修改到了 /developer 文件夹下,并改名为 backend-deploy.sh 
	
	(chmod u+x  g+x o+x a+x 777)
	
	Logback日志说明:(相关配置在logback.xml中)
	Linux下日志说明:
	·	由于CentOS系统安装的tomcat在/usr/mylibs/tomcat7/apache-tomcat-7.0.73,其运行相关的日志在/usr/mylibs/tomcat7/apache-tomcat-7.0.73/logs下,
	Windows下的日志说明:
	log的日志最终记录在tomcat服务器所在盘的相应绝对路径下
	windows测试时在C盘:
	/developer/apache-tomcat-7.0.73/logs/mmall.log

结束时间2017-12-12 21:30

	/**
	 * Description:
	 * Author:江节胜
	 * Email:dev@jiangjiesheng.cn
	 * Date: ${DATE}
	 */