电商项目介绍
2.电商行业技术特点
①技术新:(NoSql推广首在社区网站和电商项目),发展快,需求推动技术的革新。
②技术范围广:除了java,像淘宝前端还使用了PHP,数据库MySQL或者oracle,nosql,服务器端使用Linux,服务器安全、系统安全
③分布式:以前是在一台机器上做运算,现在是分散到很多机器上,最后汇总起来。(集中式向分布式进行考虑)由需求来推动
④高并发、集群、负载均衡、高可用:由并发问题采用集群进行处理,其中,集群会涉及服务器的主从以及分布问题,使用负载均衡。(权重高低)高可用是对用户而言,用户的服务不中断(系统升级,服务不中断,淘宝每周更新2次)。
⑤海量数据:双11,570亿的背后,订单有多少?浏览次数有多少?商品会有多少?活动相关数据?
⑥业务复杂:不要简单的认为是:商品展示出来后,加入购物车后购买就完成了。后台特别复杂,比如优惠(包邮、满减)
⑦系统安全:系统上线必须通过系统安全部门审核通过。前年CSDN数据泄露。快捷酒店数据泄露(通过身份证就可以查看你的开房记录)。近几年,安全意识逐步在提高。
电商行业的一些概念
1、 B2C:商家对客户,京东、当当、发展为B2C平台,天猫(B2C平台 淘宝商城由马云提出,率先发展为平台),1号店也是(在上海)
2、 B2B:商家对商家,阿里巴巴(不零售,只批发,淘宝很多商家都会去阿里巴巴进货);
3、 C2C:个人对个人,淘宝市场,淘宝,商城;
系统功能
本商城系统是一个综合性的B2C平台,类似京东商城、天猫商城。
会员可以在商城浏览商品、下订单,以及参加各种活动。
商家可以在入住淘淘商城,在该平台上开店出售自己的商品,并且得到淘淘商城提供的可靠的服务。
管理员、运营可以在平台后台管理系统中管理商品、订单、会员等。
客服可以在后台管理系统中做项目需要知道哪些java基础处理用户的询问以及投诉。

首先我们要有商品,管理员可以在系统中管理商品,用户可以查看商品。
商品多了之后要有类目模块,管理员可以管理类目信息,用户可以根据类目检索商品。
有了商品之后,要有人(会员)去买东西,普通用户注册为会员,会员可以登录到系统管理自己的信息(密码等)
买了之后会生成订单,会员可以购买商品并且可以下单,管理员可以管理订单。
有了订单之后需要支付(在线支付/货到付款)
……
这样,我们就可以把整个电商项目的功能记清楚了!
分布式系统架构
左图为分布式系统架构,右图为传统架构!

各个系统说明:
后台管理系统:管理商品、订单、类目、商品规格属性、用户管理以及内容发布等功能。
前台系统:用户可以在前台系统中进行注册、登录、浏览商品、首页、下单等操作。
会员系统:用户可以在该系统中查询已下的订单、收藏的商品、我的优惠券、团购等信息。
订单系统:提供下单、查询订单、修改订单状态、定时处理订单。
搜索系统:提供商品的搜索功能。
单点登录系统:为多个系统之间提供用户登录凭证以及查询登录用户的信息。
谈到分布式架构,我们必须对比传统架构才能彰显其优势。
①最为明显的一点,在传统的架构中,如果某个功能需要进行维护,那么我们必须停掉整个服务,这对于公司的运营会造成损失。分布式系统在核心功能模块使用单独服务器,维护部分模块不影响用户的其他操作。
②在海量数据处理方面,传统架构显得比较乏力;分布式系统架构采用服务器集群,使用负载均衡,海量数据处理游刃有余!
③在性能(检索)以及维护方面,分布式系统架构也有较为明显的优势。
6.本系统人员配置情况
l 产品经理:3人,确定需求以及给出产品原型图。
l 项目经理:1人,项目管理。
l 前端团队:3人,根据产品经理给出的原型制作静态页面。
l 后端团队:20人,实现产品功能。
l 测试团队:3人,测试所有的功能。
l 运维团队:2人,项目的发布以及维护。
7.开发流程

