接上一篇 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层设计的更多相关文章

  1. Java秒杀简单设计二:数据库表和Dao层设计

    Java秒杀简单设计二:数据库表Dao层设计 上一篇中搭建springboot项目环境和设计数据库表  https://www.cnblogs.com/taiguyiba/p/9791431.html ...

  2. Java秒杀简单设计一:搭建springboot环境

    项目参考:慕课网  https://www.imooc.com/learn/587 Java秒杀 开发环境 JDK1.8.Maven.Mysql.Eclipse.SpringBoot2.0.5.myb ...

  3. Java秒杀简单设计三:数据封装类

    上一篇https://www.cnblogs.com/taiguyiba/p/9828984.html 整合了数据库表和Dao层代码 这一篇继续设计数据封装类: 涉及到获取秒杀地址,查询,返回秒杀结果 ...

  4. Dao层和Service层设计

    1.Dao接口层 public interface IBaseDao<T, ID extends Serializable>{ public abstract Serializable s ...

  5. Java秒杀实战 (四)JMeter压测

    转自:https://blog.csdn.net/qq_41305266/article/details/81071278. 一.JMeter入门 下载链接 http://jmeter.apache. ...

  6. HTML5学习+javascript学习:打飞机游戏Service层Control层+源码

    2.Service层 如前所述,Service层是Control层与Model层之间桥接的一层,它拥有所有要在屏幕上显示的实体(除了背景)的引用 我们知道,当游戏运行时,随时都可能发生碰撞,随时都可能 ...

  7. SSM实战——秒杀系统之Service层接口设计与实现、Spring托管、声明式事务

    一:Service层接口设计 准备工作:新建三个包:service包.exception包.dto包,分别用来存放业务接口.自定义异常类.dto类. 1:定义接口 package org.myseck ...

  8. Java高并发秒杀API之Service层

    Java高并发秒杀API之Service层 第1章 秒杀业务接口设计与实现 1.1service层开发之前的说明 开始Service层的编码之前,我们首先需要进行Dao层编码之后的思考:在Dao层我们 ...

  9. [转]java web简单权限管理设计

    原文地址:http://blog.csdn.net/zwx19921215/article/details/44467099 最近在做一个网站类型项目,主要负责后台,ui框架选型为jquery eas ...

随机推荐

  1. How to make an HTTP request in Swift

    from: http://stackoverflow.com/questions/24016142/how-to-make-an-http-request-in-swift You can use N ...

  2. Robot Framework分层、开发系统关键字

            开发系统关键字:http://www.cnblogs.com/fnng/p/4261293.html http://www.cnblogs.com/fnng/p/3969978.htm ...

  3. 通过MyEclipse部署web应用程序开发环境

    1.下载并安装MyEclipse10 2.配置java开发的jar包 3.配置tomcat服务器 4.部署tomcat服务器 点击Bronse可以查看部署后的文件夹目录 5.启动tomcat服务器 6 ...

  4. 防止dedecms注入文件挂马的解决方法

    1.目录权限我们不建议用户把栏目目录设置在根目录,原因是这样进行安全设置会十分的麻烦,在默认的情况下,安装完成后,目录设置如下:(1) data.templets.uploads.a或5.3的html ...

  5. MySQL自定义排序函数FIELD()

    MySQL可以通过field()函数自定义排序,格式:field(value,str1,str2,str3,str4),value与str1.str2.str3.str4比较,返回1.2.3.4,如遇 ...

  6. java okhhtp下载学信网学籍信息

    学信网的登录有验证码,是那种计算数字或者汉字识别的,很难识别.最近连学籍信息和学历信息也换成图片了,常规的正则 css xpath都不能使. 下载图片,需要先登录,获取登陆后的cookie和学籍信息的 ...

  7. c#直接调用ssis包实现Sql Server的数据导入功能

    调用ssis包实现Sql Server的数据导入功能网上已经有很多人讨论过,自己参考后也动手实现了一下,上一次笔者的项目中还用了一下这个功能.思前想后,决定还是贴一下增强记忆,高手请54. 1.直接调 ...

  8. 【Winform】自定义Messagebox

    1.保持Msgbox的Icon 2.可以追加Checkbox,RadioBOx 下载

  9. Linux+Redis实战教程_day02_2、redis简述及安装与启动

    2. redis简述及安装 关系型数据库(SQL): Mysql,oracle 特点:数据和数据之间,表和字段之间,表和表之间是存在关系的 例如:部门表 001部门,   员工表 001 用户表,用户 ...

  10. Python之虚拟环境管理

    Python本身有很多个版本,第三方的Python包又有很多可用的版本,所以经常会遇到下面的问题: 运行不同的Python程序,需要使用不同版本的Python(2.x或3.x). 在同一中Python ...