标签:led java sage 自定义异常 rtti over 系统 code drive
该篇主要实现秒杀业务层,秒杀业务逻辑里主要包括暴露秒杀接口地址、实现秒杀业务逻辑。同时声明了三个业务类: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; } }
基于SpringMVC+Spring+MyBatis实现秒杀系统【业务逻辑】
标签:led java sage 自定义异常 rtti over 系统 code drive
原文地址:https://www.cnblogs.com/sword-successful/p/9230313.html