当前位置: 首页 > news >正文

基于SpringMVC+Spring+MyBatis实现秒杀系统【业务逻辑】

前言

       该篇主要实现秒杀业务层,秒杀业务逻辑里主要包括暴露秒杀接口地址、实现秒杀业务逻辑。同时声明了三个业务类:Exposer、SeckillExecution、SeckillResult。 Exposer主要用来实现暴露接口时一个md5的加密,防止用户在客户端篡改数据。根据seckillid生成md5,提交秒杀请求时会根据这个md5和seckillid比对是否是合法的请求。SeckillExecution主要封装秒杀时的返回值。

       SeckillExecution有2个属性,state、stateinfo,这里我没有封装枚举值,还是用整型和字符串给客户端传值,在Service里看着也直观些。

 

准备工作

1、spring-service.xml

     业务逻辑里的关键是开启事务,这里推荐用注解的方式实现。

<?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:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
       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.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

    <!--1、注解包扫描-->
    <context:component-scan base-package="com.seckill.service"/>

    <!--2、配置声明式事务-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--注入数据库-->
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!--3、配置基于注解的声明式事务-->
    <tx:annotation-driven transaction-manager="transactionManager"/>


</beans>

 

实现秒杀业务

     秒杀相关的关键方法就是最后两个方法,一个是对外暴漏秒杀地址,一个是秒杀方法。

public interface SeckillService {

    List<Seckill> getSeckillList();

    Seckill getById(long seckillId);



    /**对外暴漏秒杀接口**/
    Exposer exposeSeckillUrl(long seckillId);



    /**
     * 执行秒杀操作,有可能成功,有可能失败,所以这里我们抛出自自定义异常
     * ***/
    SeckillExecution executeSeckill(long seckillId,long phone,String md5) throws SeckillException,
            RepeatKillException,
            SeckillCloseException;


}

  

@Service
public class SeckillServiceImpl implements SeckillService {


    /***
     * 秒杀行为的枚举放在这里说明
     * 1、 秒杀成功
     * 0、 秒杀结束
     * -1、重复秒杀
     * -2、系统异常
     * -3、数据篡改
     * ***/

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    SeckillDao seckillDao;

    @Autowired
    SuccessKillDao successKillDao;

    private String salt = "zhangfei";


    @Override
    public List<Seckill> getSeckillList() {
        return seckillDao.queryAll(0, 100);
    }

    @Override
    public Seckill getById(long seckillId) {
        return seckillDao.queryById(seckillId);
    }

    @Override
    public Exposer exposeSeckillUrl(long seckillId) {
        Seckill seckill = getById(seckillId);

        Date startTime = seckill.getStartTime();
        Date endTime = seckill.getEndTime();

        Date now = new Date();

        if (now.getTime() < startTime.getTime() || now.getTime() > endTime.getTime()) {
            return new Exposer(false, seckillId, startTime.getTime(), endTime.getTime(), now.getTime());
        }

        String md5 = getMd5(seckillId);

        return new Exposer(true, md5, seckillId);
    }

    @Override
    @Transactional
    public SeckillExecution executeSeckill(long seckillId, long phone, String md5)
            throws SeckillException,RepeatKillException,SeckillCloseException {

        if (md5 == null || !md5.equals(getMd5(seckillId))) {
            throw new SeckillException("非法请求");
        }

        Date now = new Date();

        try {
            int insertCount = successKillDao.insertSuccessKilled(seckillId, phone);
            if (insertCount <= 0) {
                throw new RepeatKillException("重复秒杀");

            } else {
                int updateCount = seckillDao.reduceNumber(seckillId, now);
                if (updateCount <= 0) {
                    throw new SeckillCloseException("秒杀已关闭");
                } else {
                    //秒杀成功,可以把秒杀详情和商品详情实体返回
                    SuccessKilled successKilled = successKillDao.queryByIdWithSeckill(seckillId, phone);
                    return new SeckillExecution(seckillId, 1, "秒杀成功", successKilled);
                }
            }

        } catch (SeckillCloseException e) {
            throw e;
        } catch (RepeatKillException e1) {
            throw e1;
        } catch (SeckillException e2) {
            logger.error(e2.getMessage(), e2);
            throw new SeckillException("Unkonwn error:" + e2.getMessage());
        }

    }

    private String getMd5(long seckillId) {
        String base = seckillId + "/" + salt;
        String md5 = DigestUtils.md5DigestAsHex(base.getBytes());

        return md5;

    }
}

  

 

相关文章:

  • 嵌套ViewPager问题
  • 【微服务No.4】 API网关组件Ocelot+Consul
  • python的全局变量
  • 源码阅读:SDWebImage(十一)——SDImageCache
  • Jetty:配置安全
  • PYTHON RE正则表达式
  • 运维技术规划
  • Effective Java Item3:Enforce the singleton property with a private constructor or an enum type
  • 小程序 自动导航
  • Spark: 基本架构及原理
  • Android上的文件操作
  • Eureka微服务实战-服务提供者
  • Python入门教程之安装MyEclipse插件和安装Python环境
  • Windows系统下类UNIX环境---Cygwin安装
  • MySQL Desc指令相关
  • 《Java编程思想》读书笔记-对象导论
  • 4个实用的微服务测试策略
  • Brief introduction of how to 'Call, Apply and Bind'
  • EventListener原理
  • JAVA 学习IO流
  • JavaScript服务器推送技术之 WebSocket
  • Laravel Mix运行时关于es2015报错解决方案
  • npx命令介绍
  • python学习笔记-类对象的信息
  • Yeoman_Bower_Grunt
  • 从0到1:PostCSS 插件开发最佳实践
  • 分类模型——Logistics Regression
  • 回顾2016
  • 开源地图数据可视化库——mapnik
  • 排序(1):冒泡排序
  • 容器化应用: 在阿里云搭建多节点 Openshift 集群
  • 使用common-codec进行md5加密
  • 线上 python http server profile 实践
  • 移动端唤起键盘时取消position:fixed定位
  • CMake 入门1/5:基于阿里云 ECS搭建体验环境
  • 不要一棍子打翻所有黑盒模型,其实可以让它们发挥作用 ...
  • 你学不懂C语言,是因为不懂编写C程序的7个步骤 ...
  • #FPGA(基础知识)
  • #pragma once与条件编译
  • #ubuntu# #git# repository git config --global --add safe.directory
  • (3)选择元素——(14)接触DOM元素(Accessing DOM elements)
  • (delphi11最新学习资料) Object Pascal 学习笔记---第5章第5节(delphi中的指针)
  • (JS基础)String 类型
  • (附源码)ssm高校升本考试管理系统 毕业设计 201631
  • (附源码)ssm失物招领系统 毕业设计 182317
  • (六)软件测试分工
  • (原)记一次CentOS7 磁盘空间大小异常的解决过程
  • ***测试-HTTP方法
  • .NET(C#、VB)APP开发——Smobiler平台控件介绍:Bluetooth组件
  • .net解析传过来的xml_DOM4J解析XML文件
  • .Net中的设计模式——Factory Method模式
  • []error LNK2001: unresolved external symbol _m
  • []sim300 GPRS数据收发程序
  • [ASP.NET MVC]Ajax与CustomErrors的尴尬
  • [C#]C# winform部署yolov8目标检测的openvino模型