一、应用SpringBoot完成基础项目搭建

2-3 Mybatis接入SpringBoot项目

2-4 Mybatis自动生成器使用方式

在使用Maven自动生成接口UserDOMapper和UserPasswordDoMapper后,需要在接口文件上加上@Mapper注解,让DemoMapper能够让别的类进行引用。

使用@Mapper注解的缺点:
·直接在Mapper类上面添加注解@Mapper,这种方式要求每一个mapper类都需要添加此注解,麻烦。
改进方法:使用@MapperScan注解

此时发现,下面还是显示UserDOMapper未找到。我们还要需要在UserDOMapper上加上注解@Repository,然后就能够正常运行了,与单独加上@Mapper注解的效果一样。

对比:@Mapper注解单独使用就可以把它交给spring管理了,并且别的类可以直接引用。
@Repository也可以把它交给sprin管理,但是在获取该容器中的对象时,需要用@MapperScan扫描到此文件,或者该文件所在的package。

3-1 使用SpringMVC方式开发用户信息

  1. 首先在userservice的实例中UserServiceImpl中:
    1) 通过userDOMapper获得userDO对象(by 传入的id)
    2) 通过userPasswordDOMapper获得userPasswordDO对象(by userDO拿到id)
    3) 通过userDO和usePasswordDO得到userModel(重点方法BeanUtils.copyProperties)
  2. 在UserController中传入参数id给userService.getUserById()方法即可得到userModel,但此时的userModel(里面包含了全部用户信息,包括注册方式和加密后的密码等)并不能直接供UI使用,因此需要在controller下面创建一个viewobject包,创建一个UserVO对象,里面的用户信息是能够传递给UI的部分。
  3. 在UserController中得到userModel后将其转化成UserVO对象,然后供UI使用。(重点方法BeanUtils.copyProperties)。

3-2 定义通用的返回对象–返回正确信息

在上一节中,如果信息在传递过程中都正确,则返回没有问题,但是如果整个传递过程中出现一点问题,前端就只能显示错误信息 500。
创建respons包,创建CommonReturnType类,定义两个属性 status和data
//若status=success,则data内部返回前端需要的json数据
//若status=fail,则data内使用通用的错误码格式
//定义一个通用的创建方法
//如果不带status,则对应的status就是success,然后通过下面的同名函数返回type
public static CommonReturnType creat(Object result)
然后修改UserController中的代码,不要直接返回UserVO,通过CommonReturnType.creat()方法返回status和data(status就是success,data就是UserVO)。注意:这里是返回的正确信息,下面再讲错误信息的处理

3-3 定义通用的返回对象–返回错误信息

首先创建一个名叫error的包,在里面创建一个接口CommonError

  1. 在接口里面添加三个方法:
    1) public int getErrCode(); //用于获取错误码
    2) public String getErrMsg(); //用于获取错误信息
    3) public CommonError setErrMsg(String errMsg); //用于设置自定义错误信息
  2. 然后创建一个枚举类EmBusinessError实现上面的接口,
    定义一个通用错误类型00001,PARAMETER_VALIDATION_ERROR(00001,“参数不合法”),和一个1000开头的用户信息错误,USER_NOT_EXIST(10001,“用户不存在”),
    在枚举类中添加两个属性 int errCode;和String errMsg;添加一个全参构造器并重写三个方法。
  3. 最后创建一个异常类BusinessError实现上述接口,
    在异常类中添加一个属性CommonError,添加两个构造器,一个接收EmBusinessError的参数构造业务异常,一个接收自定义errMsg的参数构造业务异常,最后重写三个方法。

3-4 定义通用的返回对象–异常处理01

在UserController中定义exceptionhandler解决未被controller层吸收的exception

   @ExceptionHandler(Exception.class)//指明收到的是跟类异常就会进入该处理环节@ResponseStatus(HttpStatus.OK)//业务逻辑处理上的问题,而不是服务的不能处理的错误(500),返回错误码200@ResponseBody//不加该注解,只能寻找本地页面下的一些文件,加上该注解后将返回值以特定的格式(json格式)返回到response的body区域public Object handlerException(HttpServletRequest request, Exception ex){······return commonReturnType;}

