課程計劃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