Java高并发秒时啊API之Service层1

---2-1 使用Spring托管Service依赖理论----------------------------

spring ioc优势(工厂模式):
1.对象创建统一托管
2.规范的生命周期管理
3.灵活的依赖注入
4.一致的获取对象

Spring IOC 功能的理解
DAO依赖+Service依赖最终形成一致访问接口;
随意访问依赖对象

Spring IOC 容器下的 对象 默认都是单例的。

业务对象依赖图:Spring IOC容器 通过 DI 解决 依赖链(对象之间的依赖关系)

SeckillService ->SeckillDao  ->SqlSessionFactry->DataSource...

      ->successKilledDao

Spring-IOC注入方式和场景

本项目IOC使用:

  XML配置

  package-scan

  Annotation注解

---2-2 使用Spring托管Service依赖配置---------------------------------------------------------

SeckillServiceImpl.java:

  配置spring-service.xml

  标注注解@Service和@Autowired

package org.seckill.service.impl;

import java.util.Date;
import java.util.List;

import org.seckill.dao.SeckillDao;
import org.seckill.dao.SuccessKilledDao;
import org.seckill.dto.Exposer;
import org.seckill.dto.SeckillExecution;
import org.seckill.entity.Seckill;
import org.seckill.entity.SuccessKilled;
import org.seckill.enums.SeckillStatEnum;
import org.seckill.exception.RepeatKillExeception;
import org.seckill.exception.SeckillCloseException;
import org.seckill.exception.SeckillException;
import org.seckill.service.SeckillService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

//@Component @service @Dao @Controller
@Service
public class SeckillServiceImpl implements SeckillService {
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    //注入Service依赖
    @Autowired //在Spring 查找Dao类型的实例(Mybatis实现的,),并注入。不在需要自己new 实例
    //还有@Resource,@Inject等J2EE规范的注解
    private SeckillDao seckillDao;
    @Autowired
    private SuccessKilledDao successKilledDao;

    //md5盐值字符串,用于混淆MD5
    private final String slat = "[email protected]#(#$sldfj`123";
    @Override
    public List<Seckill> getSeckillList() {
        return seckillDao.queryAll(0, 4);
    }

    @Override
    public Seckill getById(long seckillId) {
        // TODO Auto-generated method stub
        return seckillDao.queryById(seckillId);
    }

    @Override
    public Exposer exportSeckillUrl(long seckillId) {
        Seckill seckill = seckillDao.queryById(seckillId);
        if(seckill == null){
            return new Exposer(false,seckillId);
        }
        Date startTime = seckill.getStartTime();
        Date endTime = seckill.getEndTime();
        //系统当前时间
        Date nowTime = new Date();
        if(nowTime.getTime() < startTime.getTime()
                || nowTime.getTime() > endTime.getTime()){
            return new Exposer(false,seckillId,nowTime.getTime(),startTime.getTime(),
                    endTime.getTime());
        }
        //转化特定字符串的过程,不可逆
        String md5 = getMD5(seckillId);//TODO
        return new Exposer(true,md5,seckillId);
    }