此图不做详细解释(就业指导课已进行详细说明,注意整个流程中容易被问到的问题)
8.后台开发环境


整个开发沿着主线进行,在一个版本定型后,前一个版本出现bug,那么此时会对bug进行修复,投入使用的依旧是之前定型的那个版本,待前一个版本的bug修复好了之后,会定义一个新的版本,主线不会改变,如果改动不大,那么只需修订问题,继续沿用此版本(1.0.x),只有出现较大改动时,才会升级一个新的版本号(1.1.x)。所有动作,交替进行,沿主线向前推进!
9.涉及技术
l Spring、SpringMVC、Mybatis
l JSP、JSTL、jQuery、jQuery plugin、EasyUI、KindEditor(富文本编辑器)、CSS+DIV
l Redis(缓存服务器)
l Lucene、Solr(搜索)
l httpclient(调用系统服务)
l Mysql
l Nginx(web服务器)
l Quartz(定时任务)
l RabbitMQ(消息队列)
技术详解见其它章节,未接触技术点(标背景色技术点)将在本项目后续内容中进行介绍。
10.开发工具和环境
l Eclipse 4.4.1
l Maven 3.2.3
l Tomcat 7.0.47(Maven Tomcat Plugin)
l JDK 1.7
l Mysql 5.6
l Nginx 1.5.1
l Redis 2.8.9
l Win7 操作系统
l SVN(版本管理)
此章节,需要注意所有开发工具的版本号要对应(一致),否则会出现冲突问题,面试大忌!(常识:电商项目火起来的时间不是很久,在开发的时候,很多开发工具和环境不像之前那些传统系统那么老旧,这点一定要引起注意!)
电商项目面试问题
项目介绍
①属于B2C平台----商家对客户
②系统的用途,主要是提供B2C的平台,其中自营商品也有商家入住,类似天猫。
③系统架构,采用分布式的系统架构,其中前台系统和单点登录系统采用了集群的方式部署,在后台管理系统中采用了Maven的多模块化的管理,其中采用了水平切分的方式,将pojo、dao、service、web分层开发,这样做的好处就是可以重用性更高。
系统内部接口调用采用Httpclient,并且使用Httpclient的连接池技术,接口提供端采用RESTful方式的接口定义;
系统之间的通知机制采用MQ的方式,使用RabbitMQ的实现,使用了RabbitMQ的消息订阅模式的消息机制;
系统的接口还对JS的跨域做了支持,采用了jsonp的解决方法,在后台接口中扩展了spirng提供的jackson数据转化器实现;
④部署方面,采用了Nginx+tomcat的模式,其中nginx的作用一方面是做反向代理、负载均衡、另一方面是做图片等静态资源的服务器。
项目介绍应该从这个项目的模式、功能、架构、解决了什么问题、部署以及投入使用情况来说。
2.整个项目的架构如何?
一般情况这个问题要从两个方面去回答,从技术架构和功能架构去谈。
技术架构:本项目使用主流框架spring+springmvc+mybatis进行开发,采用分布式的系统架构,前台系统和单点登录系统采用了集群的方式部署,后台管理系统中采用了Maven的多模块化的管理,其中采用了水平切分的方式,将pojo、dao、service、web分层开发,这样做的好处就是可以重用性更高。系统内部接口调用采用Httpclient,并且使用Httpclient的连接池技术,接口提供端采用RESTful方式的接口定义;系统之间的通知机制采用MQ的方式,使用RabbitMQ的实现,使用了RabbitMQ的消息订阅模式的消息机制;系统的接口还对JS的跨域做了支持,采用了jsonp的解决方法,在后台接口中扩展了spirng提供的jackson数据转化器实现;搜索系统使用了solr实现,在保证系统高性能的前提下,尽可能为公司节约成本,我们使用MySQL数据库进行集群(oracle收费)。在部署方面,采用了Nginx+tomcat的模式,其中nginx的作用一方面是做反向代理、负载均衡、另一方面是做图片等静态资源的服务器。
功能架构:分布式系统架构

