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 ...
随机推荐
- MySQL修改密码和忘记ROOT密码
1.关闭数据库 脚本:[root@mysql etc]# service mysql stop 2.使用脚本: mysqld_safe --skip-grant-tables 启动数据库 使用/usr ...
- python垃圾回收,判断内存占用,手动回收内存,二
以下为例子,判断计算机内存并释放程序内存. # coding=utf8 import time import psutil, gc, commands,os from logger_until imp ...
- [SLAM] 01. "Simultaneous Localization and Mapping"
本篇带你认识SLAM,形成客观的认识和体系 一.通过行业招聘初步了解SLAM 发信人: leecty (Terry), 信区: ParttimeJobPost标 题: 创业公司招SLAM 算法工程师发 ...
- [Module] 08 - MVP by Mosby
From: Mosby MVP使用教程[作者用心] View是消极视图(Passive View), 它尽量不去主动做事, 让Presenter通过抽象方式控制View 例子: 例如Presenter ...
- SpringMVC -- 梗概--源码--壹--springMVC json处理
附:实体类 Class : User package com.c61.entity; import java.text.SimpleDateFormat; import java.util.Date; ...
- python卸载或者安装时提示There is a problem with this Windows Installer package.A program required for this install to complete could not be run. Contact your support personnel or package vendor
1.卸载时报这个错,先进行下修复,再执行卸载: 2.安装时报这个错,安装的过程中,没有取得管理员的权限. Msi格式的文件,点右键后,也没有“以管理员身份运行”的菜单项,那怎么办呢?你可以点“开始”菜 ...
- 【RF库XML测试】Add Element
Name:Add ElementSource:XML <test library>Arguments:[ source | element | index=None | xpath=. ] ...
- Vim 手记:语法高亮
本文覆盖范围: Vim 的着色方案 设置高亮 选择颜色 语法高亮除错 每个程序员的文本编辑器缺少了语法高亮.特殊关键字和短语着色,都是不完整的.语法高亮突出了文档的结构,帮助发现排字错误,利于调试,整 ...
- MVC中的一些不同之处(WebForm)
一. 路由重定向 /// <summary> /// 路由重定向 /// </summary> /// <returns></returns> publ ...
- Lua中的注释
Lua中有两种注释:行注释和块注释.行注释以“--”开头,可以注释这一行后面的内容.块注释以“--[[”开始,以“--]]”结尾,可以注释这个范围内的整个内容:块注释可以注释多行内容.下面是一个示例: ...