3-5 定义通用的返回对象–异常处理02

上面返回的信息非常多,下面把错误信息封装到map中让其只返回errCode和errMsg。
首先把ex强转成BusinessException类,然后用把它的errCode和errMsg放到Map中,最后用CommonReturnType类中的creat方法生成公共错误类型并返回。
优化:

  1. 首先得判断ex是不是BusinessException的一种(instanceof)
    如果是的话正常返回,否则用同样的方法返回“未知错误”
  2. 这种异常处理是所有controller都想用的公用逻辑,不应该放在UserController里面
    在controller下面创建BaseController类,把UserController中公共的异常处理方法放到基类BaseController里面,然让UserController继承BaseController即可。

3-6 用户模型管理–otp验证码获取

在UsrController中创建HttpServletRequest对象并自动注入(@使用Autowired报错将其换成@Resource即可),然后创建getotp方法,返回CommonReturnType类型的对象。
注意:该方法上面加上注释@RequestMapping,不仅要设置value,还需呀设置method为RequestMethod.POST方法,指定getotp方法必须要映射到http的post请求才会生效。
1)需要按照一定的规则生成OTP验证码,这里使用随机数,并将其传递给otpCode
2)将OTP验证码同对应用户手机号关联,使用httpsession的方式绑定手机号与otpCode
3)将OTP验证码通过短信通道发送给用户(需要购买第三方短信通道,以httppost的方式将短信模板的内容post给用户手机)
重点:httpServletRequest通过bean的方式注入进来,bean的方式注入进来就代表其是一个单例模式,单例模式一个request如何支持多个用户的并发访问? 原因:这里注入的request实际上是一个proxy(代理),它的内部拥有ThreadLocal(线程局部变量)方式的map,让用户在每个线程当中处理自己对应的request,并且有ThreadLocal清楚机制。(当bean需要request对象时,通过该代理获得request对象。调用request的方法method时,实际上是调用了由objectFactory.getObject()生成的对象的method方法;objectFactory.getObject()生成的对象才是真正的request对象。objectFactory的类型为WebApplicationContextUtils的内部类RequestObjectFactory;而RequestObjectFactory要获得request对象需要先调用currentRequestAttributes()方法获得RequestAttributes对象,生成RequestAttributes对象的核心代码在类RequestContextHolder中,生成的RequestAttributes对象是线程局部变量(ThreadLocal),因此request对象也是线程局部变量;这就保证了request对象的线程安全性。)。

3-8 用户模型管理–getotp页面实现

界面交互使用jquery,引入jquery的js

<script src="static/assets/global/plugins/jquery-1.11.0.min.js" type="text/javascript"></script>

注意这里不能使用自闭合,否则页面显示不出来。

3-9 用户模型管理–getotp页面美化

1)引入css中的bootstrap进行上色,rel为样式表;
2)引入css中的components,让button使用自带的component的样式;
3)要做的是login页面,引入css中的login。

<link href="static/assets/global/plugins/bootstrap/css/bootstrap.min.css" rel="stylesheet" type="text/css"/>
<link href="static/assets/global/css/components.css" rel="stylesheet" type="text/css"/>
<link href="static/assets/admin/pages/css/login.css" rel="stylesheet" type="text/css"/>

3-10 用户模型管理–用户注册功能实现01

在UserController中创建register()方法,返回CommonReturnType类型,传入telephone、otpCode等所有个人信息。

  1. 在UserService中定义register()方法,传入参数userModel
  2. 在UserServiceImpl中重写该方法
    1)首先要进行两次判空(userModel为空和其中的所有参数为空(这里用||进行判断,因为我们数据库中定义了所有属性都非空),后面使用hibernate中的validate方法来校验);
    2)创造两个方法,分别把userModel转化成userDO(使用copyProperties()方法)和userPasswordDO(直接set密码和userId);
    3)通过userDOMapper和userPasswordDOMapper中的insertSelective方法插入userDO和userPasswordDO;(注意:这里要使用insertSelective而不是insert方法。两者的区别在于,如果对于的字段是null,用insert操作就会覆盖掉数据库里的默认值,而insertSelective不会覆盖)
    重点:这里的userid是自动生成的(也就是传进来的userModel是没有id信息的),所以需要先把userDO插入到书库中,自动生成id后在通过userDO的get方法获得。在拿到id后对userModel设置其id然后才能将userModel转化为userPassworDo;
  3. 验证手机号和对应的otp相符合。
    1)通过httpServletRequest.getsession().getAttribute(telephone)拿到String类型的 inSessionOtpCode;
    2)通过druid连接池中的方法StringUtils.equals()判断otp验证码和inSessionOtpCode是否相等,不符合抛出异常,符合进入下一个流程;
  4. 用户注册流程
    1)new一个userModel,并调用set方法注入属性,注意密码一定要加密,这里使用MD5Encoder.encode()加密方法。
    2)调用userService.register()方法(这里调用接口中的方法,在实现类中将其插入到数据库中);然后返回CommonReturnType。