各个系统说明:
后台管理系统:管理商品、订单、类目、商品规格属性、用户管理以及内容发布等功能。
前台系统:用户可以在前台系统中进行注册、登录、浏览商品、首页、下单等操作。
会员系统:用户可以在该系统中查询已下的订单、收藏的商品、我的优惠券、团购等信息。
订单系统:提供下单、查询订单、修改订单状态、定时处理订单。
搜索系统:提供商品的搜索功能。
单点登录系统:为多个系统之间提供用户登录凭证以及查询登录用户的信息。
谈到分布式架构,我们必须对比传统架构才能彰显其优势。
①最为明显的一点,在传统的架构中,如果某个功能需要进行维护,那么我们必须停掉整个服务,这对于公司的运营会造成损失。分布式系统在核心功能模块使用单独服务器,维护部分模块不影响用户的其他操作。
②在海量数据处理方面,传统架构显得比较乏力;分布式系统架构采用服务器集群,使用负载均衡,海量数据处理游刃有余!
③在性能(检索)以及维护方面,分布式系统架构也有较为明显的优势。
传统架构:

3.这个项目为用户提供了哪些服务?包括哪些功能?
u 商品管理模块:其中包括品牌管理,属性管理商品录入/上下架管理,商品添加审核,静态页面发布
u 订单模块:其中包括使用activiti工作流订单的查询和订单的流转,定时作废
u 商品前台首页:其中主要负责首页商品列表筛选,首页上动态展示筛选条件,点击每一个筛选条件下面的商品列表要做联动
u 单品页面:采用freemarker来实现页面静态化,展示商品详情信息和商品购买,该页面采用静态化以减轻系统压力,使用了cxf框架发布服务
u 提交订单页面:提交用户的订单信息, 处理并发问题。
u 个人中心,包括用户的登录,个人信息的管理,收货地址的管理,用户所下的订单的管理
u 购物车:把购物车的信息存在cookie里面管理
4.你承担这个项目的哪些核心模块?
在项目中主要负责相关系统的开发,主要有:
1) 后台管理系统,主要实现商品管理、商品规格参数管理、订单管理、会员管理等、CMS(内容管理系统)等,并且提供了跨域支持;
2) 前台系统,主要是面向用户访问,使用Httpclient和后台系统接口做交互,并且该系统在部署上采用集群的方式;
3) 单点登录系统,主要是提供集中用户登录凭证的集中解决方案,提供和用户信息相关的接口,比如说用户注册、查询等接口。
4) 订单系统,主要是提供和订单相关的业务接口,在订单系统了做了严格的数据校验以及高并发写的支持(这里可以说使用队列实现),并且使用了Quartz定时任务实现对订单的定时扫描,比如说关闭超时未付款的订单;
5) 搜索系统,主要是提供商品的搜索,采用开源企业级系统Solr实现,采用了MQ机制保证了商品数据可以及时同步到solr中;
6) 会员系统,主要是维护用户的信息,已购买订单、优惠券、系统消息、修改密码、绑定手机等功能;
7) 缓存,主要是用Redis实现,并且对Redis做了集群来保证Redis服务的高可用。8) 支付系统,主要是负责订单的支付、对账等功能,主要是对接了支付宝的接口;
5.这些模块的实现思路说一下?
①商品管理模块
品牌管理:
主要掌握的核心是品牌的添加
l 图片服务器的搭建,
l 上传图片到图片服务器
l 表单的验证,离开焦点的验证,点击完成时的验证,后台服务器的ajax验证,表单规范
l 防止表单的二次提交
l 编辑时不需要修改品牌名,区别readOnly和disabled
图片服务器的搭建

