KillOneServiceImpl

先声明logger(slf4j)

再实现方法

注意:声明式事务只有在运行时异常抛出才会回滚

package com.jimo.service.impl;

import com.jimo.dao.KillOneDao;
import com.jimo.dao.SuccessKilledDao;
import com.jimo.dto.Exposer;
import com.jimo.dto.KillExecution;
import com.jimo.entity.KillOne;
import com.jimo.entity.SuccessKilled;
import com.jimo.enums.KillOneStateEnum;
import com.jimo.exception.KillCloseException;
import com.jimo.exception.KillException;
import com.jimo.exception.RepeatKillException;
import com.jimo.service.KillOneService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import java.util.Date;
import java.util.List;

/**
 * Created by root on 17-5-26.
 */
@Service
public class KillOneServiceImpl implements KillOneService {

    private Logger logger = LoggerFactory.getLogger(KillOneServiceImpl.class);

    @Autowired
    private KillOneDao killOneDao;

    @Autowired
    private SuccessKilledDao successKilledDao;

    private final String SLAT = "qjdajHSBDKJAB324&^%^%%&";//用于MD5加密的密钥

    public List<KillOne> getKillList() {
        return killOneDao.queryAll(0, 4);
    }

    public KillOne getKillById(long killId) {
        return killOneDao.queryById(killId);
    }

    public Exposer exportKillUrl(long killId) {
        KillOne killOne = killOneDao.queryById(killId);
        if (killOne == null) {
            return new Exposer(false, killId);
        }
        Date start = killOne.getStartTime();
        Date end = killOne.getEndTime();
        Date now = new Date();
        //不在时间范围内
        if (now.getTime() - start.getTime() < 0 || now.getTime() - end.getTime() > 0) {
            return new Exposer(false, now.getTime(), start.getTime(), end.getTime(), killId);
        }
        String md5 = getMD5(killId);//TODO
        return new Exposer(true, md5, killId);
    }

    private String getMD5(long killId) {
        String base = killId + "/" + SLAT;
        return DigestUtils.md5DigestAsHex(base.getBytes());//使用spring的工具类生成MD5
    }

    @Transactional
    /*
    * 使用声明式事务:
    * 1、开发团队风格明确
    * 2、保证事务执行时间尽可能短,不要穿插耗时操作(RPC或其他网络操作),否则剥离出去
    * 3、不是所有方法都需要事务
    * */
    public KillExecution executeKill(long killId, long userPhone, String md5)
            throws KillException, RepeatKillException, KillCloseException {
        if (md5 == null || !md5.equals(getMD5(killId))) {
            throw new KillException("数据篡改");
        }
        try {
            //减库存
            int reduceNumber = killOneDao.reduceNumber(killId, new Date());
            if (reduceNumber <= 0) {
                throw new KillCloseException("秒杀结束");
            } else {
                //记录购买行为
                int insertCount = successKilledDao.insertSuccessKilled(killId, userPhone);
                if (insertCount <= 0) {
                    throw new KillException("重复秒杀");
                } else {
                    SuccessKilled successKilled = successKilledDao.queryByIdWithKillOne(killId, userPhone);
                    return new KillExecution(killId, KillOneStateEnum.SUCCESS, successKilled);
                }
            }
            //异常会执行回滚
        } catch (KillCloseException e) {
            throw e;
        } catch (RepeatKillException e2) {
            throw e2;
        } catch (Exception e3) {
            logger.error(e3.getMessage(), e3);
            //所有编译期异常转为运行时异常
            throw new KillException("内部错误:" + e3.getMessage());
        }
    }
}

修改的地方

加了枚举类

package com.jimo.enums;

/**
 * Created by root on 17-5-26.
 */
public enum KillOneStateEnum {
    SUCCESS(1, "秒杀成功"),
    END(0, "秒杀结束"),
    INNER_ERROR(-1, "内部错误"),
    REPEAT_KILL(-2, "重复秒杀"),
    DATA_REWRITE(-3, "数据篡改");

    private int state;
    private String stateInfo;

    KillOneStateEnum(int state, String stateInfo) {
        this.state = state;
        this.stateInfo = stateInfo;
    }

    public int getState() {
        return state;
    }

    public String getStateInfo() {
        return stateInfo;
    }

    public static KillOneStateEnum stateOf(int index) {
        for (KillOneStateEnum ke : values()) {
            if (ke.getState() == index) {
                return ke;
            }
        }
        return null;
    }
}

改了dto的构造方法:

public KillExecution(long killId, KillOneStateEnum stateEnum) {
        this.killId = killId;
        this.state = stateEnum.getState();
        this.stateInfo = stateEnum.getStateInfo();
    }

    public KillExecution(long killId, KillOneStateEnum stateEnum, SuccessKilled successKilled) {
        this.killId = killId;
        this.state = stateEnum.getState();
        this.stateInfo = stateEnum.getStateInfo();
        this.successKilled = successKilled;
    }

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">
    <!--配置service包扫描-->
    <context:component-scan base-package="com.jimo.service"/>

    <!--配置事务管理器-->
    <bean id="transactionManager"
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--引用数据源-->
        <property name="dataSource" ref="dataSource"/>
    </bean>

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

results matching ""

    No results matching ""