1.   学习计划

1、订单系统

2、提交订单

3、MyCAT

2.   订单系统

2.1. 功能分析

1、在购物车页面点击“去结算”按钮跳转到订单确认页面。

a)         展示商品列表

b)        配送地址列表

c)         选择支付方式

2、展示订单确认页面之前,应该确认用户身份。

a)         使用拦截器实现。

b)        Cookie中取token

c)         取不到token跳转到登录页面

d)        取到token,根据token查询用户信息。

e)         如果没有用户信息,登录过期跳转到登录页面

f)          取到用户信息,放行。

3、提交订单

a)         生成订单

b)        展示订单提交成功页面。

订单系统系统:订单确认页面、订单提交成功页面。

订单服务系统

2.2. 工程搭建

创建一个订单服务系统:

e3-order

|--e3-order-interface(jar)

|--e3-order-Service(war)

e3-order-web(war)

导入静态页面

2.3. 展示订单确认页面

2.3.1.    功能分析

1、在购物车页面点击“去结算”按钮跳转到订单确认页面。

2、请求的url:

/order/order-cart

3、参数:没有参数。

4、购物车商品数据从cookie中取出来的。可以在订单系统中取到cookie中的购物车数据。

5、配送地址列表,需要用户登录。需要根据用户id查询收货地址列表。静态数据。

6、支付方式。静态数据。

7、返回值:逻辑视图String,展示订单确认页面。

2.3.2.    Dao层、Service层(没有)

引入其他工程接口即可。

2.3.3.    表现层

引入服务

    <dubbo:reference interface="cn.e3mall.car.service.CartService" id="cartService" />
@Controller
public class OrderController { @Autowired
private CartService cartService; @RequestMapping("/order/order-cart")
public String showOrderCart(HttpServletRequest request){
//取用户id
TbUser user= (TbUser) request.getAttribute("user");
//根据用户id取收货地址列表
//使用静态数据。。。
//取支付方式列表
//静态数据
//根据用户id取购物车列表
List<TbItem> cartList = cartService.getCartList(user.getId());
//把购物车列表传递给jsp
request.setAttribute("cartList", cartList);
return "order-cart";
}

2.4. 用户身份认证

在展示订单确认页面之前,需要对用户身份进行认证,要求用户必须登录。

2.4.1.    功能分析

1、使用springmvc的拦截器实现。需要实现一个接口HandlerInterceptor接口。

2、业务逻辑

a)         从cookie中取token。

b)        没有token,需要跳转到登录页面。

c)         有token。调用sso系统的服务,根据token查询用户信息。

d)        如果查不到用户信息。用户登录已经过期。需要跳转到登录页面。

e)         查询到用户信息。放行。

3、在springmvc.xml中配置拦截器。

2.4.2.    拦截器实现

springmvc.xml

    <mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="cn.e3mall.order.interceptor.LoginInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>

LoginInterceptor.java

public class LoginInterceptor implements HandlerInterceptor{
@Autowired
private TokenService tokenService;
@Autowired
private CartService cartService; @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
//从cookie中取token
String token=CookieUtils.getCookieValue(request, "token");
//判断token是否存在
if(StringUtils.isBlank(token)){
//如果token不存在,跳转到登录页面
response.sendRedirect("http://localhost:8089/page/login?redirect="+request.getRequestURL());
//拦截
return false;
}
//如果token存在,根据token取用户信息
E3Result e3Result = tokenService.getUserByToken(token);
//如果取不到,表示已经过期,需要重新登录
if(e3Result.getStatus()!=200){
//如果token不存在,跳转到登录页面
response.sendRedirect("http://localhost:8089/page/login?redirect="+request.getRequestURL());
//拦截
return false;
}
//如果取到,已经登录,把用户信息写入request
TbUser user = (TbUser) e3Result.getData();
request.setAttribute("user", user);
//判断cookie中是否有购物车数据,如果有就合并
String string = CookieUtils.getCookieValue(request, "car",true);
if(StringUtils.isNoneBlank(string)){
cartService.mergeCart(user.getId(), JsonUtils.jsonToList(string, TbItem.class));
}
//放行
return true;
} @Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
// TODO Auto-generated method stub } @Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
// TODO Auto-generated method stub }
}