3. 编写上传到图片服务器的代码
由于应用服务器与图片服务器出于不同的两台机器之中,所以可以提高系统的性能,能起到负载均衡的作用。上传图片时使用Jersey客户端API调用REST风格的Web服务,Jersey1是一个开源的、可以用于生产环境的JAX-RS(RESTful Web Services 的Java API 规范,JSR-311)实现。通Jersey 可以很方便的使用Java来创建一个RESTful Web Services。
byte[] fileByte = commFile.getBytes();
//创建客服端,基于webservice
Client client = Client.create();
//指定资源路径
WebResource webResource = client.resource(Constants.picPath+fileName);
//使用put的请求方式把资源文件放到资源服务器上
webResource.put(String.class, fileByte);
前台使用ajax提交表单,需要使用jquery的jquery.form.js插件
$("#form").ajaxSubmit({
url:url,
type:"post",
dataType:"text",
data:{
...
},
//beforeSubmit:validate,
success:function(responseText){
var obj = $.parseJSON(responseText);
},
error:function(){
}
});
4. 图片服务器中Upload文件夹中随便建立一个文件,防止空文件夹的情况下发布后upload消失
表单验证1. 提交时做验证
做好约定,每个文本中设置reg属性和tip自定义的属性,reg存放正则表达式,tip中存放不合法时的提示信息,还有品牌名称重复的验证。
reg2,tip属于自定义的属性,这种定义方式方便使用jquery的属性选择器
<p>
<label><samp>*</samp>品牌名称:</label>
<input type="text" id="brandName" name="brandName" class="text state" reg2="^[a-zA-Z0-9一-龥]{1,20}$" tip="必须是中英文或数字字符,长度1-20"/>
<span></span>
</p>
2. 在表单提交时做验证使用$(“form”).submit(function(){ return false });,必填字段和非必填的字段需要区别对待
$("#form111").submit(function(){
var isSubmit = true;
$(this).find("[reg2]").each(function(){
var regStr = $(this).attr("reg2");
//剪掉值中的两侧的字符串
var value = $.trim($(this).val());
var tip = $(this).attr("tip");
//创建正则表达式的对象
var reg = new RegExp(regStr);
if(!reg.test(value)){
$(this).next("span").html(tip);
isSubmit = false;
//跳出循环,在jquery的each语句之中跳出循环使用return false; 如果在原生js里面可使用break;, return;:代表终止执行程序
return false;
}
});
$(this).find("[reg1]").each(function(){
var regStr = $(this).attr("reg1");
var value = $.trim($(this).val());
var tip = $(this).attr("tip");
var reg = new RegExp(regStr);
if(value != null && value != ""){
if(!reg.test(value)){
$(this).next("span").html(tip);
isSubmit = false;
return false;
}
}
});
return isSubmit;
});
3. 使用离焦事件做友好的提示
$("input[reg2]").blur(function(){
var regStr = $(this).attr("reg2");
var value = $.trim($(this).val());
var tip = $(this).attr("tip");
var reg = new RegExp(regStr);
if(!reg.test(value)){
$(this).next("span").html(tip);
}else{
$(this).next("span").html("");
}
});
4. 表单的二次提交处理
l 锁屏
l 锁按钮
②商品的查询商品查询需要组合条件加分页查询
l 组合条件:品牌,审核状态,商品名称,需要动态sql
<select id="queryItemByCondtion" resultMap="BaseResultMap" parameterType="map">
select *
from (select a.*, rownum rm
from (
select *
from eb_item ei
<where>
<if test="brandId != null">
ei.brand_id = #{brandId}
</if>
<if test="auditStatus != null">
and ei.audit_status = #{auditStatus}
</if>
<if test="showStatus != null">
and ei.show_status = #{showStatus}
</if>
<if test="itemName != null">
and ei.item_name like '%${itemName}%'
</if>
</where>
order by ei.item_id desc) a
<![CDATA[
where rownum < #{endNum}) b
where b.rm > #{startNum}
]]>
</select>
-- 查询大于当前页首行号,主要解决 oracle 的 rownum 不支持大于号的问题select *
from (
--查询小于当前最大行号的数据
select rownum rm,a.*
from (
--第一个select查询所有的业务数据
select * from eb_item
) a
where rownum < 21) b
where b.rm > 10
l 分页查询
1. 查询结果集的sql,传入开始行数和结束的行数
select *
from (select a.*, rownum rm
from (
...
内部sql
...
) a where rownum < #{endNum}) b
where b.rm > #{startNum}
2. 使用内部sql查询结果集的总条数
3. 使用分页工具类,创建page对象更换每次的数据总条数和当前页数和每页的条数,查询出结果集后把结果集注入到page对象之中
public class Page {
int totalCount = 0;
int pageSize = 10;
int currentPageNo = 1;
int startNum = 0;
int endNum = 11;
public Page(int totalCount, int pageSize, int currentPageNo) {
super();
this.totalCount = totalCount;
this.pageSize = pageSize;
this.currentPageNo = currentPageNo;
}
public int getStartNum(){
return (currentPageNo - 1) * pageSize;
}
public int getEndNum(){
return currentPageNo * pageSize + 1;
}
public int getTotalPage(){
int totalPage = totalCount/pageSize;
if(totalPage == 0 || totalCount%pageSize != 0){
totalPage ++;
}
return totalPage;
}
public int getNextPage(){
if(currentPageNo >= getTotalPage()){
return currentPageNo;
}else{
return currentPageNo + 1;
}
}
public int getPrePage(){
if(currentPageNo <= 1){
return currentPageNo;
}else{
return currentPageNo - 1;
}
}
List<?> list;
public List<?> getList() {
return list;
}
public void setList(List<?> list) {
this.list = list;
}
public int getTotalCount() {
return totalCount;
}
public void setTotalCount(int totalCount) {
this.totalCount = totalCount;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public int getCurrentPageNo() {
return currentPageNo;
}

public void setCurrentPageNo(int currentPageNo) {
this.currentPageNo = currentPageNo;
}
public void setStartNum(int startNum) {
this.startNum = startNum;
}
public void setEndNum(int endNum) {
this.endNum = endNum;
}
}
4. 制作前端样式
var currentPageNo = parseInt($("#currentPageNo").val());
var totalCount = parseInt($("#totalCount").val());
var totalPage = parseInt($("#totalPage").val());
$("#pagePiece").html(totalCount);
$("#pageTotal").html(currentPageNo+"/"+totalPage);
if(currentPageNo <= 1){
$("#previous").hide();
}else{
$("#previous").show();
}
if(currentPageNo >= totalPage){
$("#next").hide();
}else{
$("#next").show();
}
$("#next").click(function(){
$("#pageNo").val(parseInt(currentPageNo)+1);
$("#form1").submit();
});
$("#previous").click(function(){
$("#pageNo").val(parseInt(currentPageNo)-1);
$("#form1").submit();
});
Oracle 分页sql的描述:
1.最内层的写查询当前表的全量即可
2.对于oracle数据库分页需要依赖于rownum,但是rownum不支持大于号,但是支持小于号,可以rownum小于结束行号查询出来一个结果集(在全量的外层套一个select,它的结果集需要把rownum作为结果返回)
3.在第二步的结果集基础上再做一次查询,查询条件以第二步查询出来的rownum的值作为条件大于开始行号即可
③商品发布Console和portal是分开部署在两台服务器上,发布需要在console端去控制,但是生成的静态化的文件要发布到portal的工程之中,所以发布的服务要在portal上,但是要在console中来调用,异构之间的调用要使用webservice。
1. 采用cxf的webservice框架来整合spring
2. 在web.xml中来配置cxf的核心servlet
<servlet>
<servlet-name>cxfServlet</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>cxfServlet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
3. 创建服务的接口和接口的实现类,注意接口上加上@WebService注解
4. 创建cxf的核心配置文件cxf-servlet.xml,配置带有接口的webservice服务使用<jaxws:server>标签
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
xmlns:jaxrs="http://cxf.apache.org/jaxrs" xmlns:cxf="http://cxf.apache.org/core"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd">
<!-- 引入CXF Bean定义如下,早期的版本中使用 -->
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<jaxws:server id="publish" address="/publish" serviceClass="cn.itcast.ecps.ws.service.EbItemWSService">
<jaxws:serviceBean>
<bean class="cn.itcast.ecps.ws.service.impl.EbItemWSServiceImpl"></bean>
</jaxws:serviceBean>
<!-- 输入输出的拦截器 -->
<jaxws:inInterceptors>
<bean class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean>
</jaxws:inInterceptors>
<jaxws:outInterceptors>
<bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"></bean>
</jaxws:outInterceptors>
</jaxws:server>
</beans>
5. 修改cxf-servlet.xml的位置,在spring的listener中加载
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath*:beans.xml,classpath*:cxf-servlet.xml
</param-value>
</context-param>
6. 启动服务器发布webservice的服务,使用wsdl2java生成客户端的代码
Wsdl2java –d . –p cn.itcast.ecps.ws.stub
http://.........wsdl?
7. 在客户端调用。
④订单管理模块1) 流程设计
2) 订单整合activiti工作流
1.activiti流程和spring整合
创建activiti-context.xml文件
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
<!-- 数据源 -->
<property name="dataSource" ref="dataSource" />
<!-- 配置事务管理器,统一事务 -->
<property name="transactionManager" ref="txManager" />
<!-- 设置建表策略 -->
<property name="databaseSchemaUpdate" value="true" />
</bean>
<bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
<property name="processEngineConfiguration" ref="processEngineConfiguration" />
</bean>
<bean id="repositoryService" factory-bean="processEngine" factory-method="getRepositoryService" />
<bean id="runtimeService" factory-bean="processEngine" factory-method="getRuntimeService" />
<bean id="taskService" factory-bean="processEngine" factory-method="getTaskService" />
<bean id="historyService" factory-bean="processEngine" factory-method="getHistoryService" />
</beans>
1. 画流程图
2. 创建流程服务类
package cn.itcast.service.impl;
import java.io.File;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.DeploymentBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import cn.itcast.service.IWorkFlowService;
//@Service
public class WorkflowServiceImpl implements IWorkFlowService {
@Autowired
RepositoryService repositoryService;
/*public RepositoryService getRepositoryService() {
return repositoryService;
}
public void setRepositoryService(RepositoryService repositoryService) {
this.repositoryService = repositoryService;
}*/
public void deployFlow() {
//创建发布流程配置对象
DeploymentBuilder builder = repositoryService.createDeployment();
//指定流程资源路径
builder.addClasspathResource("activit-orderflow.bpmn").addClasspathResource("activit-orderflow.png");
builder.deploy();
}
}
1. 部署流程
2. 查询业务任务
3. 办理任务
6.项目中哪些功能模块涉及了大数据量访问?你是如何解决的?系统前台是互联网上的用户访问的,会有大量用户来访问。
假定有 1w 个人打开你的网站来订商品,问你如何解决并发问题 ( 可扩展到任何高并发网站要考虑的并发读写问题 )
问题,1w个人来访问,商品没出去前要保证大家都能看到有商品,不可能一个人在看到商品的时候别人就不能看了。到底谁能抢到,那得看这个人的“运气”(网络快慢等)
其次考虑的问题,并发,1w个人同时点击购买,到底谁能成交?总共只有一张商品。
Update eb_sku t sett.stock = t.stock – 1 where t.sku_id = #{skuId} and t.stock > 0
Update eb_sku t set t.sale = t.sale +1 where t.sku_id = #{skuId}
首先我们容易想到和并发相关的几个方案 : 锁同步
同步更多指的是应用程序的层面,多个线程进来,只能一个一个的访问,java中指的是syncrinized关键字。锁也有2个层面,一个是java中谈到的对象锁,用于线程同步;另外一个层面是数据库的锁;如果是分布式的系统,显然只能利用数据库端的锁来实现。
假定我们采用了同步机制或者数据库物理锁机制,如何保证1w个人还能同时看到有商品,显然会牺牲性能,在高并发网站中是不可取的。使用hibernate后我们提出了另外一个概念:
乐观锁(一定要用)、
悲观锁(即传统的物理锁);采用乐观锁即可解决此问题。乐观锁意思是不锁定表的情况下,利用业务的控制来解决并发问题,这样即保证数据的并发可读性又保证保存数据的排他性,保证性能的同时解决了并发带来的脏数据问题。
hibernate中如何实现乐观锁:
前提:在现有表当中增加一个冗余字段,version版本号, long类型
原理:
1)只有当前版本号》=数据库表版本号,才能提交
2)提交成功后,版本号version ++
实现很简单:在ormapping增加一属性
-lock="version"即可,以下是样例片段 optimistic<hibernate-mapping>
<class name="com.insigma.stock.ABC" optimistic-lock="version" table="T_Stock" schema="STOCK">
</hibernate-mapping>
更新的时候给版本号字段加上 1 ,然后 UPDATE 会返回一个更新结果的行数,通过这个行数去判断。Sku_id
sale
Version(乐观锁的标志字段)
1
100
1
7.在做这个项目的时候你碰到了哪些问题?你是怎么解决的?
8.你做完这个项目后有什么收获?
9.你这个项目中使用什么构建的?多模块开发是如何划分的呢?为什么要这么做?
10.你觉得在文件上传功能上面需要注意什么?
11.在你这个项目中,是如何设计商品规格的?
img src='https://s2.51cto.com/images/blog//_64e4259c9e81d86912.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=/resize,m_fixed,w_1184' alt='Java电子商务后台管理系统项目开发技术 java电商项目介绍_分布式系统_10' style="width: 694px; visibility: visible;">
12.在这个项目中你是如何实现跨系统调用的?
br> 1、 Ajax,走前台js,通过jsonp来跨域,关于jsonp请参考:
br> jsonp,部署子域名的情况
br> 需要在SpringMVC中扩展MappingJackson2HttpMessageConverter,支持jsonp。跨域问题,因为我们是子域名访问子系统接口的,采用jsonp解决;
br> 掌握spring和Httpclient的集成
13.你这个项目中CMS系统是如何设计的,简单的说一下其设计思想?
14.在这个项目中,你们主要使用什么样的数据格式来进行数据的传输的?你对JSON了解么?能说说JSON对象如何转换成Java对象的?
15.单点系统的设计思想你了解吗?他在系统架构中的作用是什么?位置如何?
img src='https://s2.51cto.com/images/blog//_64e4259cba6e.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=/resize,m_fixed,w_1184' alt='Java电子商务后台管理系统项目开发技术 java电商项目介绍_搜索_11' style="width: 640px; visibility: visible;">
img src='https://s2.51cto.com/images/blog//_64e4259cd60d075403.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=/resize,m_fixed,w_1184' alt='Java电子商务后台管理系统项目开发技术 java电商项目介绍_数据_12' style="width: 604px; visibility: visible;">
16.你们这个项目中订单ID是怎么生成的?我们公司最近打算做一个电商项目,如果让你设计这块,你会考虑哪些问题?
17.各个服务器的时间不统一怎么办?
18.在问题17的基础上,可能存在毫秒级的偏差情况,怎么办?
br> 用户ID+当前系统的时间戳+随机数(3~4位) 问题:太长? 把时间戳中的2014中的20拿掉;
19.你们线上部署时什么样的,能画一下吗?
img src='https://s2.51cto.com/images/blog//_64e4259cf0.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=/resize,m_fixed,w_1184' alt='Java电子商务后台管理系统项目开发技术 java电商项目介绍_分布式系统_13' style="width: 755px; visibility: visible;">
20.多台tomcat之间的session是怎么同步的?
21.如何解决并发问题的?
22.你们生产环境的服务器有多少台?
23.数据备份是怎么做的?有没有做读写分离?
24.你们服务器不止一台吧,那么你们的session是怎么同步的?
25.你们使用什么做支付的?如果使用易宝做支付,请求超时了怎么处理?
br> ②给订单标识付款异常状态,并且发出警告(邮件、短信)给相关人员。
26.
你刚才不是说付款成功后易宝会有数据返回吗?如果付款后易宝没有返回,或者返回超时了,但是钱又已经扣了,你怎么办?
br> ②使用定时任务处理;
27.
你们怎么做退款功能的,要多长时间才能把钱退回给用户?
28.你前台
portal
采用
4
台服务器集群部署 那你数据库有几台服务器?如果前台高并发访问性能提上去了,那数据库会不会造成一个瓶颈,这一块你是怎么处理的?
29.你购物车存cookie
里边可以实现不登录就可以使用购物车,那么我现在没有登录把商品存购物车了,然后登录了, 然后我换台电脑并且登录了还能不能看见我购物车的信息?如果看不到怎么做到
cookie
同步,就是在另外一台电脑上可以看到购物车信息
img src='https://s2.51cto.com/images/blog//_64e4259d.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=/resize,m_fixed,w_1184' alt='Java电子商务后台管理系统项目开发技术 java电商项目介绍_搜索_14' style="width: 798px; visibility: visible;">
30.点一个链接访问到一个页面,这个页面上既有静态数据,又有动态数据(需要查数据库的),打开这个页面的时候就是很慢但是也能打开。怎么解决这个问题,怎么优化?
img src='https://s2.51cto.com/images/blog//_64e4259d37c.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=/resize,m_fixed,w_1184' alt='Java电子商务后台管理系统项目开发技术 java电商项目介绍_数据_15' style="width: 684px; visibility: visible;">
31.如果用户一直向购物车添加商品怎么办?并且他添加一次你查询一次数据库?互联网上用户那么多,这样会对数据库造成很大压力你怎么办?
img src='https://s2.51cto.com/images/blog//_64e4259d59f.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=/resize,m_fixed,w_1184' alt='Java电子商务后台管理系统项目开发技术 java电商项目介绍_数据_16' style="width: 530px; visibility: visible;">
img src='https://s2.51cto.com/images/blog//_64e4259d8799b53528.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=/resize,m_fixed,w_1184' alt='Java电子商务后台管理系统项目开发技术 java电商项目介绍_搜索_17' style="width: 683px; visibility: visible;">
32.做促销时,商品详情页面的静态页面如何处理价格问题。
img src='https://s2.51cto.com/images/blog//_64e4259da4b.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=/resize,m_fixed,w_1184' alt='Java电子商务后台管理系统项目开发技术 java电商项目介绍_搜索_18' style="width: 773px; visibility: visible;">
33.商品搜索框的搜索联想如何实现?比如输入“羽绒” ,然后输入框下会列出很多关于羽绒服的搜索条件 “羽绒服男正品折扣 ”等等。
34.一个电商项目,在tomcat里面部署要打几个war包?
35.你说你用了
redis
缓存,你
redis
存的是什么格式的数据,是怎么存的?
36.购物车知识补充(在设计购物车时需要注意哪些细节)
①购物车是消费的最后一环
②购物车隐含的对比收藏功能
③购物车的重交易属性
①登录环节不要放在加入购物车前
②自动勾选用户本次挑选的商品
③陈列展示,注意沉底商品
④归类展示,可能增加购买
⑤价格和优惠的提醒
①还差一点就可以有优惠啦!
②提醒用户有些商品你真的可以买了
有关调查显示,加入购物车而没有购买的,在4小时以内提醒用户,会有27%的唤醒率哦!
所以需要提醒的几个点有:
生成订单但是还没支付的
商品有优惠信息
商品库存不足的
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/2410.html