3-11 用户模型管理–用户注册功能实现02

遇到一个bug:突然发现mybatis-generator.xml中第四行“http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd”是红色的,但是之前是没有这个问题的,放鼠标放到右侧滑动那里的红色错误提示上不懂,等出现Fetch external resource点击即可。
第二个问题:老师没讲到,是user_password表中的id一定要选择自增。

1)在@CrossOrigin注解中加上参数(allowCredentials = “true”(需要配合前端设置xhrFields授信后使得跨域session共享),allowedHeaders = “※”(允许跨域传输所有的header参数,将用于使用token放入header域做session共享的跨域请求), originPatterns = “※”)让ajax请求实现跨域操作共享session,然后在前端发送ajax时指定xhrFields: {withCredentials: true}
2)修改加密方式,因为IDEA中的MD5加密方式只支持16位。
3)在UserDOMapper.xml文件中,insert里面要设置参数
keyProperty=“id” useGeneratedKeys="true"将自增id取出以便于转发给对应的userpassword
修改
优化:

  1. 防止手机号重复注册,在数据库中把telephone设置为unique,然后在插入userDO时使用try-catch捕获名为DuplicateKeyException的异常并抛出异常;

3-12 用户模型管理–用户注册功能实现

在UserController中添加方法login,传入参数telephone和password,返回类型为CommonReturnType。

  1. 入参校验,如果手机号或者密码错误直接抛出异常
  2. 用户登录服务,用来校验用户登录是否合法,在UserService接口中加入validateLogin(),传入参数telephone和encrptpassword,返回UserModel。在UserServiceImpl实现类中重写该方法。
    1)首先通过telephone得到userDO(这里需要在mapper中加入selectByTelephone()方法),如果userDO为空直接抛出异常;
    2)通过userDO的id得到userPasswordDO,并得到用户模型,最后通过模型得到加密后的密码并与输入密码对比,不匹配则抛出异常,匹配则返回用户模型。
  3. 在UserController中调用该方法得到用户模型。
  4. 将登录凭证加入到用户登录成功的session内(在进阶版中使用分布式的会话session机制解决在分布式环境下用户登录的问题,这里假设用户单点登录)
this.httpServletRequest.getSession().setAttribute("IS_LOGIN",true);
this.httpServletRequest.getSession().setAttribute("LOGIN_USER",userModel);
  1. 返回处理结果(CommonReturnType)

3-13 用户模型管理–优化校验规则

对于用于填写的个人信息,我们需要使其在合理的范围之内,这里使用Spring的Validator进行校验。
1)在UserModel的属性上面加上注解:
JSR提供的校验注解:

@Null   被注释的元素必须为 null
@NotNull    被注释的元素必须不为 null
@AssertTrue     被注释的元素必须为 true
@AssertFalse    被注释的元素必须为 false
@Min(value)     被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value)     被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value)  被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value)  被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max=, min=)   被注释的元素的大小必须在指定的范围内
@Digits (integer, fraction)     被注释的元素必须是一个数字,其值必须在可接受的范围内
@Past   被注释的元素必须是一个过去的日期
@Future     被注释的元素必须是一个将来的日期
@Pattern(regex=,flag=)  被注释的元素必须符合指定的正则表达式

Hibernate Validator提供的校验注解:

@NotBlank(message =)   验证字符串非null,且长度必须大于0
@Email  被注释的元素必须是电子邮箱地址
@Length(min=,max=)  被注释的字符串的大小必须在指定的范围内
@NotEmpty   被注释的字符串的必须非空
@Range(min=,max=,message=)  被注释的元素必须在合适的范围内

2)创建包validator并在下面创建类ValidationResult和类ValidatorImpl;
3)在ValidationResult类中添加属性hasErrors用于校验结果是否有错,添加ErrorMsgMap用于存放错误信息,然后通过方法getError()实现通用的通过格式化字符串信息获取错误结果。(注意这里的属性一定要赋初值防止出现空指针错误)
4)让ValidatorImpl类继承InitializingBean,添加属性validator,重写方法afterPropertiesSet(),通过工厂的初始化方式使其实例化得到validator;添加反法validate()实现校验方法并返回校验结果,传入参数为Object类型的bean,返回类型为ValidationResult;通过validator的validate方法得到错误集合constraintViolationSet,通过集合大小判断是否有错误,如果有错将hasErrors设置为true;然后遍历集合拿到errMsg和propertyName并传入到errorMsgMap中,然会结果。
5)将UserServiceImpl类中的注册校验换成新的通用校验方法。

4-1 商品模型管理–商品创建01

  1. 在model包里面新建Item类,加入商品属性,然后在数据库中添加相关属性,注意先想清楚哪些属性应该放在item表中,哪些属性放入item_stock表中,两个表怎么关联;
  2. 然后在mybatis-generator.xml中加入自动生成item和item_stock的Mapper、DO和xml文件的代码
    重点:一定要将生成与user和user_password相关的代码注释掉。
  3. 运行mybatis-generator自动生成item和item_stock的Mapper、DO和xml文件,在xml文件中的插入代码中加上useGeneratedKeys和keyProperty字段。

4-2 商品模型管理–商品创建02

  1. 在service中创建ItemService接口,添加三个方法
    1)创建商品,传入itemModel返回ItemModel;
    2)商品浏览列表,空参返回List;
    3)商品详情浏览,传入id,返回ItemModel。
  2. 在service下的impl中创建ItemServiceImpl类继承service中的接口,并重写三个方法。
    1)创建商品方法:首先进行入参校验,使用上面validator对传入的itemModel进行校验;然后转化itemmodel->dataobject,通过itemModel得到itemDO和itemStockDO(使用beanUtils中的copyProperties方法,注意这里要setprice为double类型);再将其写入数据库(使用mapper中的insertSelective方法),设置itemModel的id(id是自增产生的,在后面controller中创建商品的时候是不传入id参数的);最后通过id得到并返回该模型。
    2)商品详情浏览方法:首先使用mapper中的方法通过id得到itemDO,然后对itemDO进行校验(一定要进行判空校验),并且通过id得到itemStockDO;然后将dataobject->model,使用BeanUtils中的方法通过item DO得到itemModel,使用set方法设置模型的价格(这里要将double类型转化成BigDecimal类型)和库存;最后返回模型。
  3. 在controller中创建ItemController,在viewobject中创建ItemVO,在VO中设置可以对前端显示的属性。让ItemController继承BaseController方法(用于处理异常);加上@CrossOrigin注解处理跨域请求问题;添加创建商品的的方法,传入title等参数(注意这里没有id参数,这个参数是自增自动生成的),返回CommonReturnType;直接new一个model然后调用set方法传入参数,然后在调用创建商品的方法将其传进去再返回出来,最后将其转换成itemVO(是哦用BeanUtils中的方法)然后通过CommonReturnType的creat方法将其返回。
    重点:在实现类的创建商品方法中,转化itemmodel->dataobject方法中,只能先通过itemMoedl创建itemDO,然后将itemDO写入数据库之后,通过getid方法拿到相应id再对itemModel设置id,然后才能通过itemModel转化得到itemStockDO。因为id是自动生成的,只有入item库后才会自动生成id,因为是通过该id与item_stock关联的,所以设置好itemmodel的id后才能通过itemmodel转化得到itemStockDO

4-3 商品模型管理–商品创建03