2.4.3.    实现sso系统的回调

3.   提交订单

3.1. 功能分析

1、在订单确认页面点击“提交订单”按钮生成订单。

2、请求的url:/order/create

3、参数:提交的是表单的数据。保存的数据:订单、订单明细、配送地址。

a)         向tb_order中插入记录。

  1. 订单号需要手动生成。

要求订单号不能重复。

订单号可读性号。

可以使用redis的incr命令生成订单号。订单号需要一个初始值。

  1. Payment:表单数据
  2. payment_type:表单数据
  3. user_id:用户信息
  4. buyer_nick:用户名
  5. 其他字段null

b)        向tb_order_item订单明细表插入数据。

  1. Id:使用incr生成
  2. order_id:生成的订单号
  3. 其他的都是表单中的数据。

c)         tb_order_shipping,订单配送信息

  1. order_id:生成的订单号
  2. 其他字段都是表单中的数据。

d)        使用pojo接收表单的数据。

可以扩展TbOrder,在子类中添加两个属性一个是商品明细列表,一个是配送信息。

把pojo放到e3-order-interface工程中。

public class OrderInfo extends TbOrder implements Serializable{
private List<TbOrderItem> orderItems;
private TbOrderShipping orderShipping; 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;
} }

业务逻辑:

1、接收表单的数据

2、生成订单id

3、向订单表插入数据。

4、向订单明细表插入数据

5、向订单物流表插入数据。

6、返回e3Result。

3.2. Dao层

可以使用逆向工程。

3.3. Service层

参数:OrderInfo

返回值:e3Result

@Service
public class OrderServiceImpl implements OrderService{ @Autowired
private TbOrderMapper orderMapper;
@Autowired
private TbOrderItemMapper orderItemMapper;
@Autowired
private TbOrderShippingMapper orderShippingMapper;
@Autowired
private JedisClient jedisClient; @Override
public E3Result createOrder(OrderInfo orderInfo) {
// 生成订单号
if(!jedisClient.exists("ORDER_ID_GEN")){
jedisClient.set("ORDER_ID_GEN","11500");
}
String orderId = jedisClient.incr("ORDER_ID_GEN").toString();
//补全orderInfo属性
orderInfo.setOrderId(orderId);
//1、未付款,2、已付款,3、未发货,4、已发货,5、交易成功,6、交易关闭
orderInfo.setStatus(1);
Date date = new Date();
orderInfo.setCreateTime(date);
orderInfo.setUpdateTime(date);
//插入订单表
orderMapper.insert(orderInfo);
//向订单明细表插入数据
List<TbOrderItem> orderItems = orderInfo.getOrderItems();
for (TbOrderItem tbOrderItem : orderItems) {
//生成明细id
Long orderItemId = jedisClient.incr("ORDER_ITEM_ID_GEN");
tbOrderItem.setId(orderItemId.toString());
tbOrderItem.setOrderId(orderId);
//插入数据
orderItemMapper.insert(tbOrderItem);
}
//向订单物流表插入数据
TbOrderShipping orderShipping = orderInfo.getOrderShipping();
orderShipping.setOrderId(orderId);
orderShipping.setCreated(date);
orderShipping.setUpdated(date);
orderShippingMapper.insert(orderShipping);
//返回
return E3Result.ok(orderId);
} }

发布服务

<dubbo:service interface="cn.e3mall.order.service.OrderService" ref="orderServiceImpl" timeout="600000"/>

3.4. Controller

引用服务

    <dubbo:reference interface="cn.e3mall.order.service.OrderService" id="orderService" />

请求的url:/order/create

参数:使用OrderInfo接收

返回值:逻辑视图。

@RequestMapping(value="/order/create", method=RequestMethod.POST)
public String createOrder(OrderInfo orderInfo, HttpServletRequest request) {
// 取用户信息
TbUser user = (TbUser) request.getAttribute("user");
// 把用户信息添加到orderInfo中
orderInfo.setUserId(user.getId());
orderInfo.setBuyerNick(user.getUsername());
// 调用Service创建订单。
E3Result result = orderService.createOrder(orderInfo);
//如果订单生成成功,需要删除购物车
if(result.getStatus()==200){
cartService.clearCartItem(user.getId());
}
//把订单号传递给页面
request.setAttribute("orderId", result.getData());
request.setAttribute("payment", orderInfo.getPayment());
// 返回逻辑视图展示成功页面
return "success";
}