    private String getMD5(long seckillId){
        String base = seckillId+"/"+slat;
        String md5 = DigestUtils.md5DigestAsHex(base.getBytes());
        return md5;
    }
    @Override
    public SeckillExecution executeSeckill(long seckillId, long userPhone, String md5)
            throws SeckillException, RepeatKillExeception, SeckillCloseException {
        if(md5==null|| !md5.equals(getMD5(seckillId))){
            throw new SeckillException("seckill data rewrite");
        }
        //执行秒杀逻辑:减库存 + 记录购买行为
        Date nowTime = new Date();
        try{

            int updateCount = seckillDao.reduceNumber(seckillId, nowTime);
            if(updateCount <=0){
                //没有更新记录
                throw new SeckillCloseException("seckill is closed");
            } else {
                //记录购买行为
                int insertCount= successKilledDao.insertSuccessKilled(seckillId, userPhone);
                //唯一:insert ignore
                if(insertCount <=0){
                    //重复秒杀
                    throw new RepeatKillExeception("seckill repeated");
                }else {
                    //秒杀成功
                    SuccessKilled successKilled = successKilledDao.queryByIdWithSeckill(seckillId, userPhone);
                    //return new SeckillExecution(seckillId,1,"秒杀成功",successKilled);
                    return new  SeckillExecution(seckillId,SeckillStatEnum.SUCCESS);
                }
            }

        } catch (SeckillCloseException e1) {
            throw e1;
        } catch (RepeatKillExeception e2) {
            throw e2;
        }catch (Exception e){
            logger.error(e.getMessage(),e);
            //所有编译期异常 转化为运行期异常
            //spring事务会做roll back
            throw new SeckillException("seckill inner error : "+e.getMessage());
        }
    }

}

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"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context-4.1.xsd">
    <!-- 扫描service包下所使用注解的类型 -->
    <context:component-scan base-package="org.seckill.service"/>
</beans>

---3-1 使用Spring声明式事务理论---------------------------------------------------------

1.什么是声明式事务

  通过Spring来管理(全自动),解脱事务代码

2.声明式事务使用方式:

ProxyFactoryBean + XML  -------> 早期使用方式(2.0)

tx:advice + aop命名空间    ------> 一次配置永久生效

注解@Transactional (推荐) ------>注解控制()

注解控制:在控制事务方法上加入注解,在开发中大家遵守约定。

3.事务方法嵌套:

  声明式事务独有的概念

  传播行为--->propagation_required,如果有事务就加入到事务的原有逻辑,如果没有就创建一个新事务。

4.什么时候回滚:

  抛出运行期异常(RuntimeException)

  小心不当的try-catch(如果不小心抛出了编译期异常,Spring不会回滚)

---3-2 使用Spring声明式事务配置---------------------------------------------------------

---4-1 完成Service集成测试---------------------------------------------------------

时间: 2024-10-12 20:34:41

Java高并发秒时啊API之Service层1的相关文章

Java高并发秒杀API之业务分析与DAO层

课程介绍 高并发和秒杀都是当今的热门词汇,如何使用Java框架实现高并发秒杀API是该系列课程要研究的内容.秒杀系列课程分为四门,本门课程是第一门,主要对秒杀业务进行分析设计,以及DAO层的实现.课程中使用了流行的框架组合SpringMVC+Spring+MyBatis,还等什么,赶快来加入吧! 第1章 课程介绍 本章介绍秒杀系统的技术内容,以及系统演示.并介绍不同程度的学员可以学到什么内容. 第2章 梳理所有技术和搭建工程 本章首先介绍秒杀系统所用框架和技术点,然后介绍如何基于maven搭建项

2017.4.26 慕课网--Java 高并发秒杀API(一)

Java高并发秒杀API系列(一) -----------------业务分析及Dao层 第一章 课程介绍 1.1 内容介绍及业务分析 (1)课程内容 1 SSM框架的整合使用 2 秒杀类系统需求理解和实现 3 常用技术解决高并发问题 (2)SSM框架 (3)为何选择秒杀系统 1 秒杀系统具有典型的"事务"特性 2 秒杀/红包类需求越来越常见 3 面试常用问题 1.3 项目效果演示 第二章 梳理所有技术和搭建工程 2.1 相关技术介绍 2.2 创建项目和依赖 第三章 秒杀业务分析 3.

Java高并发秒杀系统API之SSM框架集成swagger与AdminLTE

初衷与整理描述 Java高并发秒杀系统API是来源于网上教程的一个Java项目,也是我接触Java的第一个项目.本来是一枚c#码农,公司计划部分业务转java,于是我利用业务时间自学Java才有了本文,本来接触之初听别人说,c#要转java很容易,我也信了,但是真正去学习的时候还是踩了无数个坑,好在朋友有几个做安卓的,向他们讨教了一些经验,但是他们做安卓的和web又是两个方向,于是继续一个人默默采坑避雷之旅,首先上手的是下面这个Java高并发秒杀系统API. 学习java的初衷一个是公司转行,二