在itemController方法中,添加商品浏览方法,传入id返回CommonReturnType类型(注解中使用get方法,并且要去掉consumes方法)。通过id得到itemModel,然后就将其转化成itemVO并返回。

4-4 商品模型管理–商品列表

  1. 在itemDOMapper中加入listItem的SQL语句和对应方法;
  2. 实现itemControllerImpl中的商品列表浏览方法:调用mapper中的listItem()方法得到itemDOlist,通过itemDO得到itemStockDO并将其转化成itemModel(使用java8的streamAPI),得到temModelList并将其返回。
  3. 在itemController中添加商品列表浏览方法,通过上面写的方法拿到itemModelList,然后再次使用同样的方法(java8的streamAPI)得到itemVOList,通用返回结果CommonReturnType的create方法创建并返回。

4-5 商品模型管理–商品列表

完成查看商品列表的方法:

  1. 首先要完成SQL语句:在dao和对呀的mapping中item的对应模块(mapper和相应的xml文件)中加上ListItem方法;
  2. 在ItemServiceImpl中完成ListItem方法的重写:首先通过mapper的ListItem方法拿到ItemDO的list列表,然后将其转化位ItemModel的list列表(使用java8的新特性直接对列表进行操作)并将其返回;
  3. 在ItemController中加上ListItem方法,通过itemService拿到ItemModelList,然后将其转化成可对前端显示的ItemVO的list列表,最后使用通用返回类型的creat方法创建并返回。

5-1 交易模型管理–交易模型创建

首先创建OrderModel,在里面添加订单模型的属性,需要注意的点是这里的id即订单号定义成String类型,因为订单号里面一般涉及到下单时间和分库分表位等信息。然后在数据库中完成相应表的创建。最后修改mybatis-generator中的相应代码,运行并自动生成相应的mapper和DO文件。

5-2 交易模型管理–交易下单01

一、创建OrderService接口,在里面添加创建订单的信息,传入用户id(userId)、商品id(itemId)和下单数量(amount),返回订单模型(OrderModel)。
二、创建接口的实现类OrderServiceImpl,加上注释@Service并重写createorder方法(加上@Transactional注释保证创建订单是在同一个事务当中)。

  1. 合法性校验:service中的方法通过id得到对应的Model然后判空校验,订单数量直接与下单最小值和最大值对比大小校验。
  2. 落单减库存:需要在ItemService接口以及相应的实现类中添加库存扣减方法,传入itemId和amount,返回布尔类型表示成功与否。该操作与数据库相关,因此需要在item的mapper文件中写入相应的SQL语句。使用刚添加的方法判断库存扣减成功与否,失败抛出库存不足的异常(在错误枚举类型中添加30000开头的错误码表示交易信息错误)。
    重点:在SQL语句中实现库存stock和订单数量amount的大小比较(不要把stock读进来比较这样需要两条SQL语句并且需要消耗java内存空间),并返回改变数据库的行数,用行数判断成功与否。
  3. 订单入库:new一个OrderModel并设置其userId、itemId、amount、itemPrice、orderPrice和交易流水号,这里交易流水号的生成方式选择8下单时间+6位自增序列+2位分库分表位。通过orderModel得到orderDO然后调用mapper的插入方法将其插入到数据库中。
    重点:这里生成交易流水号的方法不仅要加上@Transactional标签保证在同一事务中,而且要设置属性propagation = Propagation.REQUIRES_NEW保证在创建订单回滚时,流水号不会滚。
  4. 加上商品销量:需要在ItemService接口以及相应的实现类中添加销量增加方法,传入itemId和amount返回类型为空。该操作与数据库相关,因此需要在item的mapper文件中写入相应的SQL语句。
  5. 将orderModel返回给前端

5-3 交易模型管理–交易下单02

订单号的生成方法:生成中间的6位自增序列的方法:在数据库中建一张通用的sequence表,三个参数,name、current_value和step,将名字设置为order_info,当前值设置为0,步长设置为1;使用mybatis-generator方法生成相应的文件。在获取6位自增序列时,从数据库中获取当前值,然后在当前值前面补0至长度6位即为所需的6位自增序列,最后需要再获取步长并将其与当前值加起来用于更新数据库的当前值。

5-4 交易模型管理–交易下单03