调用CartServiceImpl.java

    //清空购物车
@Override
public E3Result clearCartItem(long userId) {
jedisClient.del("Cart:" + userId);
return E3Result.ok();
}

4.   MyCAT介绍

4.1. 什么是MyCAT?

简单的说,MyCAT就是:

一个彻底开源的,面向企业应用开发的“大数据库集群”

支持事务、ACID、可以替代Mysql的加强版数据库

一个可以视为“Mysql”集群的企业级数据库,用来替代昂贵的Oracle集群

一个融合内存缓存技术、Nosql技术、HDFS大数据的新型SQL Server

结合传统数据库和新型分布式数据仓库的新一代企业级数据库产品

一个新颖的数据库中间件产品

MyCAT的目标是:低成本的将现有的单机数据库和应用平滑迁移到“云”端,解决数据存储和业务规模迅速增长情况下的数据瓶颈问题。

4.2. MyCAT的关键特性

支持 SQL 92标准

支持Mysql集群,可以作为Proxy使用

支持JDBC连接ORACLE、DB2、SQL Server,将其模拟为MySQL  Server使用

支持galera for mysql集群,percona-cluster或者mariadb cluster,提供高可用性数据分片集群

自动故障切换,高可用性

支持读写分离,支持Mysql双主多从,以及一主多从的模式

支持全局表,数据自动分片到多个节点,用于高效表关联查询

支持独有的基于E-R 关系的分片策略,实现了高效的表关联查询

多平台支持,部署和实施简单

4.3. MyCAT架构

如图所示:MyCAT使用Mysql的通讯协议模拟成了一个Mysql服务器,并建立了完整的Schema(数据库)、Table (数据表)、User(用户)的逻辑模型,并将这套逻辑模型映射到后端的存储节点DataNode(MySQL Instance)上的真实物理库中,这样一来,所有能使用Mysql的客户端以及编程语言都能将MyCAT当成是Mysql Server来使用,不必开发新的客户端协议。

5.   Mycat解决的问题

l  性能问题

l  数据库连接过多

l  E-R分片难处理

l  可用性问题

l  成本和伸缩性问题

5.1. Mycat对多数据库的支持

6.   分片策略

MyCAT支持水平分片与垂直分片:

水平分片:一个表格的数据分割到多个节点上,按照行分隔。

垂直分片:一个数据库中多个表格A,B,C,A存储到节点1上,B存储到节点2上,C存储到节点3上。

MyCAT通过定义表的分片规则来实现分片,每个表格可以捆绑一个分片规则,每个分片规则指定一个分片字段并绑定一个函数,来实现动态分片算法。

1、Schema:逻辑库,与MySQL中的Database(数据库)对应,一个逻辑库中定义了所包括的Table。

2、Table:表,即物理数据库中存储的某一张表,与传统数据库不同,这里的表格需要声明其所存储的逻辑数据节点DataNode。在此可以指定表的分片规则。

3、DataNode:MyCAT的逻辑数据节点,是存放table的具体物理节点,也称之为分片节点,通过DataSource来关联到后端某个具体数据库上

4、DataSource:定义某个物理库的访问地址,用于捆绑到Datanode上

