乐优商城的技术特点
- 技术范围广
- 技术新
- 高并发(分布式、静态化技术、缓存技术、异步并发、池化、队列)
- 高可用(集群、负载均衡、限流、降级、熔断)
- 数据量大
- 业务复杂
- 数据安全
常见的电商模式
- B2C:商家对个人,如:亚马逊、当当等
- C2C平台:个人对个人,如:咸鱼、拍拍网、ebay
- B2B平台:商家对商家,如:阿里巴巴、八方资源网等
- O2O:线上和线下结合,如:饿了么、电影票、团购等
- P2P:在线金融,贷款,如:网贷之家、人人聚财等。
- B2C平台:天猫、京东、一号店等
项目介绍
- 乐优商城是一个全品类的电商购物网站(B2C)。
- 用户可以在线购买商品、加入购物车、下单、秒杀商品
- 可以品论已购买商品
- 管理员可以在后台管理商品的上下架、促销活动
- 管理员可以监控商品销售状况
- 客服可以在后台处理退款操作
系统机构图
2.2.2.系统架构解读
整个乐优商城可以分为两部分:后台管理系统、前台门户系统。
-
后台管理:
- 后台系统主要包含以下功能:
- 商品管理,包括商品分类、品牌、商品规格等信息的管理
- 销售管理,包括订单统计、订单退款处理、促销活动生成等
- 用户管理,包括用户控制、冻结、解锁等
- 权限管理,整个网站的权限控制,采用JWT鉴权方案,对用户及API进行权限控制
- 统计,各种数据的统计分析展示
- 后台系统会采用前后端分离开发,而且整个后台管理系统会使用Vue.js框架搭建出单页应用(SPA)。
- 预览图:
- 后台系统主要包含以下功能:
-
前台门户
- 前台门户面向的是客户,包含与客户交互的一切功能。例如:
- 搜索商品
- 加入购物车
- 下单
- 评价商品等等
- 前台系统我们会使用Thymeleaf模板引擎技术来完成页面开发。出于SEO优化的考虑,我们将不采用单页应用。
- 前台门户面向的是客户,包含与客户交互的一切功能。例如:
无论是前台还是后台系统,都共享相同的微服务集群,包括:
- 商品微服务:商品及商品分类、品牌、库存等的服务
- 搜索微服务:实现搜索功能
- 订单微服务:实现订单相关
- 购物车微服务:实现购物车相关功能
- 用户中心:用户的登录注册等功能
- Eureka注册中心
- Zuul网关服务
- Spring Cloud Config配置中心
技术选型
前端技术:
- 基础的HTML、CSS、JavaScript(基于ES6标准)
- JQuery
- Vue.js 2.0以及基于Vue的框架:Vuetify
- 前端构建工具:WebPack
- 前端安装包工具:NPM
- Vue脚手架:Vue-cli
- Vue路由:vue-router
- ajax框架:axios
- 基于Vue的富文本框架:quill-editor
后端技术:
- 基础的SpringMVC、Spring 5.0和MyBatis3
- Spring Boot 2.0.1版本
- Spring Cloud 最新版 Finchley.RC1
- Redis-4.0
- RabbitMQ-3.4
- Elasticsearch-5.6.8
- nginx-1.10.2:
- FastDFS - 5.0.8
- MyCat
- Thymeleaf
3.2.开发环境
为了保证开发环境的统一,希望每个人都按照我的环境来配置:
- IDE:我们使用Idea 2017.3 版本
- JDK:统一使用JDK1.8
- 项目构建:maven3.3.9以上版本即可
- 版本控制工具:git
- 并采用一二级域名
面试讲解
1.我们前端采用vue,(一般企业vue都是结合Element 可以vue前端包中的HTTPS文件中更改后端接口),我们了解到前端使用的是weboack打包运行的 ,我在本地调试运行时就遇到了版本不兼容原因,解决办法就是降低版本 使用低版本运行
2.我们使用了Nginx的代理进行负载均衡的分发地址,根据不同的请求分发到不同的服务,同时使用反向代理
面试官:你们是怎么实现的Nginx分发的?
Ng的反向代理 就是代理服务器,正向代理就是代理客户端,所以我在Ng的配置文件ngixn.conf文件中配置了多个service,这样做的的目的就是降低服务压力
3.跨域问题
Hr:你是怎么解决跨域问题的?
我是用的是Cors跨域解决跨域问题,也就是springMvc中有一个过滤器(CorsFilter),我们在网关自定义了一个全局的过滤器,浏览器会在请求头中携带一些头信息,我们只需要判断是否允许跨域即可,一般是在头信息中的orgin塞入域名,cors的优点在于可自定义规则,支持各种请求方式,确缺点就是回产生额外的请求!
Hr:什么是cors跨域解决?
Cors是一个W3C标准,称“跨域资源共享,它允许浏览器想资源服务器发出(XML-HTTPRequest )” 请求,从而克服了 Ajax 中只能同资源使用的局限性,唯一的问题就是 IE (浏览器)版本不能低于10,
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
/**
* 实现跨域cors配置
*/
@Configuration
public class LeyouCorsFilterConfiguration {
@Bean
public CorsFilter corsFilter(){
//创建一个cors配置类
CorsConfiguration config = new CorsConfiguration();
//添加允许跨域的域名(ps 域名写* 就不可以携带cooki了)
config.addAllowedOrigin("http://manage.leyou.com");
//设置是否携带cookie
config.setAllowCredentials(true);
//添加允许访问的请求方式 (*代表所有的请求方法)
config.addAllowedMethod("*");
//添加允许携带那些 头 信息
config.addAllowedHeader("*");
//初始化配置源对象
UrlBasedCorsConfigurationSource urlSource = new UrlBasedCorsConfigurationSource();
//注册 拦截所有请求,校验是否允许跨域
urlSource.registerCorsConfiguration("/**",config);//参数需要:拦截路基 和 cors配置类
return new CorsFilter(urlSource);//需要一个配置源参数
}
}
如果携带Cookie那么Origin就不能写 * 号
Cookie作用一般会在登陆模块和购物车模块都是必须的
品牌管理模块,和品牌分类模块
后台对这些模块基本没啥逻辑,都是些简单的(增删改查,关联查询等)
在项目中,我做品牌管理和分类模块中最常见的就是400问题,也就是参数不匹配,我依然旧的一种写法是就是前端将品牌作为对象传递给我,然后品牌分类的ids就用,号分隔一同全部传递过来了,我解决的方案就是直接用一个品牌对象和一个List数组Long类型的方式进行接受,当然也用了@RequestParan进行参数绑定,在这个问题中,我还了解到前端使用了一个QS的工具,它可以将Josn对象自动转换成String,也可以将String字符串转换成Json对象API方法就是SreingIfy()和Parse()!
文件上传模块
文件上传我们使用的是FastDFS分布式文件管理器的服务当然以前项目,也使用过阿里的OSS对象存储的服务,FastDFS它分三个服务,一是 踪迹服务(跟踪服务),二是 存储服务 ,三是 客户端
流程大概是:客户端发起请求,然后去找踪迹服务,踪迹服务轮询的方式去查找存储服务分组的文件,找到后返回存储状态,并携带id和地址给客户端,客户端拿着id和地址去找存储服务要数据,
文件上传一般我们是绕过网关的,这样做是避免引发带宽问题,一般我会在Nginx里配置一个service专门用于文件上传的,同时限制文件上传的大小和类型,还会配置响应时间,文件上传经常遇到 403 Option 请求,这里就出现了跨域问题,在项目中我也不知道为啥 我在文件上传服务中配置了Cors的全局过滤的跨域解决方案但似乎不起效果,我就使用了一个注解 @CrossOrigin 注解,这个注解只对当前类使用有效
4.然后就是商品的规格管理这快
spu和sku
spu:StandardProdactUnit
sku:StockKeepingUnit
Spu:是指一组的有共同属性的商品集
Sku:是指Spu商品集中具体的特性而细分的每个商品
有点类似于对象和属性的样子,举个例子:IphoneX 是一个spu,而一个白色的256G,4G运行内存的Iphonex则是一个sku,
Spu是一个主表,Sku是一个子表,Spu表下一般有(id,title,subtitle等字段),而sku中就有(skuId,title,sku,price,image等字段),同时在项目中我们的价格都是以分作单位存储的,为啥用Bigint呢 是因为为了防止Folat数据失真的问题引起不必要的麻烦!
5.ES(ElasticSearch)