imooc课程:Java高并发秒杀API 记录

Java高并发秒杀API之业务分析与DAO层 Java高并发秒杀API之Service层 Java高并发秒杀API之web层 Java高并发秒杀API之高并发优化 除了并发部分外的这个web开发的总结:https://www.imooc.com/video/11737 springmvc运行流程 BOOTSTRAP 和 JS 的使用技巧.(模块化.不混乱.抽取字典方便修改) JQ插件(countDown && cookie 等) 原文地址:https://www.cnblogs.com/a

【实战Java高并发程序设计 3】带有时间戳的对象引用:AtomicStampedReference

[实战Java高并发程序设计 1]Java中的指针:Unsafe类 [实战Java高并发程序设计 2]无锁的对象引用:AtomicReference AtomicReference无法解决上述问题的根本是因为对象在修改过程中,丢失了状态信息.对象值本身与状态被画上了等号.因此,我们只要能够记录对象在修改过程中的状态值,就可以很好的解决对象被反复修改导致线程无法正确判断对象状态的问题. AtomicStampedReference正是这么做的.它内部不仅维护了对象值,还维护了一个时间戳(我这里把它

Java高并发,如何解决,什么方式解决

对于我们开发的网站,如果网站的访问量非常大的话,那么我们就需要考虑相关的并发访问问题了.而并发问题是绝大部分的程序员头疼的问题, 但话又说回来了,既然逃避不掉,那我们就坦然面对吧~今天就让我们一起来研究一下常见的并发和同步吧. 为了更好的理解并发和同步,我们需要先明白两个重要的概念:同步和异步    1.同步和异步的区别和联系 所谓同步,可以理解为在执行完一个函数或方法之后,一直等待系统返回值或消息,这时程序是出于阻塞的,只有接收到 返回的值或消息后才往下执行其它的命令. 异步,执行完函数或方法

java高并发

转自:https://www.cnblogs.com/lr393993507/p/5909804.html 对于我们开发的网站,如果网站的访问量非常大的话,那么我们就需要考虑相关的并发访问问题了.而并发问题是绝大部分的程序员头疼的问题, 但话又说回来了,既然逃避不掉,那我们就坦然面对吧~今天就让我们一起来研究一下常见的并发和同步吧. 为了更好的理解并发和同步,我们需要先明白两个重要的概念:同步和异步    1.同步和异步的区别和联系 所谓同步,可以理解为在执行完一个函数或方法之后,一直等待系统返

java高并发系列 - 第15天:JUC中的Semaphore,最简单的限流工具类,必备技能

这是java高并发系列第15篇文章 Semaphore(信号量)为多线程协作提供了更为强大的控制方法,前面的文章中我们学了synchronized和重入锁ReentrantLock,这2种锁一次都只能允许一个线程访问一个资源,而信号量可以控制有多少个线程可以访问特定的资源. Semaphore常用场景:限流 举个例子: 比如有个停车场,有5个空位,门口有个门卫,手中5把钥匙分别对应5个车位上面的锁,来一辆车,门卫会给司机一把钥匙,然后进去找到对应的车位停下来,出去的时候司机将钥匙归还给门卫.停车

跟着阿里p7一起学java高并发 - 第18天:玩转java线程池,这一篇就够了

java中的线程池,这一篇就够了 java高并发系列第18篇文章. 本文主要内容 什么是线程池 线程池实现原理 线程池中常见的各种队列 自定义线程创建的工厂 常见的饱和策略 自定义饱和策略 线程池中两种关闭方法有何不同 扩展线程池 合理地配置线程池 线程池中线程数量的配置 什么是线程池 大家用jdbc操作过数据库应该知道,操作数据库需要和数据库建立连接,拿到连接之后才能操作数据库,用完之后销毁.数据库连接的创建和销毁其实是比较耗时的,真正和业务相关的操作耗时是比较短的.每个数据库操作之前都需要创