Java秒杀简单设计四:service层设计
接上一篇 https://www.cnblogs.com/taiguyiba/p/9829191.html 封装了系统传递的数据类和异常类
本文继续设计service层设计:
1.SeckillService.java
package com.seckill.service; import java.util.List; import com.seckill.dto.Exposer;
import com.seckill.dto.SeckillExecution;
import com.seckill.entity.Seckill;
import com.seckill.exception.RepeatKillException;
import com.seckill.exception.SeckillCloseException;
import com.seckill.exception.SeckillException; /**
* 三个方面:1.方法定义的粒度,参数,返回类型(return ,类型/异常)
* @author kangjie
*
*/
public interface SeckillService { /**
*
* 查询所有秒杀记录
* @return
*/
List <Seckill> getSeckillList();
/**
*
* 查询单个秒杀记录
* @param seckillId
* @return
*/
Seckill getById(long seckillId);
/**
* 秒杀开启时输出秒杀接口地址 否则输出系统时间和秒杀时间
* @param seckillId
*/
Exposer exportSeckillUrl(long seckillId); //执行秒杀操作
SeckillExecution excuteSeckill(long seckillId,long userPhone,String md5)
throws RepeatKillException,SeckillCloseException,SeckillException; //执行秒杀操作by存储过程
SeckillExecution excuteSeckillProcedure(long seckillId,long userPhone,String md5);
}
2. SeckillServiceImpl
秒杀事务控制,在函数中如果更新出现问题,就会抛出异常,进行事务回滚。
package com.seckill.service.impl; import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map; import org.apache.commons.collections.MapUtils;
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 com.seckill.dao.SeckillDao;
import com.seckill.dao.SuccessKilledDao;
import com.seckill.dao.cache.RedisDao;
import com.seckill.dto.Exposer;
import com.seckill.dto.SeckillExecution;
import com.seckill.entity.Seckill;
import com.seckill.entity.SuccessKilled;
import com.seckill.enums.SeckillStateEnum;
import com.seckill.exception.RepeatKillException;
import com.seckill.exception.SeckillCloseException;
import com.seckill.exception.SeckillException;
import com.seckill.service.SeckillService; @Service
public class SeckillServiceImpl implements SeckillService { private Logger logger=LoggerFactory.getLogger(this.getClass()); @Autowired
private SeckillDao seckillDao;
@Autowired
private SuccessKilledDao successKilledDao;
@Autowired
private RedisDao redisDao;
//md5盐值,用于混淆md5
private final String salt = "!@#!@#!@#$ASDFASDFzxcv_|+)+)(("; @Override
public List<Seckill> getSeckillList() {
// TODO Auto-generated method stub
return seckillDao.queryAll(, );
} @Override
public Seckill getById(long seckillId) {
// TODO Auto-generated method stub
return seckillDao.queryById(seckillId);
} @Override
public Exposer exportSeckillUrl(long seckillId) {
// TODO Auto-generated method stub
//访问redis:缓存优化,超时的基础上维护一致性
Seckill seckill = redisDao.getSeckill(seckillId);
if(seckill == null) {
//访问数据库
seckill = seckillDao.queryById(seckillId);
if(seckill == null) {
return new Exposer(false, seckillId);
}else {
logger.error("放入redis中: " + seckill.toString());
redisDao.putSeckill(seckill);
}
}
Date startTime = seckill.getStartTime();
Date endTime = seckill.getEndTime();
Date nowTime = new Date();
if(nowTime.getTime() > endTime.getTime()
||nowTime.getTime() < startTime.getTime()) {
return new Exposer(false, nowTime.getTime(), startTime.getTime(), endTime.getTime(),seckillId);
}
String md5 = getMD5(seckillId);
return new Exposer(true, md5, seckillId); // return null;
}
private String getMD5(long seckillId) {
String base = seckillId + "/" + salt;
String md5 = DigestUtils.md5DigestAsHex(base.getBytes());
return md5;
} @Override
@Transactional
public SeckillExecution excuteSeckill(long seckillId, long userPhone, String md5)
throws RepeatKillException, SeckillCloseException, SeckillException {
// TODO Auto-generated method stub
if(md5 == null || !md5.equals(getMD5(seckillId))) {
throw new SeckillException("seckill data rewirte");
}
try { int insertCount = successKilledDao.insertSuccessKilled(seckillId, userPhone);
if (insertCount <= ) {
// 重复秒杀
throw new RepeatKillException("repeat seckill");
} else {
int updateCount = seckillDao.reduceNumber(seckillId, new Date());
if (updateCount <= ) {
throw new SeckillCloseException("seckill closed");
} else {
// 秒杀成功
SuccessKilled successKilled = successKilledDao.queryByIdWithSeckill(seckillId, userPhone);
return new SeckillExecution(seckillId,SeckillStateEnum.SUCCESSD, successKilled);
} }
} catch (RepeatKillException e) {
// TODO: handle exception
logger.error(e.getMessage(),e);
throw new RepeatKillException("repeat seckill");
}catch (SeckillCloseException e) {
// TODO: handle exception
logger.error(e.getMessage(),e);
throw new SeckillCloseException("seckill closed");
}catch (Exception e) {
logger.error(e.getMessage(), e);;
throw new SeckillException("Inner error: " + e.getMessage());
} } @Override
public SeckillExecution excuteSeckillProcedure(long seckillId, long userPhone, String md5){
// TODO Auto-generated method stub
if(md5 == null || !md5.equals(getMD5(seckillId))) {
return new SeckillExecution(seckillId,SeckillStateEnum.DATA_REWRITE);
}
Date killTime = new Date();
Map<String,Object> map = new HashMap<String,Object>();
map.put("seckillId", seckillId);
map.put("phone", userPhone);
map.put("killTime", killTime);
map.put("result", null);
try {
seckillDao.killByProcedure(map);
//获取result
int result = MapUtils.getInteger(map, "result",-);
if(result == ) {
SuccessKilled sk = successKilledDao.queryByIdWithSeckill(seckillId, userPhone);
return new SeckillExecution(seckillId,SeckillStateEnum.SUCCESSD,sk);
}else {
return new SeckillExecution(seckillId, SeckillStateEnum.stateOf(result));
}
} catch (Exception e) {
// TODO Auto-generated catch block
logger.error(e.getMessage(),e);
return new SeckillExecution(seckillId, SeckillStateEnum.INNER_ERROR);
}
} }
Java秒杀简单设计四:service层设计的更多相关文章
- Java秒杀简单设计二:数据库表和Dao层设计
Java秒杀简单设计二:数据库表Dao层设计 上一篇中搭建springboot项目环境和设计数据库表 https://www.cnblogs.com/taiguyiba/p/9791431.html ...
- Java秒杀简单设计一:搭建springboot环境
项目参考:慕课网 https://www.imooc.com/learn/587 Java秒杀 开发环境 JDK1.8.Maven.Mysql.Eclipse.SpringBoot2.0.5.myb ...
- Java秒杀简单设计三:数据封装类
上一篇https://www.cnblogs.com/taiguyiba/p/9828984.html 整合了数据库表和Dao层代码 这一篇继续设计数据封装类: 涉及到获取秒杀地址,查询,返回秒杀结果 ...
- Dao层和Service层设计
1.Dao接口层 public interface IBaseDao<T, ID extends Serializable>{ public abstract Serializable s ...
- Java秒杀实战 (四)JMeter压测
转自:https://blog.csdn.net/qq_41305266/article/details/81071278. 一.JMeter入门 下载链接 http://jmeter.apache. ...
- HTML5学习+javascript学习:打飞机游戏Service层Control层+源码
2.Service层 如前所述,Service层是Control层与Model层之间桥接的一层,它拥有所有要在屏幕上显示的实体(除了背景)的引用 我们知道,当游戏运行时,随时都可能发生碰撞,随时都可能 ...
- SSM实战——秒杀系统之Service层接口设计与实现、Spring托管、声明式事务
一:Service层接口设计 准备工作:新建三个包:service包.exception包.dto包,分别用来存放业务接口.自定义异常类.dto类. 1:定义接口 package org.myseck ...
- Java高并发秒杀API之Service层
Java高并发秒杀API之Service层 第1章 秒杀业务接口设计与实现 1.1service层开发之前的说明 开始Service层的编码之前,我们首先需要进行Dao层编码之后的思考:在Dao层我们 ...
- [转]java web简单权限管理设计
原文地址:http://blog.csdn.net/zwx19921215/article/details/44467099 最近在做一个网站类型项目,主要负责后台,ui框架选型为jquery eas ...
随机推荐
- VIM复制粘贴大全[转]
用vim这么久 了,始终也不知道怎么在vim中使用系统粘贴板,通常要在网上复制一段代码都是先gedit打开文件,中键粘贴后关闭,然后再用vim打开编辑,真的不 爽:上次论坛上有人问到了怎么在vim中使 ...
- Python 程序员都会喜欢的 6 个库
在编程时,小挫折可能与大难题一样令人痛苦.没人希望在费劲心思之后,只是做到弹出消息窗口或是快速写入数据库.因此,程序员都会喜欢那些能够快速处理这些问题,同时长远来看也很健壮的解决方案. 下面这6个Py ...
- 网易 2016 实习研发project师 3道 编程题
1 比較重量 给定两颗钻石的编号g1,g2,编号从1開始.同一时候给定关系数组vector,当中元素为一些二元组.第一个元素为一次比較中较重的钻石的编号,第二个元素为较轻的钻石的编号.最后给定之前的比 ...
- Java -- 异常的捕获及处理 -- throws与throw关键字
7.2 throws 与 throw关键字 7.2.1 throws 关键字 在定义一个方法时可以使用throws关键字声明,使用throws声明的方法标识此方法不处理异常,而交给方法的调用处进行处理 ...
- 8 -- 深入使用Spring -- 3...1 Resource实现类ServletContextResource
8.3.1 Resource实现类------ServletContextResource:访问相对于ServletContext路径下的资源的实现类. 4.访问应用相关资源 Spring提供了Ser ...
- C#调用外部DLL介绍及使用详解
一. DLL与应用程序 动态链接库(也称为DLL,即为“Dynamic Link Library”的缩写)是Microsoft Windows最重要的组成要素之一,打开Windows系统文件 ...
- PHP代码审计笔记--命令执行漏洞
命令执行漏洞,用户通过浏览器在远程服务器上执行任意系统命令,严格意义上,与代码执行漏洞还是有一定的区别. 0x01漏洞实例 例1: <?php $target=$_REQUEST['ip']; ...
- 查看python中已安装的包有哪些
新版本执行:pip list 老版本执行:pip freeze
- Linux 查看目录大小及文件数量命令
查看当前目录大小: [root@21andy.com]# du -sh 查看指定目录大小: [root@21andy.com]# du -sh /www/21andy.com 查看当前目录文件总数: ...
- Java API方式调用Kafka各种协议
众所周知,Kafka自己实现了一套二进制协议(binary protocol)用于各种功能的实现,比如发送消息,获取消息,提交位移以及创建topic等.具体协议规范参见:Kafka协议 这套协议的具 ...