课程计划javascript
一、在购物车页面点击【去结算】按钮跳转到订单确认页面。
a) 展现商品列表
b) 配送地址列表
c) 选择支付方式
二、展现订单确认页面以前,应该确认用户身份。
a) 使用拦截器实现。
b) Cookie中取token。
c) 取不到token跳转到登陆页面。
d) 取到token,根据token查询用户信息。
e) 若是没有用户信息,登陆过时跳转到登陆页面。
f) 取到用户信息,放行。
三、提交订单
a) 生成订单。
b) 展现订单提交成功页面。php
taotao-order(pom)
|--taotao-order-interface(jar)
|--taotao-order-service(war)
taotao-ordercss
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.taotao</groupId>
<artifactId>taotao-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>taotao-order</artifactId>
<packaging>pom</packaging>
<modules>
<module>taotao-order-interface</module>
<module>taotao-order-service</module>
</modules>
<dependencies>
<!-- 配置对taotao-common的依赖 -->
<dependency>
<groupId>com.taotao</groupId>
<artifactId>taotao-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 配置Tomcat插件 -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<configuration>
<port>8091</port>
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
</project>
taotao-order-interfacehtml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.taotao</groupId>
<artifactId>taotao-order</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>taotao-order-interface</artifactId>
<dependencies>
<!-- 配置对taotao-manager-pojo的依赖 -->
<dependency>
<groupId>com.taotao</groupId>
<artifactId>taotao-manager-pojo</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
taotao-order-service前端
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.taotao</groupId>
<artifactId>taotao-order</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>taotao-order-service</artifactId>
<packaging>war</packaging>
<dependencies>
<!-- 配置对taotao-manager-dao的依赖 -->
<dependency>
<groupId>com.taotao</groupId>
<artifactId>taotao-manager-dao</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- 配置对taotao-order-interface的依赖:服务层发布服务要经过该接口 -->
<dependency>
<groupId>com.taotao</groupId>
<artifactId>taotao-order-interface</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- 配置对spring的依赖 -->
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<!-- 配置对dubbo的依赖 -->
<!-- dubbo相关 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<!-- 排除对低版本jar包的依赖 -->
<exclusions>
<exclusion>
<artifactId>spring</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>netty</artifactId>
<groupId>org.jboss.netty</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</dependency>
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
</dependency>
</dependencies>
</project>
能够参考taotao-manager整合。java
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>taotao-order-service</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- 初始化spring容器:也即加载spring容器 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/applicationContext*.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
表现层工程处理订单的确认页面
和订单提交后产生的订单号
。
taotao-order-web打包方式war。git
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.taotao</groupId>
<artifactId>taotao-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>taotao-order-web</artifactId>
<packaging>war</packaging>
<dependencies>
<!-- 配置对taotao-common的依赖 -->
<dependency>
<groupId>com.taotao</groupId>
<artifactId>taotao-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- 配置对taotao-order-interface的依赖:表现层调用服务要经过该接口 -->
<dependency>
<groupId>com.taotao</groupId>
<artifactId>taotao-order-interface</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<!-- JSP相关 -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<scope>provided</scope>
</dependency>
<!-- 配置对dubbo的依赖 -->
<!-- dubbo相关 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<!-- 排除对低版本jar包的依赖 -->
<exclusions>
<exclusion>
<artifactId>spring</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>netty</artifactId>
<groupId>org.jboss.netty</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</dependency>
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 配置Tomcat插件 -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<configuration>
<port>8092</port>
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
</project>
能够参考taotao-portal-web整合。github
添加配置资源映射标签
:
在购物车表现层工程中的,有咱们订单确认页面的URL:
/taotao-cart-web/src/main/webapp/WEB-INF/jsp/cart.jspweb
List<TbItem>
,就能够了,可是还须要将
${cart.images[0]}
改成
${cart.image}
请求分析:
请求的url:/order/order-cart
参数:没有参数。
返回值:逻辑视图String(order-cart.jsp),展现订单确认页面。
业务逻辑:
一、首先用户先登陆,从cookie中获取token,根据token调用SSO服务获取登陆的用户信息。
二、从cookie中获取购物车的商品的列表数据。
三、从redis中获取该用户的购物车的商品列表数据。
四、将这二者的数据进行合并,展现商品数据。并清除cookie中的数据。
五、展现配送地址列表,须要根据用户id从数据库中查询收货地址列表,这里暂时使用静态数据。
六、展现支付方式,也须要从数据库中查询支付的方式列表,这里暂时使用静态数据。redis
须要根据用户id查询收货地址列表。
须要查询支付方式。
可是因为这两个都使用的静态数据
,因此服务层不须要编写。
静态数据,作静态页面处理。
业务逻辑:
直接调用其余的服务层的服务便可。(须要添加对应的依赖,并引用服务。)
因为表现层须要调服务层的SSO服务和购物车服务,因此须要在taotao-sso-service和taotao-cart-service工程中发布服务。
在taotao-order-web工程中的pom.xml文件中配置对taotao-sso-interface和taotao-cart-interface的依赖:
<!-- 配置对taotao-sso-interface的依赖:表现层调用服务要经过该接口 -->
<dependency>
<groupId>com.taotao</groupId>
<artifactId>taotao-sso-interface</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- 配置对taotao-cart-interface的依赖:表现层调用服务要经过该接口 -->
<dependency>
<groupId>com.taotao</groupId>
<artifactId>taotao-cart-interface</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
在taotao-order-web工程中的springmvc.xml文件中引用服务:
参考功能分析的业务逻辑。
请求的url:/order/order-cart
参数:无
@Autowired
private UserLoginService userLoginService;
@Autowired
private CartService cartService;
@Value("${COOKIE_TOKEN_KEY}")
private String COOKIE_TOKEN_KEY;
@Value("${COOKIE_CART_KEY}")
private String COOKIE_CART_KEY;
@RequestMapping("/order/order-cart")
public String showOrderCart(HttpServletRequest request, HttpServletResponse response) {
// 一、从cookie中获取token
String token = CookieUtils.getCookieValue(request, COOKIE_TOKEN_KEY);
// 二、根据token调用SSO服务获取登陆的用户信息,查看用户是否已通过期
TbUser tbUser = null;
if (StringUtils.isNotBlank(token)) {
TaotaoResult result = userLoginService.getUserByToken(token);
if (result.getStatus() == 200) {
tbUser = (TbUser) result.getData();
}
}
// 三、用户必须登陆才展现订单页面
// 四、展现用户的配送地址列表,根据用户id从数据库中查询收货地址列表,这里暂时使用静态数据
// 五、展现支付方式列表,从数据库中查询支付的方式列表,这里暂时使用静态数据
// 六、从cookie中获取购物车的商品列表
List<TbItem> cartList2 = getCartListFromCookie(request);
// 七、调用购物车服务从redis数据库中获取购物车的商品列表
List<TbItem> cartList1 = cartService.queryCartListByUserId(tbUser == null ? -1 : tbUser.getId());
// 八、合并数据到redis中
for (TbItem tbItem2 : cartList2) { // 遍历cookie的购物车数据
boolean flag = false;
if (cartList1 != null) { // redis数据库中有购物车数据
for (TbItem tbItem1 : cartList1) { // 遍历redis数据库中购物车的数据
if (tbItem1.getId() == tbItem2.getId().longValue()) {
// 商品数量相加
tbItem1.setNum(tbItem1.getNum() + tbItem2.getNum());
// 更新redis数据库
cartService.updateTbItemCartByUserIdAndItemId(tbUser.getId(), tbItem1.getId(), tbItem1.getNum());
flag = true; // 表示找到
}
}
}
if (flag == false) { // 若是找了redis数据库尚未找到,说明cookie中的商品是新的,须要添加至redis数据库
cartService.addItemCart(tbUser.getId(), tbItem2, tbItem2.getNum());
}
}
// 九、合并数据后删除cookie
if (!cartList2.isEmpty()) {
CookieUtils.deleteCookie(request, response, COOKIE_CART_KEY);
}
// 十、再次调用购物车服务从redis数据库中获取新的购物车的商品列表
List<TbItem> cartList = cartService.queryCartListByUserId(tbUser.getId());
request.setAttribute("cartList", cartList);
return "order-cart";
}
/**
* 从cookie中获取购物车的商品列表的方法
* @param request
* @return
*/
private List<TbItem> getCartListFromCookie(HttpServletRequest request) {
// 一、从cookie中获取商品列表字符串
String cartJson = CookieUtils.getCookieValue(request, COOKIE_CART_KEY, true);
// 二、将字符串转换成java对象
List<TbItem> list = new ArrayList<>();
if (StringUtils.isNotBlank(cartJson)) {
list = JsonUtils.jsonToList(cartJson, TbItem.class);
}
return list;
}
属性文件内容以下:
首先安装taotao-order工程,再启动taotao-order-web。须要先登陆,再去访问。
在展现订单确认页面以前,须要对用户身份进行认证,要求用户必须是登陆装态。
一、使用springmvc的拦截器实现。须要一个实现类实现HandlerInterceptor接口。
二、业务逻辑
a) 从cookie中取token。
b) 没有token,须要跳转到登陆页面。
c) 有token,调用sso系统的服务,根据token查询用户信息。
d) 若是查不到用户信息、用户登陆已通过期。须要跳转到登陆页面。
e) 查询到用户信息,放行。
三、在springmvc.xml中配置拦截器。
/**
* 判断用户是否登陆的拦截器
* @author chenmingjun
* @date 2018年12月7日 下午3:41:52
* @version V1.0
*/
public class LoginInterceptor implements HandlerInterceptor {
@Autowired
private UserLoginService userLoginService;
@Value("${COOKIE_TOKEN_KEY}")
private String COOKIE_TOKEN_KEY;
@Value("${SSO_URL}")
private String SSO_URL;
/**
* 在进入目标方法以前执行该方法。
* 若是返回为false表示拦截,不让访问;若是返回为true,表示放行。
* 咱们在这里进行用户身份的认证。
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// 一、从cookie中获取token
String token = CookieUtils.getCookieValue(request, COOKIE_TOKEN_KEY);
// 二、判断token是否存在
if (StringUtils.isEmpty(token)) {
// 三、若是token不存在,说明用户没登陆,重定向到SSO系统的登陆页面,在SSO系统登陆成功以后跳转回订单确认页面
// http://localhost:8088/page/login?redirect=http://localhost:8092/order/order-cart.html
response.sendRedirect(SSO_URL + "/page/login?redirect=" + request.getRequestURL().toString());
// 拦截
return false;
}
// 四、若是token存在,则调用SSO服务判断用户信息,查看用户登陆是否已通过期(加入依赖,引入服务,注入服务,使用)
TaotaoResult result = userLoginService.getUserByToken(token);
if (result.getStatus() != 200) {
// 五、若是用户登陆已过时,重定向到SSO系统的登陆页面,在SSO系统登陆成功以后跳转回订单确认页面
// http://localhost:8088/page/login?redirect=http://localhost:8092/order/order-cart.html
response.sendRedirect(SSO_URL + "/page/login?redirect=" + request.getRequestURL().toString());
// 拦截
return false;
}
// 六、用户登陆且没过时,放行
return true;
}
/**
* 在进入目标方法以后,在返回ModelAndView以前执行该方法。
* 咱们在这里能够对公用变量进行设置。好比用户名。
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
throws Exception {
}
/**
* 在返回ModelAndView以后执行该方法。
* 咱们在这里能够进行异常的处理、日志的清理等。
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
}
}
属性文件中的SSO_URL:
#cookie中存放token的key
COOKIE_TOKEN_KEY=COOKIE_TOKEN_KEY
#cookie中存放购物车的key
COOKIE_CART_KEY=COOKIE_CART_KEY
#SSO系统的URL
SSO_URL=http://localhost:8088
在taotao-order-web工程中的springmvc.xml文件中配置拦截器:
<!-- 配置用户身份认证的拦截器,用于拦截订单和订单相关的请求-->
<mvc:interceptors>
<mvc:interceptor>
<!-- **表示当前路径及其子路径,*表示当前路径 -->
<mvc:mapping path="/order/**"/><!-- 拦截订单和订单相关的请求 -->
<bean class="com.taotao.order.interceptor.LoginInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
访问地址:http://localhost:8092/order/order-cart.html
发现被拦截后,重定向到登录界面,登陆成功后,跳转到商城首页了。
存在两个问题:
一、SSO服务被调用了两次,先在拦截器类
中的handler方法
中调用了一次,而后进入Controller类
中的目标方法
获取用户信息时又调用了一次。
二、登陆成功后跳转到了商城首页,应当跳转到订单确认页面才对。
实际上,只须要在拦截器类
中的handler方法
中调用了一次即可以了,调用以后,将用户信息的数据存放在request域中,等进入目标的方法后,能够直接经过request域获取用户信息。
在拦截器中,将登陆的用户信息放到request域中:
拦截器类的代码修改以下:
这里访问订单确认页面,须要登陆,登陆以后应当跳转到订单确认页面,不该该回到商城首页。
下面是正常的流程图:
特别注意:要安装taota-sso工程和taota-order工程,而后重启全部工程
,详情省略。。。
用户在购物车点击【去结算】按钮后,再点击【提交订单】按钮,会建立一个订单,以下:
在数据库中涉及到三张表:tb_order、tb_order_item、tb_order_shipping
在tb_order表中
CREATE TABLE `tb_order` (
`order_id` varchar(50) COLLATE utf8_bin NOT NULL DEFAULT '' COMMENT '订单id',
`payment` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT '实付金额。精确到2位小数;单位:元。如:200.07,表示:200元7分',
`payment_type` int(2) DEFAULT NULL COMMENT '支付类型,一、在线支付,二、货到付款',
`post_fee` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT '邮费。精确到2位小数;单位:元。如:200.07,表示:200元7分',
`status` int(10) DEFAULT NULL COMMENT '状态:一、未付款,二、已付款,三、未发货,四、已发货,五、交易成功,六、交易关闭',
`create_time` datetime DEFAULT NULL COMMENT '订单建立时间',
`update_time` datetime DEFAULT NULL COMMENT '订单更新时间',
`payment_time` datetime DEFAULT NULL COMMENT '付款时间',
`consign_time` datetime DEFAULT NULL COMMENT '发货时间',
`end_time` datetime DEFAULT NULL COMMENT '交易完成时间',
`close_time` datetime DEFAULT NULL COMMENT '交易关闭时间',
`shipping_name` varchar(20) COLLATE utf8_bin DEFAULT NULL COMMENT '物流名称',
`shipping_code` varchar(20) COLLATE utf8_bin DEFAULT NULL COMMENT '物流单号',
`user_id` bigint(20) DEFAULT NULL COMMENT '用户id',
`buyer_message` varchar(100) COLLATE utf8_bin DEFAULT NULL COMMENT '买家留言',
`buyer_nick` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT '买家昵称',
`buyer_rate` int(2) DEFAULT NULL COMMENT '买家是否已经评价',
PRIMARY KEY (`order_id`),
KEY `create_time` (`create_time`),
KEY `buyer_nick` (`buyer_nick`),
KEY `status` (`status`),
KEY `payment_type` (`payment_type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
详解以下:
主键order_id是字符串类型,不是自增加的,所以咱们须要本身生成订单编号,咱们平时使用京东、天猫等购物网站,发现人家的订单号都是用`数字`组成的,咱们也使用数字做为订单号,可是怎样才能使订单号不重复呢?用`时间加随机数`的方案生成的订单其实仍是可能会重复的,当同一时刻生成的订单越多越有可能出现订单号同样的状况,所以咱们不能使用这种方案。比较好的方案是什么呢?是`用redis的incr方法`,因为redis中每个操做都是`单线程`的,因此每个操做都是具备`原子性`的,所以不会出现编号重复的问题。
payment 字段是实付金额,须要从前台传过来,`保留小数点后2位`。
payment_type 是支付类型,分为在线支付和货到付款,也须要从前台页面传过来。
post_free 字段是邮费,邮费得由前台传过来,由于不少电商都搞活动,买够多少钱的东西就免邮费,所以`邮费是动态变化`的。
status 字段是订单状态,订单状态咱们暂且定义了6种状态,未付款、已付款、未发货、已发货、交易成功、交易关闭。
create_time 字段是订单建立时间,这没什么可说的。
update_time 字段是订单更新时间,这个一般是订单状态发生了变化。
payment_time 字段是付款时间。
consign_time 字段是发货时间。
end_time 字段是交易完成时间,这个一般是用户点确认收货的时间。
close_time 字段是交易关闭时间,交易关闭时间则是该订单的全部流程都走完后的时间。
shipping_name 字段是物流名称,即用的谁家的快递。
shipping_code 字段是物流单号,这个不用废话。
user_id 字段固然是指`购买者ID`。
buyer_message 字段是指买家留言。
buyer_nick 字段指`买家昵称`。
buyer_rate 字段记录买家是否已经评价。
表中还能够看到create_time、buyer_nick、status、payment_type这四个字段由key修饰,说明为这四个字段创建了索引。
设计要求:
1、订单号须要手动生成。
2、要求订单号不能重复。
3、订单号可读性好。
4、订单号不能太长。20位。
5、可使用`redis的incr命令生成订单号`。订单号须要一个`初始值`。
在tb_order_item表中
CREATE TABLE `tb_order_item` (
`id` varchar(20) COLLATE utf8_bin NOT NULL,
`item_id` varchar(50) COLLATE utf8_bin NOT NULL COMMENT '商品id',
`order_id` varchar(50) COLLATE utf8_bin NOT NULL COMMENT '订单id',
`num` int(10) DEFAULT NULL COMMENT '商品购买数量',
`title` varchar(200) COLLATE utf8_bin DEFAULT NULL COMMENT '商品标题',
`price` bigint(50) DEFAULT NULL COMMENT '商品单价',
`total_fee` bigint(50) DEFAULT NULL COMMENT '商品总金额',
`pic_path` varchar(200) COLLATE utf8_bin DEFAULT NULL COMMENT '商品图片地址',
PRIMARY KEY (`id`),
KEY `item_id` (`item_id`),
KEY `order_id` (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
详解以下:
从订单表中能够看到订单表中并无购买`商品详情信息`,那么商品详情信息在哪儿存放呢?
答:它被存放到了tb_order_item表中,主键id字段也是个字符串,咱们也须要为其生成主键,一样使用`redis的incr`。
设计要求:
1、展现商品的数据,`增长字段冗余`(目的:`减小关联查询,提高查询性能`)。
2、逆规范化与反三范式参考连接:https://blog.csdn.net/liuyifeng1920/article/details/54136385
在tb_order_shipping表中
CREATE TABLE `tb_order_shipping` (
`order_id` varchar(50) NOT NULL COMMENT '订单ID',
`receiver_name` varchar(20) DEFAULT NULL COMMENT '收货人全名',
`receiver_phone` varchar(20) DEFAULT NULL COMMENT '固定电话',
`receiver_mobile` varchar(30) DEFAULT NULL COMMENT '移动电话',
`receiver_state` varchar(10) DEFAULT NULL COMMENT '省份',
`receiver_city` varchar(10) DEFAULT NULL COMMENT '城市',
`receiver_district` varchar(20) DEFAULT NULL COMMENT '区/县',
`receiver_address` varchar(200) DEFAULT NULL COMMENT '收货地址,如:xx路xx号',
`receiver_zip` varchar(6) DEFAULT NULL COMMENT '邮政编码,如:310001',
`created` datetime DEFAULT NULL,
`updated` datetime DEFAULT NULL,
PRIMARY KEY (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
详解以下:
这张表存放的是订单物流信息,包括收货人姓名、固定电话、移动电话、省、市、区/县、街道门牌号、邮政编码,并且收货人信息与订单是一对一的关系,所以收货地址表的主键是order_id。
点击【提交订单】按钮时,会触发$('#orderForm').submit()函数
,使用id选择器
来获得表单,而且将该表单提交。
隐藏
的,是不会被用户看到的,用户看到的只是表单下面展现的信息(这些信息只是作展现用,不会被提交,真正提交的是被隐藏的表单)。表单要提交的话,咱们通常
用pojo来接收
比较合适,那么这个表单咱们应该用什么样的pojo来接收呢?先来看看这个表单都有那些数据。
tb_order
、
tb_order_item
、
tb_order_shipping
三张表的数据,其中
红色线框
起来的支付方式paymentType、支付金额payment属于
tb_order
,
黑色线框
起来的商品信息属于
tb_order_item
,
黄色线框
起来的订单物流信息属于
tb_order_shipping
表。这里暂时将
tb_order_shipping
表的数据写死,支付类型也默认使用“1”。
写个包装的pojo类包含这些表单信息
,那么咱们这个pojo应该放到哪儿比较合适呢?咱们不能把它放到taotao-common当中,由于咱们的pojo类要继承TbOrder类,TbOrder类属于taotao-manager-dao工程,即taotao-common工程要依赖taotao-manager-dao了,而taotao-manager-dao工程已经依赖了taotao-common工程,那么便成了
相互依赖
了,这是断不可行的。咱们还想该pojo类要
尽量的共用
,则把它放到taotao-order-interface工程比较合适,由于taotao-order工程及taotao-order-web工程都依赖taotao-order-interface,所以把pojo写到taotao-order-interface工程比较合适。
继承了TbOrder类
,这样OrderInfo便直接拥有了
TbOrder的属性
。即扩展TbOrder,在子类中添加两个属性一个是
商品明细列表
,一个是
配送信息表
。为了让该pojo在网络中传输,咱们须要让它
实现序列化接口
。
/**
* 订单信息包装类
* @author chenmingjun
* @date 2018年12月7日 下午9:10:56
* @version V1.0
*/
public class OrderInfo extends TbOrder implements Serializable {
private static final long serialVersionUID = 1L;
// 订单明细表
private List<TbOrderItem> orderItems; // springmvc属性绑定的命名要求:与页面上的一致
// 订单物流表
private TbOrderShipping orderShipping; // springmvc属性绑定的命名要求:与页面上的一致
public List<TbOrderItem> getOrderItems() {
return orderItems;
}
public void setOrderItems(List<TbOrderItem> orderItems) {
this.orderItems = orderItems;
}
public TbOrderShipping getOrderShipping() {
return orderShipping;
}
public void setOrderShipping(TbOrderShipping orderShipping) {
this.orderShipping = orderShipping;
}
}
URL: /order/create
参数:表单的数据(包含:订单信息、订单明细列表、订单物流信息)
参数:提交的是表单的数据。保存的数据:订单、订单明细、配送地址。
a) 向tb_order中插入记录。
i.订单号须要手动生成。
要求订单号不能重复。
订单号可读性好。
可使用redis的incr命令生成订单号。订单号须要一个初始值。
ii.payment:表单数据
iii.payment_type:表单数据
iv.user_id:用户信息
v.buyer_nick:用户名
vi.其余字段null
b) 向tb_order_item订单明细表中插入数据。
i.id:使用incr生成
ii.order_id:生成的订单号
iii.其余的都是表单中的数据
c) 向tb_order_shipping订单配送信息中插入数据。
i.order_id:生成的订单号
ii.其余字段都是表单中的数据
d) 使用pojo接收表单的数据。
能够扩展TbOrder,在子类中添加两个属性一个是商品明细列表,一个是配送信息表。
把pojo放到taotao-order-interface工程中。
返回值:逻辑视图(包含:订单的ID)
业务逻辑:
一、接收表单的数据。
二、生成订单ID。
三、向订单表插入数据。(注意:不要忘记用户ID设置)
四、向订单明细表插入数据。
五、向订单物流表插入数据。
六、返回TaotaoResult。(包含订单的ID)
返回值:TaotaoResult 包含订单ID
既然表和接收表单的pojo都有了,代码就好写了。
直接使用逆向工程生成的代码。
在taotao-order-interface建立接口:
/**
* 订单管理的接口
* @author chenmingjun
* @date 2018年12月7日 下午10:57:07
* @version V1.0
*/
public interface OrderService {
/**
* 生成订单
* @param orderInfo 包含了表单提交的全部数据
* @return
*/
TaotaoResult createOrder(OrderInfo orderInfo);
}
在taotao-order-service中建立实现类:
因为要操做redis因此须要jedis的依赖,在pom.xml中添加依赖:
<!-- 配置对Redis的Java客户端jedis的依赖 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
在taotao-order-service工程的/src/main/java中添加jedis的工具包,以下图所示:
#订单号生成的key
ORDER_ID_GEN_KEY=ORDER_ID_GEN
#订单号的初始值
ORDER_ID_INIT_VALUE=100888
#订单明细表主键生成的key
ORDER_ITEM_ID_GEN_KEY=ORDER_ITEM_ID_GEN
还须要在taotao-order-service中applicationContext-dao.xml文件配置对resources.properties文件扫描,以下图所示:
/**
* 订单管理的Service
* @author chenmingjun
* @date 2018年12月7日 下午10:58:44
* @version V1.0
*/
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
private JedisClient jedisClient;
@Autowired
private TbOrderMapper tbOrderMapper;
@Autowired
private TbOrderItemMapper tbOrderItemMapper;
@Autowired
private TbOrderShippingMapper tbOrderShippingMapper;
@Value("${ORDER_ID_GEN_KEY}")
private String ORDER_ID_GEN_KEY;
@Value("${ORDER_ID_INIT_VALUE}")
private String ORDER_ID_INIT_VALUE;
@Value("${ORDER_ITEM_ID_GEN_KEY}")
private String ORDER_ITEM_ID_GEN_KEY;
@Override
public TaotaoResult createOrder(OrderInfo orderInfo) {
// 一、接收表单的数据。
// 二、向订单表插入数据。
if (!jedisClient.exists(ORDER_ID_GEN_KEY)) { // 说明订单生成的key不存在
// 设置订单号的初始值
jedisClient.set(ORDER_ID_GEN_KEY, ORDER_ID_INIT_VALUE);
}
// 2.一、生成订单的ID。经过redis的incr来生成。
String orderId = jedisClient.incr(ORDER_ID_GEN_KEY).toString();
// 2.二、补全订单表的其余属性。
// 设置订单id
orderInfo.setOrderId(orderId);
// 设置订单状态:一、未付款,二、已付款,三、未发货,四、已发货,五、交易成功,六、交易关闭
orderInfo.setStatus(1);
// 设置订单邮费
orderInfo.setPostFee("0");
// 设置订单建立日期
orderInfo.setCreateTime(new Date());
// 设置订单更新日期
orderInfo.setUpdateTime(new Date());
// 在Controller中设置
// 设置买家昵称
// orderInfo.setBuyerNick(buyerNick);
// 设置用户id
// orderInfo.setUserId(userId);
tbOrderMapper.insert(orderInfo);
// 三、向订单明细表插入数据。
List<TbOrderItem> orderItems = orderInfo.getOrderItems();
for (TbOrderItem tbOrderItem : orderItems) {
// 3.一、生成订单明细表的ID。经过redis的incr来生成。
String orderItemId = jedisClient.incr(ORDER_ITEM_ID_GEN_KEY).toString();
// 3.二、补全订单明细的其余属性。
// 设置订单明细id
tbOrderItem.setId(orderItemId);
// 设置订单明细所属订单id
tbOrderItem.setOrderId(orderId);
tbOrderItemMapper.insert(tbOrderItem);
}
// 四、向订单物流表插入数据。
TbOrderShipping orderShipping = orderInfo.getOrderShipping();
// 4.一、设置订单的ID。
orderShipping.setOrderId(orderId);
// 4.二、补全订单物流表的其余属性。
orderShipping.setCreated(new Date());
orderShipping.setUpdated(new Date());
tbOrderShippingMapper.insert(orderShipping);
// 五、返回TaotaoResult。(要包含订单的ID)
return TaotaoResult.ok(orderId);
}
}
在applicationContext-service.xml发布服务:
在springmvc.xml中引入服务:
请求的url:/order/create
参数:使用OrderInfo接收
返回值:逻辑视图。(页面应该显示订单号)
业务逻辑:
一、接收表单提交的数据OrderInfo。
二、补全用户信息。
三、调用Service建立订单。
四、返回逻辑视图展现订单提交成功页面:
4.一、须要Service返回订单号。
4.二、当前日期加三天。
第一步:首先加入时间操做组件的依赖:已经在taotao-common中依赖。
<!-- 时间操做组件 -->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
</dependency>
Controller代码以下:
@RequestMapping(value="/order/create", method=RequestMethod.POST)
public String createOrder(OrderInfo orderInfo, HttpServletRequest request) {
// 0、引入服务,注入服务
// 一、接收表单提交的数据OrderInfo。
// 从request域中获取登陆的用户信息。
TbUser tbUser = (TbUser) request.getAttribute("USER_INFO");
// 二、补全OrderInfo信息。
orderInfo.setUserId(tbUser.getId());
orderInfo.setBuyerNick(tbUser.getUsername());
// 三、调用Service建立订单。
TaotaoResult result = orderService.createOrder(orderInfo);
// 四、返回逻辑视图展现订单提交成功页面
// 4.一、须要Service返回订单号。
request.setAttribute("orderId", result.getData().toString());
request.setAttribute("payment", orderInfo.getPayment());
// 4.二、返回当前日期加三天。
DateTime dateTime = new DateTime();
dateTime = dateTime.plusDays(3);
request.setAttribute("date", dateTime.toString("yyyy-MM-dd"));
return "success";
}
安装taotao-order,启动,用户在购物车点击去结算,点击提交订单,会建立一个订单,查看数据库中已存在数据。
本文参考: https://blog.csdn.net/pdsu161530247/article/details/82312620 https://blog.csdn.net/u012453843/article/details/73368967