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 ...
随机推荐
- Linux安装rpc监控系统资源
1.rpc服务需rsh的支持,一般情况下rsh已安装.rpm -qa rsh查看. 2.右键另存为http://heanet.dl.sourceforge.net/sourceforge/rstatd ...
- css3-rem
http://www.w3cplus.com/css3/define-font-size-with-css3-rem https://mp.weixin.qq.com/s/DpLXJhfCHsgrbg ...
- java TreeNode接口
今天写安卓程序见到一个方法getChildAt();不懂其用边去百度搜索了一下,看到了它的api,细致看看原来是在接口里面如今我把这个api贴给大家共享假设是操作xml我认为用这个非常方便 javax ...
- Eclipse------如何将项目通过maven编译并打包
1.右击项目>>>点击Debug As>>>点击 Maven install进行编译,编译成功后入图 2.右击项目>>>点击Debug As> ...
- 分分钟学会GCD
2014 什么是GCD Grand Central Dispatch (GCD)是异步运行任务的技术之中的一个.一般将应用程序中记述的线程管理用的代码在系统级中实现.因为线程管理是作为系统的一部分来实 ...
- 反射简介—C#特性和反射
.NET编译器的任务之一就是为所有定义和引用的类型生成元数据描述.除了程序集中标准的元数据外,.NET平台还支持特定(attribute)把更多的元数据嵌入到程序集中. .NET特性扩展了抽象的Sys ...
- Git Step by Step – (2) 本地Repo
前面一篇文章简单介绍了Git,并前在Windows平台上搭建了Git环境,现在就正式的Git使用了. Git基本概念 在开始Git的使用之前,需要先介绍一些概念,通过这些概念对Git有些基本的认识,这 ...
- grid网格的流动一
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- grid布局合并单元格
参考:http://www.w3cplus.com/css3/css-grid-layout-merge-cells.html <!DOCTYPE html> <html lang= ...
- iOS LLDB调试精解
小笨狼与LLDB: http://jiangliancheng.gitcafe.io/2015/12/13/%E5%B0%8F%E7%AC%A8%E7%8B%BC%E4%B8%8ELLDB%E7%9A ...