三、创建OrderCOntroller,加上注解@RestController、@RequestMapping和@CrossOrigin(处理跨域请求问题),添加创建订单方法方法(加上注解@RequestMapping)传入参数商品id(itemId)、下单数量(amount),返回公共返回类型。

  1. 获取用户登录凭证,判断用户是否登录(获取前面加入到session中的登录信息)注意这里使用Boolean类型防止空指针异常;
  2. 获取用户登录信息得到userModel,然后获得userId,这样创建订单的三个参数全部得到,用过orderServicer的createOrder方法拿到订单模型orderModel;
  3. 调用通用返回类型的create方法创建并返回。

6-1 秒杀模型管理–活动模型创建

创建PromoModel并添加活动的属性,并在数据库中创建相应的表,然后使用mybatis-generator生成相应的文件。

6-2 秒杀模型管理–活动模型与商品模型结合01

一、 创建PromoService接口,添加方法getPromoByItemId,传入itemId返回promoModel;
二、 创建实现类PromoServiceImpl实现接口,加上@Service注释,并重写方法。

  1. 获取对应商品的秒杀活动:在对应数据库文件中加上方法,selectByItemId,在实现方法中,通过该方法得到promoDO;
  2. dataobject->model:把promoDO转化成promoModel
  3. 判断当前时间是否秒杀活动即将开始或正在进行:在promoModel中添加一个属性(与数据库没有关系)status,为1表示还未开始,2表示进行中,3表示已结束。回到方法中,对promoModel进行判空,然后获取当前时间,与开始时间和结束时间对比,对属性status设置相应的值。最后返回该模型promoModel。
  4. 回到ItemModel中,使用聚合模型,添加属性promoModel,如果不为空,表示其拥有还未结束的秒杀活动,再回到对应的实现类ItemServiceImpl中,在商品详情浏览中返回itemModel之前,加上获取活动商品信息,如果其promoModel不为空并且status不为3,则对模型itemModel设置对应的属性。
  5. 再回到ItemVO中,添加几个字段,promoStatus记录是否在秒杀活动中,0表示没有秒杀活动,1表示秒杀活动待开始,2表示秒杀活动正在进行中。promoPrice表示秒杀活动价格,promoId表示秒杀活动id,startDate表示秒杀活动开始时间。回到ItemController中的model转VO中添加相应的内容,再返回VO之前,对itemModel的promoModel进行判断,如果非空,则对VO设置相应的属性,否则设置PromoStatus为0;

6-4 秒杀模型管理–活动模型与商品模型结合03

  1. 在OrderModel中添加字段,promoId若非空,则itemPrice和orderprice是以秒杀的价格进行。然后去mapper中加上相应的SQL语句;
  2. 在OrderService中添加入参promoId,然后在实现类中也添加该参数,然后校验信息最下面加上活动信息校验
  3. 修改订单入库时的商品价格,判断其是活动价格还是平销价格;
  4. 在OrderController中的下单中,添加入参。