SSM商城项目(十三)的更多相关文章

  1. SSM商城项目(一)

    1. 学习计划 1.电商行业的背景. 2.宜立方商城介绍 3.宜立方商城的系统架构 a) 功能介绍 b) 架构讲解 4.工程搭建-后台工程 a) 使用maven搭建工程 b) 使用maven的tomc ...

  2. SSM商城项目(四)

    1. 学习计划 1.图片服务器 2.图片服务器安装 3.图片服务器的使用 4.图片上传功能 5.富文本编辑器的使用方法 6.商品添加功能实现 2. 图片服务器 1.存储空间可扩展. 2.提供一个统一的 ...

  3. SSM商城项目(二)

    1. 学习计划 1.将工程改造为基于SOA架构 2.商品列表查询功能实现. 2. 将工程改造为SOA架构 2.1. 分析 由于商城是基于soa的架构,表现层和服务层是不同的工程.所以要实现商品列表查询 ...

  4. SSM商城项目(五)

    1.   学习计划 1.前台系统搭建 2.商城首页展示 3.Cms系统的实现 a)         内容分类管理 b)         内容管理 4.前台内容动态展示 2.   商城首页展示 2.1. ...

  5. SSM商城项目(十二)

    1.   学习计划 1.购物车实现 2.未登录状态下使用购物车 3.登录状态下使用购物车 2.   购物车的实现 2.1. 功能分析 1.购物车是一个独立的表现层工程. 2.添加购物车不要求登录.可以 ...

  6. SSM商城项目(十一)

    1.   学习计划 1.sso注册功能实现 2.sso登录功能实现 3.通过token获得用户信息 Ajax跨域请求(jsonp) 2.   Sso系统工程搭建 需要创建一个sso服务工程,可以参考e ...

  7. SSM商城项目(十)

    1.   学习计划 1.使用freemarker实现网页静态化 a)Freemarker的使用方法 b)Freemarker模板的语法 c)Freemarker整合springmvc 2.Active ...

  8. SSM商城项目(九)

    1.   学习计划 1.Activemq整合springMQ的应用场景 2.添加商品同步索引库 3.商品详情页面动态展示 4.展示详情页面使用缓存 2.   Activemq整合spring 2.1. ...

  9. SSM商城项目(八)

    1.   学习计划 1.solr集群搭建 2.使用solrj管理solr集群 3.把搜索功能切换到集群版 4.添加商品同步到索引库 2.   什么是SolrCloud SolrCloud(solr 云 ...

随机推荐

  1. Django的安装和启动以及第一个工程的建立

    ---恢复内容开始--- 前提:已经安装了python和Anaconda (windows系统) 在Anaconda安装好之后,其文件夹下有一个叫做Anaconda Prompt的工具,类似windo ...

  2. 一维信号频谱图仿真——matlab

    程序1: %在MATLAB中是用连续信号在等时间间隔点的样值来近似地表示连续信号的,当采样时间间隔足够小时,这些离散的采样值就能较好地近似出连续信号,matlab中连续信号的显示实际上还是离散信号的显 ...

  3. js赋值后,不影响源变量的方法。

    以前都没发现这个问题,特记录一下. var productListData={pages:001}; var data=productListData;//这样就会有问题. data=$.extend ...

  4. CentOS 7.x 如何关闭 numa

    CentOS7.x中发现 numactl --interleave=all 执行失败. CentOS7.x中可以通过下面的方式关闭 numa: 1. 编辑 /etc/default/grub 文件,如 ...

  5. Centos 7 LVM xfs文件系统修复

    Centos 7 LVM xfs文件系统修复 今天一大早,zabbix开始报警了,一台linux主机出现问题. 登陆控制台查看,报如下错误. 解决方法如下: ls -l /dev/mapper xfs ...

  6. json,pickle,shelve模块,xml处理模块

    常用模块学习—序列化模块详解 什么叫序列化? 序列化是指把内存里的数据类型转变成字符串,以使其能存储到硬盘或通过网络传输到远程,因为硬盘或网络传输时只能接受bytes. 为什么要序列化? 你打游戏过程 ...

  7. 转HDMI

    HDMI协议解析 2017年06月18日 14:19:27 阅读数:2987 转载请标明出处floater的csdn blog,http://blog.csdn.net/flaoter 本文从软件工程 ...

  8. let const区别!

    这次做项目在申明变量的时候用到let const 总结下这两个区别 : 首先 let与const都是只在声明所在的块级作用域内有效. let声明的变量可以改变,值和类型都可以改变,没有限制.const ...

  9. VB.net中合并word中的表格

    软帝国产品的互兼容性使得我们采用vb.net编程语言操作Microsoft Word文档变得相当容易.针对本文的主题,网络上已经有很多大牛博客做了详细的介绍,基本的我就不再赘述,只是自己在做项目的时候 ...

  10. eclipse注解模板,实实在在的

    1.可以引用其他codetemplate.xml 2.可以自己配置,很快,就几个主要的,个人建议这个,配一次妥妥的,以后就会了,也不用搭理模板了 3.按照公司要求 拿去https://www.jian ...