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>