SptingBoot构建电商基础秒杀项目时遇到的问题相关推荐

  1. SpringBoot构建电商基础秒杀项目——用户模型管理

    项目进展: 已经完成了springboot + MVC + mybatis 框架搭建,外加常态的错误异常定义.正确的返回值类型定义. 接下来还需完成模型能力管理,其包括用户模型.商品模型.下单模型.秒 ...

  2. SpringBoot构建电商基础秒杀项目知识点总结(第3章)

    文章目录 3-1 使用SpringMVC方式开发用户信息 1.springMVC中Model的设计思想 2.对象复制函数,用于不同层的model的转化 3.需要在controller方法上加上@res ...

  3. 用Elasticsearch构建电商搜索平台(有赞)

    随着互联网数据规模的爆炸式增长,如何从海量的历史,实时数据中快速获取有用的信息,变得越来越有挑战性. 电商数据系统主要类型 一个中等的电商平台,每天都要产生百万条原始数据,上亿条用户行为数据.一般来说 ...

  4. 电商抢购秒杀系统的设计_1_应用场景分析

    2019独角兽企业重金招聘Python工程师标准>>> 电商抢购秒杀系统的设计_1_应用场景分析 概述 所谓知已知彼,百战不殆,在开始详细介绍实战中的抢购秒杀系统时,我们了解一些抢购 ...

  5. Java生鲜电商平台-秒杀系统微服务架构设计与源码解析实战

    Java生鲜电商平台-秒杀系统微服务架构设计与源码解析实战 Java生鲜电商平台-  什么是秒杀 通俗一点讲就是网络商家为促销等目的组织的网上限时抢购活动 比如说京东秒杀,就是一种定时定量秒杀,在规定 ...

  6. 02-Flutter移动电商实战-建立项目和编写入口文件

    02-Flutter移动电商实战-建立项目和编写入口文件 环境搭建请参考之前写的一篇文章:Flutter_初体验_创建第一个应用 1.创建项目 采用AndroidStudio构建本项目,FIle> ...

  7. 电商网站秒杀和抢购的高并发技术实现和优化

    一.如何防止多个用户同时抢购同一商品,防止高并发同时订购同一商品?​ 最近双十一抢购系统应用频繁,销量火爆的同时,让人头疼是却是多用户高并发情况下出现的库存问题. 据调查,多个用户同时下单,导致查询和 ...

  8. 电商大数据项目-推荐系统实战(一)

    电商大数据项目-推荐系统实战(一)环境搭建以及日志,人口,商品分析 https://blog.51cto.com/6989066/2325073 电商大数据项目-推荐系统实战之推荐算法 https:/ ...

  9. 电商大数据项目-推荐系统实战之推荐算法(三)

    电商大数据项目-推荐系统实战(一)环境搭建以及日志,人口,商品分析 https://blog.51cto.com/6989066/2325073 电商大数据项目-推荐系统实战之推荐算法 https:/ ...

  10. 干货:5个维度构建电商全景大数据分析

    电商是一个伴随数据而生的行业,数据在电商平台上高速运转,由此也诞生了非常多的电商信息化平台,有物流系统.供应链系统.OA系统.流量分析平台等,而各平台产生的数据都被分散在各个系统中,无法发挥出数据的价 ...

最新文章

  1. 设置IDEA自动导入import 关联的包
  2. Centos MySQL 5.7安装、升级教程
  3. nacos 配置_阿里巴巴 Nacos 分布式配置中心原理
  4. Wireshark抓取数据包
  5. 为nginx创建windows服务自启动
  6. Linux之ubuntu的网卡配置
  7. Java(Android)线程池
  8. .NET如何写正确的“抽奖”——数组乱序算法
  9. java webinf lib jar_java web项目中classes文件夹下的class和WEB-INF/lib中jar里的class文件加载顺序...
  10. CAD中椭圆如何转换成多段线
  11. python一个简单的一元二次方程求解的过程
  12. Spring Cloud 快速入门指南(二)
  13. C语言根号下ln怎么表示,用C语言怎么编y=sin(根号下ax)+ln(a+X)
  14. Codeforces718 C. Sasha and Array(线段树维护矩阵,矩阵快速幂求斐波那契数列,矩阵乘法结合律)
  15. 由随机数生成器到宿命论
  16. python贷款_Python贷款逾期分析
  17. 图像处理专业术语中英文对照(不断补充中)
  18. Linux中卷的扩展命令
  19. 番茄炖牛腩做法,味美汤浓开胃爽口,牛腩入口即化,太下饭!
  20. Python数据分析和django建站一般使用工具

热门文章

  1. CSDN的C1-见习工程师能力认证相关知识(框架)
  2. JavaWeb之【web站点的欢迎页面】
  3. 明星危机公关应该怎么做?
  4. 怎么在计算机网络上添加文件,教你win7如何设置网络共享文件夹
  5. 如何使用 Zend Expressive 建立 NASA 图片库?
  6. 微信支付-企业付款到零钱
  7. Java输入时间输出热量卡路里的小程序
  8. 【BZOJ4453】cys就是要拿英魂!
  9. html5禁用右侧滚轮条,鼠标滚轮终于不乱跳了,自己动手更换鼠标滚轮编码器 雷柏7100=================...
  10. 计算机组装怎么备份系统,电脑怎么备份系统(高手教你win7系统怎么备份)