Full Code of justinbaby/spring-mybatis for AI

master 3c0c39e88ec9 cached
53 files
68.6 KB
22.4k tokens
118 symbols
1 requests
Download .txt
Repository: justinbaby/spring-mybatis
Branch: master
Commit: 3c0c39e88ec9
Files: 53
Total size: 68.6 KB

Directory structure:
gitextract_vsg0jjnm/

├── .github/
│   └── workflows/
│       └── maven.yml
├── .gitignore
├── LICENSE
├── README.md
├── docs/
│   └── script/
│       └── initDB.sql
├── pom.xml
├── seckill-client/
│   ├── pom.xml
│   └── src/
│       └── main/
│           └── java/
│               └── com/
│                   └── imooc/
│                       └── client/
│                           └── SeckillService.java
├── seckill-core/
│   ├── .gitignore
│   ├── pom.xml
│   └── src/
│       └── main/
│           ├── java/
│           │   └── com/
│           │       └── imooc/
│           │           ├── aop/
│           │           │   └── LogAOP.java
│           │           └── web/
│           │               └── SeckillController.java
│           ├── resources/
│           │   ├── logback.xml
│           │   └── spring/
│           │       ├── applicationContext.xml
│           │       ├── spring-dubbo-config.xml
│           │       ├── spring-dubbo-consumer.xml
│           │       └── spring-web.xml
│           └── webapp/
│               ├── WEB-INF/
│               │   ├── jsp/
│               │   │   ├── common/
│               │   │   │   ├── head.jsp
│               │   │   │   └── tag.jsp
│               │   │   ├── detail.jsp
│               │   │   └── list.jsp
│               │   └── web.xml
│               └── resources/
│                   └── js/
│                       └── seckill.js
├── seckill-model/
│   ├── pom.xml
│   └── src/
│       └── main/
│           └── java/
│               └── com/
│                   └── imooc/
│                       ├── dto/
│                       │   ├── Exposer.java
│                       │   ├── SeckillExecution.java
│                       │   └── SeckillResult.java
│                       ├── entity/
│                       │   ├── Seckill.java
│                       │   └── SuccessKilled.java
│                       ├── enums/
│                       │   └── SeckillStateEnum.java
│                       └── exception/
│                           ├── RepeatKillException.java
│                           ├── SeckillCloseException.java
│                           └── SeckillException.java
└── seckill-service-provider/
    ├── pom.xml
    └── src/
        └── main/
            ├── java/
            │   └── com/
            │       └── imooc/
            │           ├── dao/
            │           │   ├── SeckillDao.java
            │           │   ├── SuccessKilledDao.java
            │           │   └── cache/
            │           │       └── RedisDao.java
            │           └── service/
            │               └── impl/
            │                   ├── App.java
            │                   └── SeckillServiceImpl.java
            ├── resources/
            │   ├── dubbo.proerpties
            │   ├── jdbc.properties
            │   ├── logback.xml
            │   ├── mapper/
            │   │   ├── SeckillDao.xml
            │   │   └── SuccessKilledDao.xml
            │   ├── mybatis-config.xml
            │   └── spring/
            │       ├── applicationContext.xml
            │       ├── spring-dao.xml
            │       ├── spring-dubbo-config.xml
            │       ├── spring-dubbo-provider.xml
            │       ├── spring-service.xml
            │       └── spring-web.xml
            └── webapp/
                ├── WEB-INF/
                │   └── web.xml
                └── index.jsp

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/workflows/maven.yml
================================================
# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-maven

# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.

name: Java CI with Maven

on:
  push:
    branches: [ "master" ]
  pull_request:
    branches: [ "master" ]

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3
    - name: Set up JDK 17
      uses: actions/setup-java@v3
      with:
        java-version: '17'
        distribution: 'temurin'
        cache: maven
    - name: Build with Maven
      run: mvn -B package --file pom.xml

    # Optional: Uploads the full dependency graph to GitHub to improve the quality of Dependabot alerts this repository can receive
    - name: Update dependency graph
      uses: advanced-security/maven-dependency-submission-action@571e99aab1055c2e71a1e2309b9691de18d6b7d6


================================================
FILE: .gitignore
================================================
*.class

# Mobile Tools for Java (J2ME)
.mtj.tmp/

# Package Files #
*.jar
*.war
*.ear
*.idea

# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2020 justinbaby

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# seckill(Java高并发秒杀API)
一个spring入门项目,后续将更新spring中级项目 :)
#### 所用技术点
 - spring
 - springMVC: MVC框架
 - Tomcat: web容器
 - mybatis: ORM框架
 - bootstrap: css/html框架
 - JQuery: JS框架
 - Redis: NOSQL数据库
 - MySQL: 关系型数据库
 - Logback: 日志框架
 - JUnit: 单元测试
 - CDN: 内容分发服务器
 - Procedure:数据库存储过程
 - Protostuff:Google开发的基于Java语言的序列化库
 - ZooKeeper:分布式应用程序协调服务 
 - DUBBO:分布式应用服务框架 

## Java高并发秒杀系统API

本项目参考慕课网视频(版权方),并在此基础上进行了模块划分,功能添加,欢迎去官网观看!!!!

## 安装部署

 #### 软件环境:

  - IDEA
  - MySQL
  - JDK1.8或以上
  - tomcat 8.0
  - Redis
  - Maven
 #### 硬件环境(最小配置):

  - CPU:1核
  - 内存:1G

 #### 说明
 - seckill-core:秒杀核心模块,部署tomcat启动
 - seckill-api:秒杀api模块
 - seckill-base:秒杀工具类模块
 - seckill-web:秒杀页面模块

 #### 步骤
 1. 创建数据库,导入初始化脚本initDB.sql
 2. 修改系统数据库连接seckill-core/src/main/resources/jdbc.properties
 3. Tomcat运行

## FAQ
- Q:为什么我的maven下载依赖jar包这么慢
- A:可以自己下载maven,使用自己的Maven,修改maven安装目录下的/conf/settings.xml,在IDEA或eclipse里配置为默认的设置
```XML
                           <mirror>
                               <id>nexus-aliyun</id>
                               <mirrorOf>central</mirrorOf>
                               <name>Nexus aliyun</name>
                               <url>http://maven.aliyun.com/nexus/content/groups/public</url>
                           </mirror>
```

- Q:为什么我的数据库连不上
- A:查看一下jdbc.properties,配置url为你的数据库地址,你的数据库用户名和密码

- Q:为什控制台报Redis异常
- A:查看一下Redis服务器是否启动,没下载的建议去官网下载window或linux版

- Q:eclipse怎么导入
- A:去掉.开头的文件就可以导入!!!


================================================
FILE: docs/script/initDB.sql
================================================
/*

Source Server         : root
Source Server Version : 50538
Source Host           : localhost:3306
Source Database       : seckill

Target Server Type    : MYSQL
Target Server Version : 50538
File Encoding         : 65001

Date: 2017-02-17 12:05:42
*/

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for seckill
-- ----------------------------
DROP TABLE IF EXISTS `seckill`;
CREATE TABLE `seckill` (
  `seckill_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '商品库存ID',
  `name` varchar(120) NOT NULL COMMENT '商品名称',
  `number` int(11) NOT NULL COMMENT '库存数量',
  `start_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '秒杀开始时间',
  `end_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '秒杀结束时间',
  `create_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '创建时间',
  PRIMARY KEY (`seckill_id`),
  KEY `idx_start_time` (`start_time`),
  KEY `idx_end_time` (`end_time`),
  KEY `idx_create_time` (`create_time`)
) ENGINE=InnoDB AUTO_INCREMENT=1006 DEFAULT CHARSET=utf8 COMMENT='秒杀库存表';

-- ----------------------------
-- Records of seckill
-- ----------------------------
INSERT INTO `seckill` VALUES ('1000', '100元秒杀诺基亚', '10000', '2017-02-17 12:02:05', '2019-12-21 00:00:00', '2016-12-21 00:00:00');
INSERT INTO `seckill` VALUES ('1001', '5000元秒杀iphone7', '1700', '2017-02-17 11:47:36', '2016-04-11 00:00:00', '2016-04-11 00:00:00');
INSERT INTO `seckill` VALUES ('1002', '1000元秒杀ipad1', '3500', '2017-02-17 11:47:41', '2016-05-12 00:00:00', '2016-05-12 00:00:00');
INSERT INTO `seckill` VALUES ('1003', '1600元秒杀小米4', '1200', '2017-02-17 11:47:47', '2016-07-23 00:00:00', '2016-07-23 00:00:00');
INSERT INTO `seckill` VALUES ('1004', '1400元秒杀魅族4', '1099', '2017-02-17 12:02:28', '2018-02-17 11:48:00', '2017-02-17 11:48:00');
INSERT INTO `seckill` VALUES ('1005', '1400元秒杀小米3', '1100', '2017-02-17 11:48:23', '2016-01-21 00:00:00', '2016-01-21 00:00:00');

-- ----------------------------
-- Table structure for success_killed
-- ----------------------------
DROP TABLE IF EXISTS `success_killed`;
CREATE TABLE `success_killed` (
  `seckill_id` bigint(20) NOT NULL COMMENT '秒杀商品ID',
  `user_phone` bigint(20) NOT NULL COMMENT '用户手机号',
  `state` tinyint(4) NOT NULL DEFAULT '-1' COMMENT '状态标识:-1:无效 0:成功 1:已付款 2:已发货',
  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间',
  PRIMARY KEY (`seckill_id`,`user_phone`),
  KEY `idx_create_time` (`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='秒杀成功明细表';

-- ----------------------------
-- Records of success_killed
-- ----------------------------
INSERT INTO `success_killed` VALUES ('1004', '15643645806', '-1', '2017-02-17 12:02:27');

-- ----------------------------
-- View structure for v1
-- ----------------------------
DROP VIEW IF EXISTS `v1`;
CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost`  VIEW `v1` AS SELECT *FROM seckill ;

-- ----------------------------
-- Procedure structure for execute_seckill
-- ----------------------------
DROP PROCEDURE IF EXISTS `execute_seckill`;
DELIMITER ;;
CREATE DEFINER=`root`@`localhost` PROCEDURE `execute_seckill`(IN v_seckill_id bigint, IN v_phone BIGINT,
IN v_kill_time TIMESTAMP, OUT r_result INT)
BEGIN
		DECLARE insert_count INT DEFAULT 0;
		START TRANSACTION;
		INSERT ignore INTO success_killed (seckill_id, user_phone, create_time)
		VALUES(v_seckill_id, v_phone, v_kill_time);
		SELECT ROW_COUNT() INTO insert_count;
		IF (insert_count = 0) THEN
			ROLLBACK;
			SET r_result = -1;
		ELSEIF (insert_count < 0) THEN
			ROLLBACK ;
			SET r_result = -2;
		ELSE
			UPDATE seckill SET number = number - 1
			WHERE seckill_id = v_seckill_id AND end_time > v_kill_time
			AND start_time < v_kill_time AND number > 0;
			SELECT ROW_COUNT() INTO insert_count;
			IF (insert_count = 0) THEN
				ROLLBACK;
				SET r_result = 0;
			ELSEIF (insert_count < 0) THEN
				ROLLBACK;
				SET r_result = -2;
			ELSE
				COMMIT;
			SET r_result = 1;
			END IF;
		END IF;
	END
;;
DELIMITER ;
SET FOREIGN_KEY_CHECKS=1;


================================================
FILE: pom.xml
================================================
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.imooc</groupId>
    <artifactId>seckill</artifactId>
    <packaging>pom</packaging>
    <version>0.0.1-SNAPSHOT </version>
    <modules>
        <module>seckill-core</module>
        <module>seckill-model</module>
        <module>seckill-client</module>
    </modules>
    <name>seckill Maven Webapp</name>
    <url>http://maven.apache.org</url>
    <dependencies>
        <!-- 单元测试 	//test master add something -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.1</version>
        </dependency>

        <!-- 1.日志 -->
        <!-- 实现slf4j接口并整合 -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.0</version>
        </dependency>

        <!-- 2.数据库 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
			<version>8.0.16</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>c3p0</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.1.2</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.0.13</version>
        </dependency>

        <!-- DAO: MyBatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.6</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.3.2</version>
        </dependency>

        <!-- 3.Servlet web -->
        <dependency>
            <groupId>taglibs</groupId>
            <artifactId>standard</artifactId>
            <version>1.1.2</version>
        </dependency>
        <dependency>
            <groupId>jstl</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.10.7</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
        </dependency>

        <!-- 4.Spring -->
        <!-- 1)Spring核心 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>4.3.21.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>4.1.7.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.1.7.RELEASE</version>
        </dependency>
        <!-- 2)Spring DAO层 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>4.1.7.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>4.1.7.RELEASE</version>
        </dependency>
        <!-- 3)Spring web -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>4.1.7.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>4.1.7.RELEASE</version>
        </dependency>
        <!-- 4)Spring test -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>4.1.7.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>4.1.7.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>4.2.0.RELEASE</version>
        </dependency>

        <!-- redis客户端:Jedis -->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.7.3</version>
        </dependency>
        <dependency>
            <groupId>com.dyuproject.protostuff</groupId>
            <artifactId>protostuff-core</artifactId>
            <version>1.0.8</version>
        </dependency>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-api</artifactId>
            <version>7.0</version>
        </dependency>
        <dependency>
            <groupId>com.dyuproject.protostuff</groupId>
            <artifactId>protostuff-runtime</artifactId>
            <version>1.0.8</version>
        </dependency>

        <dependency>
            <groupId>commons-collections</groupId>
            <artifactId>commons-collections</artifactId>
            <version>3.2.2</version>
        </dependency>
    </dependencies>
    <build>
        <finalName>seckill</finalName>
    </build>
</project>


================================================
FILE: seckill-client/pom.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>seckill</artifactId>
        <groupId>com.imooc</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>seckill-client</artifactId>
    <dependencies>
        <dependency>
            <groupId>com.imooc</groupId>
            <artifactId>seckill-model</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>


</project>

================================================
FILE: seckill-client/src/main/java/com/imooc/client/SeckillService.java
================================================
package com.imooc.client;

import com.imooc.dto.Exposer;
import com.imooc.dto.SeckillExecution;
import com.imooc.entity.Seckill;
import com.imooc.exception.RepeatKillException;
import com.imooc.exception.SeckillCloseException;
import com.imooc.exception.SeckillException;

import java.util.List;

/**
 * 业务接口:站在"使用者"角度设计接口 三个方面:方法定义粒度,参数,返回类型(return 类型/异常)
 *
 * @author yan
 */
public interface SeckillService {

    /**
     * 查询所有秒杀记录
     *
     * @return
     */
    List<Seckill> getSeckillList();

    /**
     * 查询单个秒杀记录
     *
     * @param seckillId
     * @return
     */
    Seckill getById(long seckillId);

    /**
     * 秒杀开启时输出秒杀接口地址,否则输出系统时间和秒杀时间
     *
     * @param seckillId
     * @return
     */
    Exposer exportSeckillUrl(long seckillId);

    /**
     * 执行秒杀操作
     *
     * @param seckillId
     * @param userPhone
     * @param md5
     * @return
     * @throws SeckillException
     * @throws RepeatKillException
     * @throws SeckillCloseException
     */
    SeckillExecution executeSeckill(long seckillId, long userPhone, String md5)
            throws SeckillException, RepeatKillException, SeckillCloseException;

    /**
     * 执行秒杀操作by存储过程
     *
     * @param seckillId
     * @param userPhone
     * @param md5
     * @return
     * @throws SeckillException
     * @throws RepeatKillException
     * @throws SeckillCloseException
     */
    SeckillExecution executeSeckillProcedure(long seckillId, long userPhone, String md5)
            throws SeckillException, RepeatKillException, SeckillCloseException;

}

================================================
FILE: seckill-core/.gitignore
================================================
*.class

# Mobile Tools for Java (J2ME)
.mtj.tmp/

# Package Files #
*.jar
*.war
*.ear

# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*


================================================
FILE: seckill-core/pom.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>seckill</artifactId>
        <groupId>com.imooc</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>seckill-core</artifactId>
    <packaging>war</packaging>
    <name>seckill-dubbo-consumer Maven Webapp</name>
    <url>http://maven.apache.org</url>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <dependencies>
        <dependency>
            <groupId>com.imooc</groupId>
            <artifactId>seckill-model</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.imooc</groupId>
            <artifactId>seckill-client</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        <!-- Dubbo 依赖 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo</artifactId>
            <version>2.5.7</version>
            <exclusions>
                <exclusion>
                    <artifactId>spring</artifactId>
                    <groupId>org.springframework</groupId>
                </exclusion>
            </exclusions>
        </dependency>

        <!-- Zookeeper 依赖 -->
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.5.3-beta</version>
            <exclusions>
                <exclusion>
                    <artifactId>log4j</artifactId>
                    <groupId>log4j</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.101tec</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.8</version>
        </dependency>
    </dependencies>

</project>

================================================
FILE: seckill-core/src/main/java/com/imooc/aop/LogAOP.java
================================================
package com.imooc.aop;


import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;

/**
 * @author yan
 *         <p>
 *         采用AOP的方式处理参数问题。
 */
@Component
@Aspect
public class LogAOP {

    private final Logger LOG = LoggerFactory.getLogger(this.getClass());

    @Pointcut("execution(* com.imooc.web.*.*(..))")
    public void aopMethod() {
    }

    @Around("aopMethod()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        String classType = joinPoint.getTarget().getClass().getName();
        //运用反射的原理创建对象
        Class<?> clazz = Class.forName(classType);
        String clazzName = clazz.getName();
        String clazzSimpleName = clazz.getSimpleName();
        String methodName = joinPoint.getSignature().getName();
        Logger logger = LoggerFactory.getLogger(clazzName);
        logger.info("clazzName: " + clazzName + ", methodName:" + methodName);
        long start = System.currentTimeMillis();
        LOG.info("before method invoking!");
        BindingResult bindingResult = null;
        System.out.println("---------------");
        System.out.println("调用类:" + clazzSimpleName);
        System.out.println("调用方法:" + methodName);
        return joinPoint.proceed();
    }
}

================================================
FILE: seckill-core/src/main/java/com/imooc/web/SeckillController.java
================================================
package com.imooc.web;

import com.imooc.dto.SeckillExecution;
import com.imooc.exception.SeckillCloseException;
import com.imooc.dto.Exposer;
import com.imooc.dto.SeckillResult;
import com.imooc.entity.Seckill;
import com.imooc.enums.SeckillStateEnum;
import com.imooc.exception.RepeatKillException;
import com.imooc.client.SeckillService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

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

@Controller // @Service @Componet
@RequestMapping("/seckill") // url:/模块/资源/{id}/细分 /seckill/list
public class SeckillController {

	//sb
	private Logger logger = LoggerFactory.getLogger(this.getClass());

	@Autowired
	private SeckillService seckillService;
	//http://localhost:8080/seckill/seckill/list
	@RequestMapping(value = "/list", method = RequestMethod.GET)
	public String list(Model model) {
		// 获取列表页
		List<Seckill> list = seckillService.getSeckillList();
		model.addAttribute("list", list);
		// list.jsp + model = ModelAndView
		return "list";// WEB-INF/jsp/"list".jsp
	}

	@RequestMapping(value = "/{seckillId}/detail", method = RequestMethod.GET)
	public String detail(@PathVariable("seckillId") Long seckillId, Model model) {
		if (seckillId == null) {
			return "redirect:/seckill/list";
		}
		Seckill seckill = seckillService.getById(seckillId);
		if (seckill == null) {
			return "forward:/seckill/list";
		}
		model.addAttribute("seckill", seckill);
		return "detail";
	}

	// ajax json
	@RequestMapping(value = "/{seckillId}/exposer", method = RequestMethod.POST, produces = {
			"application/json; charset=utf-8" })
	@ResponseBody
	public SeckillResult<Exposer> exposer(@PathVariable("seckillId") Long seckillId) {
		SeckillResult<Exposer> result;
		try {
			Exposer exposer = seckillService.exportSeckillUrl(seckillId);
			result = new SeckillResult<Exposer>(true, exposer);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			result = new SeckillResult<Exposer>(false, e.getMessage());
		}
		return result;
	}

	@RequestMapping(value = "/{seckillId}/{md5}/execution", method = RequestMethod.POST, produces = {
			"application/json; charset=utf-8" })
	@ResponseBody
	public SeckillResult<SeckillExecution> execute(@PathVariable("seckillId") Long seckillId,
												   @PathVariable("md5") String md5, @CookieValue(value = "killPhone", required = false) Long phone) {
		// springmvc valid
		if (phone == null) {
			return new SeckillResult<SeckillExecution>(false, "未注册");
		}
		try {
			// 存储过程调用
			SeckillExecution execution = seckillService.executeSeckillProcedure(seckillId, phone, md5);
			return new SeckillResult<SeckillExecution>(true, execution);
		} catch (RepeatKillException e) {
			SeckillExecution execution = new SeckillExecution(seckillId, SeckillStateEnum.REPEAT_KILL);
			return new SeckillResult<SeckillExecution>(true, execution);
		} catch (SeckillCloseException e) {
			SeckillExecution execution = new SeckillExecution(seckillId, SeckillStateEnum.END);
			return new SeckillResult<SeckillExecution>(true, execution);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			SeckillExecution execution = new SeckillExecution(seckillId, SeckillStateEnum.INNER_ERROR);
			return new SeckillResult<SeckillExecution>(true, execution);
		}
	}

	@RequestMapping(value = "/time/now", method = RequestMethod.GET)
	@ResponseBody
	public SeckillResult<Long> time() {
		Date now = new Date();
		return new SeckillResult<Long>(true, now.getTime());
	}

}


================================================
FILE: seckill-core/src/main/resources/logback.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true">
	<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
		<!-- encoders are by default assigned the type ch.qos.logback.classic.encoder.PatternLayoutEncoder -->
		<encoder>
			<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
		</encoder>
	</appender>

	<root level="debug">
		<appender-ref ref="STDOUT" />
	</root>
</configuration>

================================================
FILE: seckill-core/src/main/resources/spring/applicationContext.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <import resource="spring-*"/>
</beans>

================================================
FILE: seckill-core/src/main/resources/spring/spring-dubbo-config.xml
================================================
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://code.alibabatech.com/schema/dubbo
    http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

    <dubbo:application name="seckill-service-consumer" owner="seckill" organization="seckill-service-consumer" logger="slf4j"/>
    <dubbo:registry address="zookeeper://127.0.0.1:2181"/>
    <dubbo:protocol name="dubbo" port="20882" host="127.0.0.1"/>
    <dubbo:provider timeout="15000" retries="0" delay="-1"/>
    <dubbo:consumer check="false" timeout="15000"/>
</beans>

================================================
FILE: seckill-core/src/main/resources/spring/spring-dubbo-consumer.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:dubbo="http://code.alibabatech.com/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://code.alibabatech.com/schema/dubbo
    http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
    <!-- 生成远程服务代理,可以和本地bean一样使用demoService -->
    <dubbo:reference id="seckillService" interface="com.imooc.client.SeckillService" />
</beans>

================================================
FILE: seckill-core/src/main/resources/spring/spring-web.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"
	   xmlns:mvc="http://www.springframework.org/schema/mvc"
	   xmlns:aop="http://www.springframework.org/schema/aop"
	   xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context.xsd
	http://www.springframework.org/schema/mvc
	http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
	http://www.springframework.org/schema/aop
	http://www.springframework.org/schema/aop/spring-aop.xsd">

	<!-- 激活组件扫描功能,扫描aop的相关组件组件 -->
	<context:component-scan base-package="com.imooc.aop"/>
	<!-- 启动对@AspectJ注解的支持 -->
	<aop:aspectj-autoproxy proxy-target-class="false" />

	<!-- 配置SpringMVC -->
	<!-- 1.开启SpringMVC注解模式 -->
	<!-- 简化配置: 
		(1)自动注册DefaultAnootationHandlerMapping,AnotationMethodHandlerAdapter 
		(2)提供一些列:数据绑定,数字和日期的format @NumberFormat, @DateTimeFormat, xml,json默认读写支持 
	-->
	<mvc:annotation-driven />
	
	<!-- 2.静态资源默认servlet配置
		(1)加入对静态资源的处理:js,gif,png
		(2)允许使用"/"做整体映射
	 -->
	 <mvc:default-servlet-handler/>
	 
	 <!-- 3.配置jsp 显示ViewResolver -->
	 <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	 	<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
	 	<property name="prefix" value="/WEB-INF/jsp/" />
	 	<property name="suffix" value=".jsp" />
	 </bean>
	 
	 <!-- 4.扫描web相关的bean -->
	 <context:component-scan base-package="com.imooc.web" />
</beans>

================================================
FILE: seckill-core/src/main/webapp/WEB-INF/jsp/common/head.jsp
================================================
<%  
    String path = request.getContextPath();  
    String basePath = request.getScheme() + "://"  
            + request.getServerName() + ":" + request.getServerPort()  
            + path + "/";  
    pageContext.setAttribute("basePath",basePath);    
%>

<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->

<!-- 新 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet"
	href="//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css">
	
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
      <script src="//cdn.bootcss.com/html5shiv/3.7.2/html5shiv.min.js"></script>
      <script src="//cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->


================================================
FILE: seckill-core/src/main/webapp/WEB-INF/jsp/common/tag.jsp
================================================
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

================================================
FILE: seckill-core/src/main/webapp/WEB-INF/jsp/detail.jsp
================================================
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<%@include file="common/head.jsp"%>
<title>秒杀详情页</title>
</head>
<body>
<input type="hidden" id="basePath" value="${basePath}" />
	<div class="container">
		<div class="panel panel-default text-center">
			<div class="panel-heading">
				<h1>${seckill.name}</h1>
			</div>
			<div class="panel-body">
				<h2 class="text-danger">
					<!-- 显示time图标 -->
					<span class="glyphicon glyphicon-time"></span>
					<!-- 展示倒计时 -->
					<span class="glyphicon" id="seckillBox"></span>
				</h2>
			</div>
		</div>
	</div>

	<!-- 登录弹出层,输入电话 -->
	<div id="killPhoneModal" class="modal fade">
		<div class="modal-dialog">
			<div class="modal-content">
				<div class="modal-header">
					<h3 class="modal-title text-center">
						<span class="glyphicon glyphicon-phone"></span>秒杀电话:
					</h3>
				</div>
				<div class="modal-body">
					<div class="row">
						<div class="col-xs-8 col-xs-offset-2">
							<input type="text" name="killphone" id="killphoneKey"
								placeholder="填手机号^O^" class="form-control" />
						</div>
					</div>
				</div>
				<div class="modal-footer">
					<span id="killphoneMessage" class="glyphicon"></span>
					<button type="button" id="killPhoneBtn" class="btn btn-success">
						<span class="glyphicon glyphicon-phone"></span> Submit
					</button>
				</div>
			</div>
		</div>
	</div>

	<!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
	<script src="//cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>
	<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
	<script src="//cdn.bootcss.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
	<!-- jQuery cookie操作插件 -->
	<script src="//cdn.bootcss.com/jquery-cookie/1.4.1/jquery.cookie.min.js"></script>
	<!-- jQery countDonw倒计时插件  -->
	<script src="//cdn.bootcss.com/jquery.countdown/2.1.0/jquery.countdown.min.js"></script>
	<!-- 开始编写交互逻辑 -->
	<script src="${basePath}resources/js/seckill.js"  type="text/javascript"></script>
	<script type="text/javascript">
		$(function(){
			//使用EL表达式传入参数
			seckill.detail.init({
				seckillId : ${seckill.seckillId},
				startTime : ${seckill.startTime.time},//毫秒
				endTime : ${seckill.endTime.time}
			});
		});
	</script>
</body>
</html>

================================================
FILE: seckill-core/src/main/webapp/WEB-INF/jsp/list.jsp
================================================
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!-- 引入jstl -->
<%@include file="common/tag.jsp" %>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<%@include file="common/head.jsp"%>
<title>秒杀列表页</title>
</head>
<body>
	<!-- 页面显示部分 -->
	<div class="container">
		<div class="panel panel-default">
			<div class="panel-heading text-center">
				<h2>秒杀列表</h2>
			</div>
			<div class="panel-body">
				<table class="table table-hover">
					<thead>
						<tr>
							<th>名称</th>
							<th>库存</th>
							<th>开始时间</th>
							<th>结束时间</th>
							<th>创建时间</th>
							<th>详情页</th>
						</tr>
					</thead>
					<tbody>
						<c:forEach var="sk" items="${list}">
							<tr>
								<td>${sk.name}</td>
								<td>${sk.number}</td>
								<td>
									<fmt:formatDate value="${sk.startTime}" pattern="yyy-MM-dd HH:mm:ss"/>
								</td>
								<td>
									<fmt:formatDate value="${sk.endTime}" pattern="yyy-MM-dd HH:mm:ss"/>
								</td>
								<td>
									<fmt:formatDate value="${sk.createTime}" pattern="yyy-MM-dd HH:mm:ss"/>
								</td>
								<td>
									<a class="btn btn-info" href="${basePath}seckill/${sk.seckillId}/detail" target="_blank">link</a>
								</td>
							</tr>
						</c:forEach>
					</tbody>
				</table>
			</div>
		</div>
	</div>

	<!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
	<script src="//cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>
	<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
	<script src="//cdn.bootcss.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
</body>
</html>

================================================
FILE: seckill-core/src/main/webapp/WEB-INF/web.xml
================================================
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
	version="3.1" metadata-complete="true">
	<!-- 修改servlet版本为3.1 -->
	<!-- 配置DispatcherServlet -->
	<servlet>
		<servlet-name>seckill-dispatcher</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<!-- 配置springMVC需要加载的配置文件
			spring-dao.xml,spring-service.xml,spring-web.xml
			Mybatis - > spring -> springmvc
		 -->
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:spring/applicationContext.xml</param-value>
		</init-param>
	</servlet>
	<servlet-mapping>
			<servlet-name>seckill-dispatcher</servlet-name>
		<!-- 默认匹配所有的请求 -->
		<url-pattern>/</url-pattern>
	</servlet-mapping>
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:spring/applicationContext.xml</param-value>
	</context-param>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
</web-app>


================================================
FILE: seckill-core/src/main/webapp/resources/js/seckill.js
================================================
// 存放主要交换逻辑js代码
// javascript 模块化
var seckill = {
	// 封装秒杀相关ajax的url
	URL : {
		basePath : function() {
			return $('#basePath').val();
		},
		now : function() {
			return seckill.URL.basePath() + 'seckill/time/now';
		},
		exposer : function(seckillId) {
			return seckill.URL.basePath() + 'seckill/' + seckillId + '/exposer';
		},
		execution : function(seckillId, md5) {
			return seckill.URL.basePath() + 'seckill/' + seckillId + '/' + md5 + '/execution';
		}
	},
	// 处理秒杀逻辑
	handleSeckill : function(seckillId, node) {
		// 获取秒杀地址,控制显示逻辑,执行秒杀
		node.hide().html('<button class="btn btn-primary btn-lg" id="killBtn">开始秒杀</button>');
		console.log('exposerUrl=' + seckill.URL.exposer(seckillId));//TODO
		$.post(seckill.URL.exposer(seckillId), {}, function(result) {
			// 在回调函数中,执行交互流程
			if (result && result['success']) {
				var exposer = result['data'];
				if (exposer['exposed']) {
					// 开启秒杀
					var md5 = exposer['md5'];
					var killUrl = seckill.URL.execution(seckillId, md5);
					console.log('killUrl=' + killUrl);//TODO
					$('#killBtn').one('click', function() {
						// 执行秒杀请求
						// 1.先禁用按钮
						$(this).addClass('disabled');
						// 2.发送秒杀请求
						$.post(killUrl, {}, function(result) {
							if (result && result['success']) {
								var killResult = result['data'];
								var state = killResult['state'];
								var stateInfo = killResult['stateInfo'];
								// 3.显示秒杀结果
								node.html('<span class="label label-success">' + stateInfo + '</span>');
							}
						});
					});
					node.show();
				} else {
					// 未开启秒杀
					var now = exposer['now'];
					var start = exposer['start'];
					var end = exposer['end'];
					// 重新计算计时逻辑
					seckill.countdown(seckillId, now, start, end);
				}
			} else {
				console.log('result=' + result);
			}
		});
	},
	// 验证手机号
	validatePhone : function(phone) {
		if (phone && phone.length == 11 && !isNaN(phone)) {
			return true;
		} else {
			return false;
		}
	},
	// 倒计时
	countdown : function(seckillId, nowTime, startTime, endTime) {
		// 时间判断
		var seckillBox = $('#seckillBox');
		if (nowTime > endTime) {
			// 秒杀结束
			seckillBox.html('秒杀结束!');
		} else if (nowTime < startTime) {
			// 秒杀未开始,计时事件绑定
			var killTime = new Date(startTime + 1000);
			seckillBox.countdown(killTime, function(event) {
				// 时间格式
				var format = event.strftime('秒杀倒计时:%D天 %H时 %M分 %S秒');
				seckillBox.html(format);
				// 时间完成后回调事件
			}).on('finish.countdown', function() {
				// 获取秒杀地址,控制显示逻辑,执行秒杀
				seckill.handleSeckill(seckillId, seckillBox);
			});
		} else {
			// 秒杀开始
			seckill.handleSeckill(seckillId ,seckillBox);
		}
	},
	// 详情页秒杀逻辑
	detail : {
		// 详情页初始化
		init : function(params) {
			// 用户手机验证和登录,计时交互
			// 规划我们的交互流程
			// 在cookie中查找手机号
			var killPhone = $.cookie('killPhone');
			var startTime = params['startTime'];
			var endTime = params['endTime'];
			var seckillId = params['seckillId'];
			// 验证手机号
			if (!seckill.validatePhone(killPhone)) {
				// 绑定phone
				// 控制输出
				var killPhoneModal = $('#killPhoneModal');
				killPhoneModal.modal({
					show : true,// 显示弹出层
					backdrop : 'static',// 禁止位置关闭
					keyboard : false
				// 关闭键盘事件
				})
				$('#killPhoneBtn').click(function() {
					var inputPhone = $('#killphoneKey').val();
					console.log('inputPhone='+inputPhone);//TODO
					if (seckill.validatePhone(inputPhone)) {
						// 电话写入cookie
						$.cookie('killPhone', inputPhone, {
							expires : 7,
							path : '/seckill'
						});
						// 刷新页面
						window.location.reload();
					} else {
						$('#killphoneMessage').hide().html('<label class="label label-danger">手机号错误!</label>').show(300);
					}
				});
			}
			// 已经登录
			// 计时交互
			var startTime = params['startTime'];
			var endTime = params['endTime'];
			var seckillId = params['seckillId'];
			$.get(seckill.URL.now(), {}, function(result) {
				if (result && result['success']) {
					var nowTime = result['data'];
					// 时间判断,计时交互
					seckill.countdown(seckillId, nowTime, startTime, endTime);
				} else {
					console.log(result['reult:'] + result);
				}
			});
		}
	}
}


================================================
FILE: seckill-model/pom.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>seckill</artifactId>
        <groupId>com.imooc</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>seckill-model</artifactId>


</project>

================================================
FILE: seckill-model/src/main/java/com/imooc/dto/Exposer.java
================================================
package com.imooc.dto;

import java.io.Serializable;

/**
 * 暴露秒杀接口DTO
 * 
 * @author yan
 */
public class Exposer implements Serializable {

	// 是否开启秒杀
	private boolean exposed;

	// 一种加密措施
	private String md5;

	// id
	private long seckillId;

	// 系统当前时间(毫秒)
	private long now;

	// 开启时间
	private long start;

	// 结束时间
	private long end;

	public Exposer(boolean exposed, String md5, long seckillId) {
		this.exposed = exposed;
		this.md5 = md5;
		this.seckillId = seckillId;
	}

	public Exposer(boolean exposed, long seckillId, long now, long start, long end) {
		this.exposed = exposed;
		this.seckillId = seckillId;
		this.now = now;
		this.start = start;
		this.end = end;
	}

	public Exposer(boolean exposed, long seckillId) {
		this.exposed = exposed;
		this.seckillId = seckillId;
	}

	public boolean isExposed() {
		return exposed;
	}

	public void setExposed(boolean exposed) {
		this.exposed = exposed;
	}

	public String getMd5() {
		return md5;
	}

	public void setMd5(String md5) {
		this.md5 = md5;
	}

	public long getSeckillId() {
		return seckillId;
	}

	public void setSeckillId(long seckillId) {
		this.seckillId = seckillId;
	}

	public long getNow() {
		return now;
	}

	public void setNow(long now) {
		this.now = now;
	}

	public long getStart() {
		return start;
	}

	public void setStart(long start) {
		this.start = start;
	}

	public long getEnd() {
		return end;
	}

	public void setEnd(long end) {
		this.end = end;
	}
		
	//重写toString方法
	@Override
	public String toString() {
		return "Exposer [exposed=" + exposed + ", md5=" + md5 + ", seckillId=" + seckillId + ", now=" + now + ", start="
				+ start + ", end=" + end + "]";
	}

}


================================================
FILE: seckill-model/src/main/java/com/imooc/dto/SeckillExecution.java
================================================
package com.imooc.dto;

import com.imooc.entity.SuccessKilled;
import com.imooc.enums.SeckillStateEnum;

import java.io.Serializable;

/**
 * 封装秒杀执行后结果
 * 
 * @author yan
 */
public class SeckillExecution implements Serializable {

	private Long seckillId;

	// 秒杀执行结果状态
	private Integer state;

	// 状态标识
	private String stateInfo;

	// 秒杀成功对象
	private SuccessKilled successKilled;

	public SeckillExecution(Long seckillId, SeckillStateEnum stateEnum, SuccessKilled successKilled) {
		this.seckillId = seckillId;
		this.state = stateEnum.getState();
		this.stateInfo = stateEnum.getStateInfo();
		this.successKilled = successKilled;
	}

	public SeckillExecution(Long seckillId, SeckillStateEnum stateEnum) {
		this.seckillId = seckillId;
		if(stateEnum!=null){
			this.state = stateEnum.getState();
			this.stateInfo = stateEnum.getStateInfo();
		}
	}

	public Long getSeckillId() {
		return seckillId;
	}

	public void setSeckillId(Long seckillId) {
		this.seckillId = seckillId;
	}

	public Integer getState() {
		return state;
	}

	public void setState(Integer state) {
		this.state = state;
	}

	public String getStateInfo() {
		return stateInfo;
	}

	public void setStateInfo(String stateInfo) {
		this.stateInfo = stateInfo;
	}

	public SuccessKilled getSuccessKilled() {
		return successKilled;
	}

	public void setSuccessKilled(SuccessKilled successKilled) {
		this.successKilled = successKilled;
	}

	@Override
	public String toString() {
		return "SeckillExecution [seckillId=" + seckillId + ", state=" + state + ", stateInfo=" + stateInfo
				+ ", successKilled=" + successKilled + "]";
	}

}


================================================
FILE: seckill-model/src/main/java/com/imooc/dto/SeckillResult.java
================================================
package com.imooc.dto;

//封装json结果
public class SeckillResult<T> {

	private boolean success;

	private T data;

	private String error;

	public SeckillResult(boolean success, String error) {
		this.success = success;
		this.error = error;
	}

	public SeckillResult(boolean success, T data) {
		this.success = success;
		this.data = data;
	}

	public boolean isSuccess() {
		return success;
	}

	public void setSuccess(boolean success) {
		this.success = success;
	}

	public T getData() {
		return data;
	}

	public void setData(T data) {
		this.data = data;
	}

	public String getError() {
		return error;
	}

	public void setError(String error) {
		this.error = error;
	}

	@Override
	public String toString() {
		return "SeckillResult [success=" + success + ", data=" + data + ", error=" + error + "]";
	}

}


================================================
FILE: seckill-model/src/main/java/com/imooc/entity/Seckill.java
================================================
package com.imooc.entity;

import java.io.Serializable;
import java.util.Date;

/**
 * 秒杀库存实体
 * 
 * @author yan
 */
public class Seckill implements Serializable {
	private long seckillId;

	private String name;

	private int number;

	private Date startTime;

	private Date endTime;

	private Date createTime;

	public long getSeckillId() {
		return seckillId;
	}

	public void setSeckillId(long seckillId) {
		this.seckillId = seckillId;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getNumber() {
		return number;
	}

	public void setNumber(int number) {
		this.number = number;
	}

	public Date getStartTime() {
		return startTime;
	}

	public void setStartTime(Date startTime) {
		this.startTime = startTime;
	}

	public Date getEndTime() {
		return endTime;
	}

	public void setEndTime(Date endTime) {
		this.endTime = endTime;
	}

	public Date getCreateTime() {
		return createTime;
	}

	public void setCreateTime(Date createTime) {
		this.createTime = createTime;
	}

	@Override
	public String toString() {
		return "Seckill [seckillId=" + seckillId + ", name=" + name + ", number=" + number + ", startTime=" + startTime
				+ ", endTime=" + endTime + ", createTime=" + createTime + "]";
	}

}


================================================
FILE: seckill-model/src/main/java/com/imooc/entity/SuccessKilled.java
================================================
package com.imooc.entity;

import java.io.Serializable;
import java.util.Date;

/**
 * 成功秒杀实体
 * 
 * @author yan
 */
public class SuccessKilled implements Serializable {

	private long seckillId;

	private long userPhone;

	private short state;

	private Date creteTime;

	// 多对一的复合属性
	private Seckill seckill;

	public long getSeckillId() {
		return seckillId;
	}

	public void setSeckillId(long seckillId) {
		this.seckillId = seckillId;
	}

	public long getUserPhone() {
		return userPhone;
	}

	public void setUserPhone(long userPhone) {
		this.userPhone = userPhone;
	}

	public short getState() {
		return state;
	}

	public void setState(short state) {
		this.state = state;
	}

	public Date getCreteTime() {
		return creteTime;
	}

	public void setCreteTime(Date creteTime) {
		this.creteTime = creteTime;
	}

	public Seckill getSeckill() {
		return seckill;
	}

	public void setSeckill(Seckill seckill) {
		this.seckill = seckill;
	}

	@Override
	public String toString() {
		return "SuccessKilled [seckillId=" + seckillId + ", userPhone=" + userPhone + ", state=" + state
				+ ", creteTime=" + creteTime + "]";
	}

}


================================================
FILE: seckill-model/src/main/java/com/imooc/enums/SeckillStateEnum.java
================================================
package com.imooc.enums;

/**
 * 使用枚举表述常量数据字典
 *
 * @author yan
 */
public enum SeckillStateEnum {

    SUCCESS(1, "秒杀成功"), END(0, "秒杀结束"),

    REPEAT_KILL(-1, "重复秒杀"),

    INNER_ERROR(-2, "系统异常"),

    DATA_REWRITE(-3, "数据篡改");

    private Integer state;

    private String stateInfo;

    private SeckillStateEnum(int state, String stateInfo) {
        this.state = state;
        this.stateInfo = stateInfo;
    }

    public Integer getState() {
        return state;
    }

    public String getStateInfo() {
        return stateInfo;
    }

    public static SeckillStateEnum stateOf(Integer index) {
        for (SeckillStateEnum state : values()) {
            if (state.getState().equals(index)) {
                return state;
            }
        }
        return null;
    }

}


================================================
FILE: seckill-model/src/main/java/com/imooc/exception/RepeatKillException.java
================================================
package com.imooc.exception;

/**
 * 重复秒杀异常(运行期异常)
 * 
 * @author yan
 */
public class RepeatKillException extends SeckillException {
	public RepeatKillException(String message) {
		super(message);
	}

	public RepeatKillException(String message, Throwable cause) {
		super(message, cause);
	}

}


================================================
FILE: seckill-model/src/main/java/com/imooc/exception/SeckillCloseException.java
================================================
package com.imooc.exception;

/**
 * 秒杀关闭异常
 * 
 * @author yan
 */
public class SeckillCloseException extends SeckillException {

	public SeckillCloseException(String message) {
		super(message);
	}

	public SeckillCloseException(String message, Throwable cause) {
		super(message, cause);
	}

}


================================================
FILE: seckill-model/src/main/java/com/imooc/exception/SeckillException.java
================================================
package com.imooc.exception;

/**
 * 秒杀相关业务异常
 * 
 * @author yan
 */
public class SeckillException extends RuntimeException {

	public SeckillException(String message) {
		super(message);
	}

	public SeckillException(String message, Throwable cause) {
		super(message, cause);
	}

}


================================================
FILE: seckill-service-provider/pom.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>seckill</artifactId>
        <groupId>com.imooc</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>seckill-service</artifactId>
    <packaging>war</packaging>
    <name>seckill-dubbo-consumer Maven Webapp</name>
    <url>http://maven.apache.org</url>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <dependencies>
        <dependency>
            <groupId>com.imooc</groupId>
            <artifactId>seckill-model</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.imooc</groupId>
            <artifactId>seckill-client</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        <!-- Dubbo 依赖 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo</artifactId>
            <version>2.5.7</version>
            <exclusions>
                <exclusion>
                    <artifactId>spring</artifactId>
                    <groupId>org.springframework</groupId>
                </exclusion>
            </exclusions>
        </dependency>

        <!-- Zookeeper 依赖 -->
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.5.3-beta</version>
            <exclusions>
                <exclusion>
                    <artifactId>log4j</artifactId>
                    <groupId>log4j</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.101tec</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.8</version>
        </dependency>
    </dependencies>


</project>

================================================
FILE: seckill-service-provider/src/main/java/com/imooc/dao/SeckillDao.java
================================================
package com.imooc.dao;

import com.imooc.entity.Seckill;
import org.apache.ibatis.annotations.Param;

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

/**
 * 秒杀库存DAO接口
 * 
 * @author yan
 */
public interface SeckillDao {

	/**
	 * 减库存
	 * 
	 * @param seckillId
	 * @param killTime
	 * @return 如果影响行数等于>1,表示更新的记录行数
	 */
	int reduceNumber(@Param("seckillId") long seckillId, @Param("killTime") Date killTime);

	/**
	 * 根据id查询秒杀对象
	 * 
	 * @param seckillId
	 * @return
	 */
	Seckill queryById(long seckillId);

	/**
	 * 根据偏移量查询秒杀商品列表
	 * 
	 * @param offset
	 * @param limit
	 * @return
	 */
	List<Seckill> queryAll(@Param("offset") int offset, @Param("limit") int limit);

	/**
	 * 使用存储过程执行秒杀
	 * 
	 * @param paramMap
	 */
	void killByProcedure(Map<String, Object> paramMap);

}


================================================
FILE: seckill-service-provider/src/main/java/com/imooc/dao/SuccessKilledDao.java
================================================
package com.imooc.dao;

import com.imooc.entity.SuccessKilled;
import org.apache.ibatis.annotations.Param;

public interface SuccessKilledDao {

	/**
	 * 插入购买明细,可过滤重复
	 * 
	 * @param seckillId
	 * @param userPhone
	 * @return 插入的行数
	 */
	int insertSuccessKilled(@Param("seckillId") long seckillId, @Param("userPhone") long userPhone);

	/**
	 * 根据id查询SuccessKilled并携带秒杀产品对象实体
	 * 
	 * @param seckillId
	 * @param userPhone
	 * @return
	 */
	SuccessKilled queryByIdWithSeckill(@Param("seckillId") long seckillId, @Param("userPhone") long userPhone);

}


================================================
FILE: seckill-service-provider/src/main/java/com/imooc/dao/cache/RedisDao.java
================================================
package com.imooc.dao.cache;

import com.dyuproject.protostuff.LinkedBuffer;
import com.dyuproject.protostuff.ProtostuffIOUtil;
import com.dyuproject.protostuff.runtime.RuntimeSchema;
import com.imooc.entity.Seckill;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

public class RedisDao {

	private final Logger logger = LoggerFactory.getLogger(this.getClass());

	private final JedisPool jedisPool;

	private RuntimeSchema<Seckill> schema = RuntimeSchema.createFrom(Seckill.class);

	public RedisDao(String ip, int port) {
		jedisPool = new JedisPool(ip, port);
	}

	public Seckill getSeckill(long seckillId) {
		// redis操作逻辑
		try {
			Jedis jedis = jedisPool.getResource();
			try {
				String key = "seckill:" + seckillId;
				// 并没有实现内部序列化操作
				// get -> byte[] -> 反序列化 -> object[Seckill]
				// 采用自定义序列化
				// protostuff : pojo.
				byte[] bytes = jedis.get(key.getBytes());
				if (bytes != null) {
					Seckill seckill = schema.newMessage();
					ProtostuffIOUtil.mergeFrom(bytes, seckill, schema);
					// seckill被反序列化
					return seckill;
				}
			} finally {
				jedis.close();
			}
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
		return null;
	}

	public String putSeckill(Seckill seckill) {
		// set Object(Seckill) -> 序列号 -> byte[]
		try {
			Jedis jedis = jedisPool.getResource();
			try {
				String key = "seckill:" + seckill.getSeckillId();
				byte[] bytes = ProtostuffIOUtil.toByteArray(seckill, schema,
						LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE));
				// 超时缓存
				int timeout = 60 * 60;
				String result = jedis.setex(key.getBytes(), timeout, bytes);
				return result;
			} finally {
				jedis.close();
			}
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
		return null;
	}

}


================================================
FILE: seckill-service-provider/src/main/java/com/imooc/service/impl/App.java
================================================
package com.imooc.service.impl;

import com.imooc.client.SeckillService;
import com.imooc.entity.Seckill;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.IOException;
import java.util.List;

public class App {
    public static void main(String[] args) throws IOException {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"spring/applicationContext.xml"});
        context.start();
        SeckillService seckillService = context.getBean("seckillService",SeckillService.class);
        List<Seckill> getSeckillList = seckillService.getSeckillList();
        System.out.println(getSeckillList);
        System.out.println("press any key to exit.");
        System.in.read();
    }
}


================================================
FILE: seckill-service-provider/src/main/java/com/imooc/service/impl/SeckillServiceImpl.java
================================================
package com.imooc.service.impl;

import com.imooc.dao.SeckillDao;
import com.imooc.dao.SuccessKilledDao;
import com.imooc.dao.cache.RedisDao;
import com.imooc.dto.Exposer;
import com.imooc.dto.SeckillExecution;
import com.imooc.entity.Seckill;
import com.imooc.entity.SuccessKilled;
import com.imooc.enums.SeckillStateEnum;
import com.imooc.exception.RepeatKillException;
import com.imooc.exception.SeckillCloseException;
import com.imooc.exception.SeckillException;
import com.imooc.client.SeckillService;
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 java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

//@Componet @Service @Dao @Controller
@Service
public class SeckillServiceImpl implements SeckillService {

	private Logger logger = LoggerFactory.getLogger(this.getClass());

	// 注入Service依赖
	@Autowired
	private SeckillDao seckillDao;

	@Autowired
	private SuccessKilledDao successKilledDao;

	@Autowired
	private RedisDao redisDao;

	// md5盐值字符串,用于混淆MD5
	private final String slat = "sdfsgsfjks;sf,lasmglksmg";

	@Override
	public List<Seckill> getSeckillList() {
		return seckillDao.queryAll(0, 6);
	}

	@Override
	public Seckill getById(long seckillId) {
		return seckillDao.queryById(seckillId);
	}

	private String getMD5(long seckillId) {
		String base = seckillId + "/" + slat;
		String md5 = DigestUtils.md5DigestAsHex(base.getBytes());
		return md5;
	}

	@Override
	public Exposer exportSeckillUrl(long seckillId) {
		// 优化点:缓存优化:超时的基础上维护一致性
		// 1.访问redis
		Seckill seckill = redisDao.getSeckill(seckillId);
		if (seckill == null) {
			// 2.访问数据库
			seckill = seckillDao.queryById(seckillId);
			if (seckill == null) {
				return new Exposer(false, seckillId);
			} else {
				// 3.访问redis
				redisDao.putSeckill(seckill);
			}
		}
		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);
		return new Exposer(true, md5, seckillId);
	}

	@Override
	@Transactional
	/**
	 * 使用注解控制事务方法的优点: 1.开发团队达成一致约定,明确标注事务方法的编程风格
	 * 2.保证事务方法的执行时间尽可能短,不要穿插其他网络操作,RPC/HTTP请求或者剥离到事务方法外部
	 * 3.不是所有的方法都需要事务,如只有一条修改操作,只读操作不需要事务控制
	 */
	public SeckillExecution executeSeckill(long seckillId, long userPhone, String md5)
			throws SeckillException, RepeatKillException, SeckillCloseException {
		if (md5 == null || !md5.equals(getMD5(seckillId))) {
			throw new SeckillException("seckill data rewrite");
		}
		// 执行秒杀逻辑:减库存 + 记录购买行为
		Date now = new Date();
		try {
			// 记录购买行为
			int insertCount = successKilledDao.insertSuccessKilled(seckillId, userPhone);
			// 唯一:seckillId,userPhone
			if (insertCount <= 0) {
				// 重复秒杀
				throw new RepeatKillException("seckill repeated");
			} else {
				// 减库存,热点商品竞争
				int updateCount = seckillDao.reduceNumber(seckillId, now);
				if (updateCount <= 0) {
					// 没有更新到记录 rollback
					throw new SeckillCloseException("seckill is closed");
				} else {
					// 秒杀成功 commit
					SuccessKilled successKilled = successKilledDao.queryByIdWithSeckill(seckillId, userPhone);
					return new SeckillExecution(seckillId, SeckillStateEnum.SUCCESS, successKilled);
				}
			}
		} catch (SeckillCloseException e1) {
			throw e1;
		} catch (RepeatKillException e2) {
			throw e2;
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			// 所有编译期异常转换为运行期异常
			throw new SeckillException("seckill inner error:" + e.getMessage());
		}
	}

	@Override
	public SeckillExecution executeSeckillProcedure(long seckillId, long userPhone, String md5) {
		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);
		// 执行存储过程,result被赋值
		try {
			seckillDao.killByProcedure(map);
			// 获取result
			int result = MapUtils.getInteger(map, "result", -2);
			if (result == 1) {
				SuccessKilled sk = successKilledDao.queryByIdWithSeckill(seckillId, userPhone);
				return new SeckillExecution(seckillId, SeckillStateEnum.SUCCESS, sk);
			} else {
				return new SeckillExecution(seckillId, SeckillStateEnum.stateOf(result));
			}
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			return new SeckillExecution(seckillId, SeckillStateEnum.INNER_ERROR);
		}
	}

}


================================================
FILE: seckill-service-provider/src/main/resources/dubbo.proerpties
================================================
dubbo.application.name=seckill-service
dubbo.registry.address=zookeeper://127.0.0.1:2181
dubbo.registry.check=false
dubbo.protocol.name=dubbo

================================================
FILE: seckill-service-provider/src/main/resources/jdbc.properties
================================================
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/seckill?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8
jdbc.username=root
jdbc.password=root

#ʼӴС
jdbc.initialSize=0
#ӳ
jdbc.maxActive=20
#ӳС
jdbc.minIdle=1
#ȡȴʱ
jdbc.maxWait=60000

================================================
FILE: seckill-service-provider/src/main/resources/logback.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true">
	<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
		<!-- encoders are by default assigned the type ch.qos.logback.classic.encoder.PatternLayoutEncoder -->
		<encoder>
			<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
		</encoder>
	</appender>

	<root level="debug">
		<appender-ref ref="STDOUT" />
	</root>
</configuration>

================================================
FILE: seckill-service-provider/src/main/resources/mapper/SeckillDao.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.imooc.dao.SeckillDao">
	<!-- 目的:为dao接口方法提供sql语句配置 -->
	<update id="reduceNumber">
		<!-- 具体的sql -->
		UPDATE seckill
		SET number = number - 1
		WHERE
			seckill_id = #{seckillId}
		AND start_time <![CDATA[ <= ]]> #{killTime}
		AND end_time >= #{killTime}
		AND number > 0
	</update>
	
	<select id="queryById" resultType="Seckill" parameterType="long">
		SELECT
			seckill_id,
			NAME,
			number,
			start_time,
			end_time,
			create_time
		FROM
			seckill
		WHERE
			seckill_id = #{seckillId}
	</select>
	
	<select id="queryAll" resultType="Seckill">
		SELECT
			seckill_id,
			NAME,
			number,
			start_time,
			end_time,
			create_time
		FROM
			seckill
		ORDER BY
			create_time DESC
		LIMIT #{offset},
		#{limit}
	</select>
	
	<select id="killByProcedure" statementType="CALLABLE">
		call execute_seckill (
			#{seckillId, jdbcType = BIGINT, mode = IN },
			#{phone, jdbcType = BIGINT, mode = IN },
			#{killTime, jdbcType = TIMESTAMP, mode = IN },
			#{result, jdbcType = INTEGER, mode = OUT }
		)
	</select>
</mapper>

================================================
FILE: seckill-service-provider/src/main/resources/mapper/SuccessKilledDao.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.imooc.dao.SuccessKilledDao">
	<insert id="insertSuccessKilled">
		<!-- 主键冲突,报错 -->
		INSERT ignore INTO success_killed (seckill_id, user_phone, state)
		VALUES (#{seckillId}, #{userPhone}, 0)
	</insert>
	
	<select id="queryByIdWithSeckill" resultType="SuccessKilled">
		<!-- 如何告诉MyBatis把结果映射到SuccessKilled同时映射seckill属性 -->
		<!-- 可以自由控制SQL -->
		SELECT
			sk.seckill_id,
			sk.user_phone,
			sk.create_time,
			sk.state,
			s.seckill_id "seckill.seckill_id",
			s.`name` "seckill.name",
			s.number "seckill.number",
			s.start_time "seckill.start_time",
			s.end_time "seckill.end_time",
			s.create_time "seckill.create_time"
		FROM
			success_killed sk
		INNER JOIN seckill s ON sk.seckill_id = s.seckill_id
		WHERE
			sk.seckill_id = #{seckillId}
		AND sk.user_phone = #{userPhone}
	</select>
</mapper>

================================================
FILE: seckill-service-provider/src/main/resources/mybatis-config.xml
================================================
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<!-- 配置全局属性 -->
	<settings>
		<!-- 使用jdbc的getGeneratedKeys获取数据库自增主键值 -->
		<setting name="useGeneratedKeys" value="true" />

		<!-- 使用列别名替换列名 默认:true -->
		<setting name="useColumnLabel" value="true" />

		<!-- 开启驼峰命名转换:Table{create_time} -> Entity{createTime} -->
		<setting name="mapUnderscoreToCamelCase" value="true" />
	</settings>
</configuration>

================================================
FILE: seckill-service-provider/src/main/resources/spring/applicationContext.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <import resource="spring-*"/>
</beans>

================================================
FILE: seckill-service-provider/src/main/resources/spring/spring-dao.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.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context.xsd">
	<!-- 配置整合mybatis过程 -->
	<!-- 1.配置数据库相关参数properties的属性:${url} -->
	<context:property-placeholder location="classpath:jdbc.properties" />

	<!-- 2.数据库连接池 -->
	<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
		  init-method="init" destroy-method="clone">
		<!-- 基本属性driverClassName、 url、user、password -->
		<property name="driverClassName" value="${jdbc.driver}" />
		<property name="url" value="${jdbc.url}" />
		<property name="username" value="${jdbc.username}" />
		<property name="password" value="${jdbc.password}" />

		<!-- 配置初始化大小、最小、最大 -->
		<!-- 通常来说,只需要修改initialSize、minIdle、maxActive -->
		<!-- 初始化时建立物理连接的个数,缺省值为0 -->
		<property name="initialSize" value="${jdbc.initialSize}" />
		<!-- 最小连接池数量 -->
		<property name="minIdle" value="${jdbc.minIdle}" />
		<!-- 最大连接池数量,缺省值为8 -->
		<property name="maxActive" value="${jdbc.maxActive}" />

		<!-- 获取连接时最大等待时间,单位毫秒。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置useUnfairLock属性为true使用非公平锁。 -->
		<property name="maxWait" value="${jdbc.maxWait}" />
	</bean>
	<!--<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">-->
		<!--&lt;!&ndash; 配置连接池属性 &ndash;&gt;-->
		<!--<property name="driverClass" value="${jdbc.driver}" />-->
		<!--<property name="jdbcUrl" value="${jdbc.url}" />-->
		<!--<property name="user" value="${jdbc.username}" />-->
		<!--<property name="password" value="${jdbc.password}" />-->

		<!--&lt;!&ndash; c3p0连接池的私有属性 &ndash;&gt;-->
		<!--<property name="maxPoolSize" value="30" />-->
		<!--<property name="minPoolSize" value="10" />-->
		<!--&lt;!&ndash; 关闭连接后不自动commit &ndash;&gt;-->
		<!--<property name="autoCommitOnClose" value="false" />-->
		<!--&lt;!&ndash; 获取连接超时时间 &ndash;&gt;-->
		<!--<property name="checkoutTimeout" value="10000" />-->
		<!--&lt;!&ndash; 当获取连接失败重试次数 &ndash;&gt;-->
		<!--<property name="acquireRetryAttempts" value="2" />-->
	<!--</bean>-->

	<!-- 3.配置SqlSessionFactory对象 -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<!-- 注入数据库连接池 -->
		<property name="dataSource" ref="dataSource" />
		<!-- 配置MyBaties全局配置文件:mybatis-config.xml -->
		<property name="configLocation" value="classpath:mybatis-config.xml" />
		<!-- 扫描entity包 使用别名 -->
		<property name="typeAliasesPackage" value="com.imooc.entity" />
		<!-- 扫描sql配置文件:mapper需要的xml文件 -->
		<property name="mapperLocations" value="classpath:mapper/*.xml" />
	</bean>

	<!-- 4.配置扫描Dao接口包,动态实现Dao接口,注入到soring容器中 -->
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<!-- 注入sqlSessionFactory -->
		<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
		<!-- 给出需要扫描Dao接口包 -->
		<property name="basePackage" value="com.imooc.dao" />
	</bean>

	<!-- RedisDao -->
	<bean id="redisDao" class="com.imooc.dao.cache.RedisDao">
		<constructor-arg index="0" value="localhost" />
		<constructor-arg index="1" value="6379" />
	</bean>

</beans>

================================================
FILE: seckill-service-provider/src/main/resources/spring/spring-dubbo-config.xml
================================================
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://code.alibabatech.com/schema/dubbo
    http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

    <dubbo:application name="seckill-service" owner="seckill" organization="seckill-service" logger="slf4j"/>
    <dubbo:registry address="zookeeper://127.0.0.1:2181"/>
    <dubbo:protocol name="dubbo" port="20882" host="127.0.0.1"/>
    <dubbo:provider timeout="15000" retries="0" delay="-1"/>
    <dubbo:consumer check="false" timeout="15000"/>
</beans>

================================================
FILE: seckill-service-provider/src/main/resources/spring/spring-dubbo-provider.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:dubbo="http://code.alibabatech.com/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://code.alibabatech.com/schema/dubbo
    http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

    <dubbo:service interface="com.imooc.client.SeckillService" ref="seckillService"  timeout="10000"/>
    <!-- 和本地bean一样实现服务 -->
    <bean id="seckillService" class="com.imooc.service.impl.SeckillServiceImpl" />
</beans>

================================================
FILE: seckill-service-provider/src/main/resources/spring/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"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context.xsd
	http://www.springframework.org/schema/tx
	http://www.springframework.org/schema/tx/spring-tx.xsd">
	<!-- 扫描service包下所有使用注解的类型 -->
	<context:component-scan base-package="com.imooc.service" />

	<!-- 配置事务管理器 -->
	<bean id="transactionManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<!-- 注入数据库连接池 -->
		<property name="dataSource" ref="dataSource" />
	</bean>

	<!-- 配置基于注解的声明式事务 -->
	<tx:annotation-driven transaction-manager="transactionManager" />
</beans>

================================================
FILE: seckill-service-provider/src/main/resources/spring/spring-web.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"
	   xmlns:mvc="http://www.springframework.org/schema/mvc"
	   xmlns:aop="http://www.springframework.org/schema/aop"
	   xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context.xsd
	http://www.springframework.org/schema/mvc
	http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
	http://www.springframework.org/schema/aop
	http://www.springframework.org/schema/aop/spring-aop.xsd">

	<!-- 激活组件扫描功能,扫描aop的相关组件组件 -->
	<context:component-scan base-package="com.imooc.*"/>
	<!-- 启动对@AspectJ注解的支持 -->
	<aop:aspectj-autoproxy proxy-target-class="false" />

	<!-- 配置SpringMVC -->
	<!-- 1.开启SpringMVC注解模式 -->
	<!-- 简化配置: 
		(1)自动注册DefaultAnootationHandlerMapping,AnotationMethodHandlerAdapter 
		(2)提供一些列:数据绑定,数字和日期的format @NumberFormat, @DateTimeFormat, xml,json默认读写支持 
	-->
	<mvc:annotation-driven />
	
	<!-- 2.静态资源默认servlet配置
		(1)加入对静态资源的处理:js,gif,png
		(2)允许使用"/"做整体映射
	 -->
	 <mvc:default-servlet-handler/>
	 
	 <!-- 3.配置jsp 显示ViewResolver -->
	 <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	 	<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
	 	<property name="prefix" value="/WEB-INF/jsp/" />
	 	<property name="suffix" value=".jsp" />
	 </bean>

</beans>

================================================
FILE: seckill-service-provider/src/main/webapp/WEB-INF/web.xml
================================================
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
  version="3.1" metadata-complete="true">
  <!-- 配置DispatcherServlet -->
  <servlet>
    <servlet-name>seckill-dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!-- 配置springMVC需要加载的配置文件 -->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:spring/applicationContext.xml</param-value>
    </init-param>
  </servlet>

  <servlet-mapping>
    <servlet-name>seckill-dispatcher</servlet-name>
    <!-- 默认匹配所有的请求 -->
    <url-pattern>/</url-pattern>
  </servlet-mapping>

  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:spring/applicationContext.xml</param-value>
  </context-param>
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
</web-app>

================================================
FILE: seckill-service-provider/src/main/webapp/index.jsp
================================================
<html>
<body>
<h2>Hello World!</h2>
</body>
</html>
Download .txt
gitextract_vsg0jjnm/

├── .github/
│   └── workflows/
│       └── maven.yml
├── .gitignore
├── LICENSE
├── README.md
├── docs/
│   └── script/
│       └── initDB.sql
├── pom.xml
├── seckill-client/
│   ├── pom.xml
│   └── src/
│       └── main/
│           └── java/
│               └── com/
│                   └── imooc/
│                       └── client/
│                           └── SeckillService.java
├── seckill-core/
│   ├── .gitignore
│   ├── pom.xml
│   └── src/
│       └── main/
│           ├── java/
│           │   └── com/
│           │       └── imooc/
│           │           ├── aop/
│           │           │   └── LogAOP.java
│           │           └── web/
│           │               └── SeckillController.java
│           ├── resources/
│           │   ├── logback.xml
│           │   └── spring/
│           │       ├── applicationContext.xml
│           │       ├── spring-dubbo-config.xml
│           │       ├── spring-dubbo-consumer.xml
│           │       └── spring-web.xml
│           └── webapp/
│               ├── WEB-INF/
│               │   ├── jsp/
│               │   │   ├── common/
│               │   │   │   ├── head.jsp
│               │   │   │   └── tag.jsp
│               │   │   ├── detail.jsp
│               │   │   └── list.jsp
│               │   └── web.xml
│               └── resources/
│                   └── js/
│                       └── seckill.js
├── seckill-model/
│   ├── pom.xml
│   └── src/
│       └── main/
│           └── java/
│               └── com/
│                   └── imooc/
│                       ├── dto/
│                       │   ├── Exposer.java
│                       │   ├── SeckillExecution.java
│                       │   └── SeckillResult.java
│                       ├── entity/
│                       │   ├── Seckill.java
│                       │   └── SuccessKilled.java
│                       ├── enums/
│                       │   └── SeckillStateEnum.java
│                       └── exception/
│                           ├── RepeatKillException.java
│                           ├── SeckillCloseException.java
│                           └── SeckillException.java
└── seckill-service-provider/
    ├── pom.xml
    └── src/
        └── main/
            ├── java/
            │   └── com/
            │       └── imooc/
            │           ├── dao/
            │           │   ├── SeckillDao.java
            │           │   ├── SuccessKilledDao.java
            │           │   └── cache/
            │           │       └── RedisDao.java
            │           └── service/
            │               └── impl/
            │                   ├── App.java
            │                   └── SeckillServiceImpl.java
            ├── resources/
            │   ├── dubbo.proerpties
            │   ├── jdbc.properties
            │   ├── logback.xml
            │   ├── mapper/
            │   │   ├── SeckillDao.xml
            │   │   └── SuccessKilledDao.xml
            │   ├── mybatis-config.xml
            │   └── spring/
            │       ├── applicationContext.xml
            │       ├── spring-dao.xml
            │       ├── spring-dubbo-config.xml
            │       ├── spring-dubbo-provider.xml
            │       ├── spring-service.xml
            │       └── spring-web.xml
            └── webapp/
                ├── WEB-INF/
                │   └── web.xml
                └── index.jsp
Download .txt
SYMBOL INDEX (118 symbols across 18 files)

FILE: docs/script/initDB.sql
  type `seckill` (line 21) | CREATE TABLE `seckill` (
  type `success_killed` (line 48) | CREATE TABLE `success_killed` (
  type `v1` (line 66) | CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost`  VIEW `v1` AS SELE...

FILE: seckill-client/src/main/java/com/imooc/client/SeckillService.java
  type SeckillService (line 17) | public interface SeckillService {
    method getSeckillList (line 24) | List<Seckill> getSeckillList();
    method getById (line 32) | Seckill getById(long seckillId);
    method exportSeckillUrl (line 40) | Exposer exportSeckillUrl(long seckillId);
    method executeSeckill (line 53) | SeckillExecution executeSeckill(long seckillId, long userPhone, String...
    method executeSeckillProcedure (line 67) | SeckillExecution executeSeckillProcedure(long seckillId, long userPhon...

FILE: seckill-core/src/main/java/com/imooc/aop/LogAOP.java
  class LogAOP (line 18) | @Component
    method aopMethod (line 24) | @Pointcut("execution(* com.imooc.web.*.*(..))")
    method around (line 28) | @Around("aopMethod()")

FILE: seckill-core/src/main/java/com/imooc/web/SeckillController.java
  class SeckillController (line 21) | @Controller // @Service @Componet
    method list (line 31) | @RequestMapping(value = "/list", method = RequestMethod.GET)
    method detail (line 40) | @RequestMapping(value = "/{seckillId}/detail", method = RequestMethod....
    method exposer (line 54) | @RequestMapping(value = "/{seckillId}/exposer", method = RequestMethod...
    method execute (line 69) | @RequestMapping(value = "/{seckillId}/{md5}/execution", method = Reque...
    method time (line 95) | @RequestMapping(value = "/time/now", method = RequestMethod.GET)

FILE: seckill-model/src/main/java/com/imooc/dto/Exposer.java
  class Exposer (line 10) | public class Exposer implements Serializable {
    method Exposer (line 30) | public Exposer(boolean exposed, String md5, long seckillId) {
    method Exposer (line 36) | public Exposer(boolean exposed, long seckillId, long now, long start, ...
    method Exposer (line 44) | public Exposer(boolean exposed, long seckillId) {
    method isExposed (line 49) | public boolean isExposed() {
    method setExposed (line 53) | public void setExposed(boolean exposed) {
    method getMd5 (line 57) | public String getMd5() {
    method setMd5 (line 61) | public void setMd5(String md5) {
    method getSeckillId (line 65) | public long getSeckillId() {
    method setSeckillId (line 69) | public void setSeckillId(long seckillId) {
    method getNow (line 73) | public long getNow() {
    method setNow (line 77) | public void setNow(long now) {
    method getStart (line 81) | public long getStart() {
    method setStart (line 85) | public void setStart(long start) {
    method getEnd (line 89) | public long getEnd() {
    method setEnd (line 93) | public void setEnd(long end) {
    method toString (line 98) | @Override

FILE: seckill-model/src/main/java/com/imooc/dto/SeckillExecution.java
  class SeckillExecution (line 13) | public class SeckillExecution implements Serializable {
    method SeckillExecution (line 26) | public SeckillExecution(Long seckillId, SeckillStateEnum stateEnum, Su...
    method SeckillExecution (line 33) | public SeckillExecution(Long seckillId, SeckillStateEnum stateEnum) {
    method getSeckillId (line 41) | public Long getSeckillId() {
    method setSeckillId (line 45) | public void setSeckillId(Long seckillId) {
    method getState (line 49) | public Integer getState() {
    method setState (line 53) | public void setState(Integer state) {
    method getStateInfo (line 57) | public String getStateInfo() {
    method setStateInfo (line 61) | public void setStateInfo(String stateInfo) {
    method getSuccessKilled (line 65) | public SuccessKilled getSuccessKilled() {
    method setSuccessKilled (line 69) | public void setSuccessKilled(SuccessKilled successKilled) {
    method toString (line 73) | @Override

FILE: seckill-model/src/main/java/com/imooc/dto/SeckillResult.java
  class SeckillResult (line 4) | public class SeckillResult<T> {
    method SeckillResult (line 12) | public SeckillResult(boolean success, String error) {
    method SeckillResult (line 17) | public SeckillResult(boolean success, T data) {
    method isSuccess (line 22) | public boolean isSuccess() {
    method setSuccess (line 26) | public void setSuccess(boolean success) {
    method getData (line 30) | public T getData() {
    method setData (line 34) | public void setData(T data) {
    method getError (line 38) | public String getError() {
    method setError (line 42) | public void setError(String error) {
    method toString (line 46) | @Override

FILE: seckill-model/src/main/java/com/imooc/entity/Seckill.java
  class Seckill (line 11) | public class Seckill implements Serializable {
    method getSeckillId (line 24) | public long getSeckillId() {
    method setSeckillId (line 28) | public void setSeckillId(long seckillId) {
    method getName (line 32) | public String getName() {
    method setName (line 36) | public void setName(String name) {
    method getNumber (line 40) | public int getNumber() {
    method setNumber (line 44) | public void setNumber(int number) {
    method getStartTime (line 48) | public Date getStartTime() {
    method setStartTime (line 52) | public void setStartTime(Date startTime) {
    method getEndTime (line 56) | public Date getEndTime() {
    method setEndTime (line 60) | public void setEndTime(Date endTime) {
    method getCreateTime (line 64) | public Date getCreateTime() {
    method setCreateTime (line 68) | public void setCreateTime(Date createTime) {
    method toString (line 72) | @Override

FILE: seckill-model/src/main/java/com/imooc/entity/SuccessKilled.java
  class SuccessKilled (line 11) | public class SuccessKilled implements Serializable {
    method getSeckillId (line 24) | public long getSeckillId() {
    method setSeckillId (line 28) | public void setSeckillId(long seckillId) {
    method getUserPhone (line 32) | public long getUserPhone() {
    method setUserPhone (line 36) | public void setUserPhone(long userPhone) {
    method getState (line 40) | public short getState() {
    method setState (line 44) | public void setState(short state) {
    method getCreteTime (line 48) | public Date getCreteTime() {
    method setCreteTime (line 52) | public void setCreteTime(Date creteTime) {
    method getSeckill (line 56) | public Seckill getSeckill() {
    method setSeckill (line 60) | public void setSeckill(Seckill seckill) {
    method toString (line 64) | @Override

FILE: seckill-model/src/main/java/com/imooc/enums/SeckillStateEnum.java
  type SeckillStateEnum (line 8) | public enum SeckillStateEnum {
    method SeckillStateEnum (line 22) | private SeckillStateEnum(int state, String stateInfo) {
    method getState (line 27) | public Integer getState() {
    method getStateInfo (line 31) | public String getStateInfo() {
    method stateOf (line 35) | public static SeckillStateEnum stateOf(Integer index) {

FILE: seckill-model/src/main/java/com/imooc/exception/RepeatKillException.java
  class RepeatKillException (line 8) | public class RepeatKillException extends SeckillException {
    method RepeatKillException (line 9) | public RepeatKillException(String message) {
    method RepeatKillException (line 13) | public RepeatKillException(String message, Throwable cause) {

FILE: seckill-model/src/main/java/com/imooc/exception/SeckillCloseException.java
  class SeckillCloseException (line 8) | public class SeckillCloseException extends SeckillException {
    method SeckillCloseException (line 10) | public SeckillCloseException(String message) {
    method SeckillCloseException (line 14) | public SeckillCloseException(String message, Throwable cause) {

FILE: seckill-model/src/main/java/com/imooc/exception/SeckillException.java
  class SeckillException (line 8) | public class SeckillException extends RuntimeException {
    method SeckillException (line 10) | public SeckillException(String message) {
    method SeckillException (line 14) | public SeckillException(String message, Throwable cause) {

FILE: seckill-service-provider/src/main/java/com/imooc/dao/SeckillDao.java
  type SeckillDao (line 15) | public interface SeckillDao {
    method reduceNumber (line 24) | int reduceNumber(@Param("seckillId") long seckillId, @Param("killTime"...
    method queryById (line 32) | Seckill queryById(long seckillId);
    method queryAll (line 41) | List<Seckill> queryAll(@Param("offset") int offset, @Param("limit") in...
    method killByProcedure (line 48) | void killByProcedure(Map<String, Object> paramMap);

FILE: seckill-service-provider/src/main/java/com/imooc/dao/SuccessKilledDao.java
  type SuccessKilledDao (line 6) | public interface SuccessKilledDao {
    method insertSuccessKilled (line 15) | int insertSuccessKilled(@Param("seckillId") long seckillId, @Param("us...
    method queryByIdWithSeckill (line 24) | SuccessKilled queryByIdWithSeckill(@Param("seckillId") long seckillId,...

FILE: seckill-service-provider/src/main/java/com/imooc/dao/cache/RedisDao.java
  class RedisDao (line 12) | public class RedisDao {
    method RedisDao (line 20) | public RedisDao(String ip, int port) {
    method getSeckill (line 24) | public Seckill getSeckill(long seckillId) {
    method putSeckill (line 50) | public String putSeckill(Seckill seckill) {

FILE: seckill-service-provider/src/main/java/com/imooc/service/impl/App.java
  class App (line 10) | public class App {
    method main (line 11) | public static void main(String[] args) throws IOException {

FILE: seckill-service-provider/src/main/java/com/imooc/service/impl/SeckillServiceImpl.java
  class SeckillServiceImpl (line 29) | @Service
    method getSeckillList (line 47) | @Override
    method getById (line 52) | @Override
    method getMD5 (line 57) | private String getMD5(long seckillId) {
    method exportSeckillUrl (line 63) | @Override
    method executeSeckill (line 93) | @Override
    method executeSeckillProcedure (line 137) | @Override
Condensed preview — 53 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (85K chars).
[
  {
    "path": ".github/workflows/maven.yml",
    "chars": 1145,
    "preview": "# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow executi"
  },
  {
    "path": ".gitignore",
    "chars": 196,
    "preview": "*.class\n\n# Mobile Tools for Java (J2ME)\n.mtj.tmp/\n\n# Package Files #\n*.jar\n*.war\n*.ear\n*.idea\n\n# virtual machine crash l"
  },
  {
    "path": "LICENSE",
    "chars": 1067,
    "preview": "MIT License\n\nCopyright (c) 2020 justinbaby\n\nPermission is hereby granted, free of charge, to any person obtaining a copy"
  },
  {
    "path": "README.md",
    "chars": 1418,
    "preview": "# seckill(Java高并发秒杀API)\n一个spring入门项目,后续将更新spring中级项目 :)\n#### 所用技术点\n - spring\n - springMVC: MVC框架\n - Tomcat: web容器\n - myb"
  },
  {
    "path": "docs/script/initDB.sql",
    "chars": 4065,
    "preview": "/*\n\nSource Server         : root\nSource Server Version : 50538\nSource Host           : localhost:3306\nSource Database   "
  },
  {
    "path": "pom.xml",
    "chars": 5795,
    "preview": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:sc"
  },
  {
    "path": "seckill-client/pom.xml",
    "chars": 725,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www"
  },
  {
    "path": "seckill-client/src/main/java/com/imooc/client/SeckillService.java",
    "chars": 1549,
    "preview": "package com.imooc.client;\n\nimport com.imooc.dto.Exposer;\nimport com.imooc.dto.SeckillExecution;\nimport com.imooc.entity."
  },
  {
    "path": "seckill-core/.gitignore",
    "chars": 189,
    "preview": "*.class\n\n# Mobile Tools for Java (J2ME)\n.mtj.tmp/\n\n# Package Files #\n*.jar\n*.war\n*.ear\n\n# virtual machine crash logs, se"
  },
  {
    "path": "seckill-core/pom.xml",
    "chars": 2398,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www"
  },
  {
    "path": "seckill-core/src/main/java/com/imooc/aop/LogAOP.java",
    "chars": 1512,
    "preview": "package com.imooc.aop;\n\n\nimport org.aspectj.lang.ProceedingJoinPoint;\nimport org.aspectj.lang.annotation.Around;\nimport "
  },
  {
    "path": "seckill-core/src/main/java/com/imooc/web/SeckillController.java",
    "chars": 3660,
    "preview": "package com.imooc.web;\n\nimport com.imooc.dto.SeckillExecution;\nimport com.imooc.exception.SeckillCloseException;\nimport "
  },
  {
    "path": "seckill-core/src/main/resources/logback.xml",
    "chars": 440,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<configuration debug=\"true\">\n\t<appender name=\"STDOUT\" class=\"ch.qos.logback.core."
  },
  {
    "path": "seckill-core/src/main/resources/spring/applicationContext.xml",
    "chars": 335,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<beans xmlns=\"http://www.springframework.org/schema/beans\"\n       xmlns:xsi=\"http"
  },
  {
    "path": "seckill-core/src/main/resources/spring/spring-dubbo-config.xml",
    "chars": 794,
    "preview": "<beans xmlns=\"http://www.springframework.org/schema/beans\"\n       xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
  },
  {
    "path": "seckill-core/src/main/resources/spring/spring-dubbo-consumer.xml",
    "chars": 602,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<beans xmlns=\"http://www.springframework.org/schema/beans\"\n       xmlns:xsi=\"http"
  },
  {
    "path": "seckill-core/src/main/resources/spring/spring-web.xml",
    "chars": 1721,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<beans xmlns=\"http://www.springframework.org/schema/beans\"\n\t   xmlns:xsi=\"http://"
  },
  {
    "path": "seckill-core/src/main/webapp/WEB-INF/jsp/common/head.jsp",
    "chars": 934,
    "preview": "<%  \n    String path = request.getContextPath();  \n    String basePath = request.getScheme() + \"://\"  \n            + req"
  },
  {
    "path": "seckill-core/src/main/webapp/WEB-INF/jsp/common/tag.jsp",
    "chars": 130,
    "preview": "<%@ taglib prefix=\"c\" uri=\"http://java.sun.com/jsp/jstl/core\" %>\n<%@ taglib prefix=\"fmt\" uri=\"http://java.sun.com/jsp/js"
  },
  {
    "path": "seckill-core/src/main/webapp/WEB-INF/jsp/detail.jsp",
    "chars": 2276,
    "preview": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\"\n\tpageEncoding=\"UTF-8\"%>\n<!DOCTYPE html>\n<html lang=\"zh-C"
  },
  {
    "path": "seckill-core/src/main/webapp/WEB-INF/jsp/list.jsp",
    "chars": 1558,
    "preview": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\"\n\tpageEncoding=\"UTF-8\"%>\n<!-- 引入jstl -->\n<%@include file="
  },
  {
    "path": "seckill-core/src/main/webapp/WEB-INF/web.xml",
    "chars": 1182,
    "preview": "<web-app xmlns=\"http://xmlns.jcp.org/xml/ns/javaee\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLoc"
  },
  {
    "path": "seckill-core/src/main/webapp/resources/js/seckill.js",
    "chars": 4062,
    "preview": "// 存放主要交换逻辑js代码\n// javascript 模块化\nvar seckill = {\n\t// 封装秒杀相关ajax的url\n\tURL : {\n\t\tbasePath : function() {\n\t\t\treturn $('#ba"
  },
  {
    "path": "seckill-model/pom.xml",
    "chars": 504,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www"
  },
  {
    "path": "seckill-model/src/main/java/com/imooc/dto/Exposer.java",
    "chars": 1665,
    "preview": "package com.imooc.dto;\n\nimport java.io.Serializable;\n\n/**\n * 暴露秒杀接口DTO\n * \n * @author yan\n */\npublic class Exposer imple"
  },
  {
    "path": "seckill-model/src/main/java/com/imooc/dto/SeckillExecution.java",
    "chars": 1604,
    "preview": "package com.imooc.dto;\n\nimport com.imooc.entity.SuccessKilled;\nimport com.imooc.enums.SeckillStateEnum;\n\nimport java.io."
  },
  {
    "path": "seckill-model/src/main/java/com/imooc/dto/SeckillResult.java",
    "chars": 813,
    "preview": "package com.imooc.dto;\n\n//封装json结果\npublic class SeckillResult<T> {\n\n\tprivate boolean success;\n\n\tprivate T data;\n\n\tprivat"
  },
  {
    "path": "seckill-model/src/main/java/com/imooc/entity/Seckill.java",
    "chars": 1278,
    "preview": "package com.imooc.entity;\n\nimport java.io.Serializable;\nimport java.util.Date;\n\n/**\n * 秒杀库存实体\n * \n * @author yan\n */\npub"
  },
  {
    "path": "seckill-model/src/main/java/com/imooc/entity/SuccessKilled.java",
    "chars": 1128,
    "preview": "package com.imooc.entity;\n\nimport java.io.Serializable;\nimport java.util.Date;\n\n/**\n * 成功秒杀实体\n * \n * @author yan\n */\npub"
  },
  {
    "path": "seckill-model/src/main/java/com/imooc/enums/SeckillStateEnum.java",
    "chars": 795,
    "preview": "package com.imooc.enums;\n\n/**\n * 使用枚举表述常量数据字典\n *\n * @author yan\n */\npublic enum SeckillStateEnum {\n\n    SUCCESS(1, \"秒杀成功"
  },
  {
    "path": "seckill-model/src/main/java/com/imooc/exception/RepeatKillException.java",
    "chars": 296,
    "preview": "package com.imooc.exception;\n\n/**\n * 重复秒杀异常(运行期异常)\n * \n * @author yan\n */\npublic class RepeatKillException extends Secki"
  },
  {
    "path": "seckill-model/src/main/java/com/imooc/exception/SeckillCloseException.java",
    "chars": 296,
    "preview": "package com.imooc.exception;\n\n/**\n * 秒杀关闭异常\n * \n * @author yan\n */\npublic class SeckillCloseException extends SeckillExc"
  },
  {
    "path": "seckill-model/src/main/java/com/imooc/exception/SeckillException.java",
    "chars": 283,
    "preview": "package com.imooc.exception;\n\n/**\n * 秒杀相关业务异常\n * \n * @author yan\n */\npublic class SeckillException extends RuntimeExcept"
  },
  {
    "path": "seckill-service-provider/pom.xml",
    "chars": 2403,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www"
  },
  {
    "path": "seckill-service-provider/src/main/java/com/imooc/dao/SeckillDao.java",
    "chars": 797,
    "preview": "package com.imooc.dao;\n\nimport com.imooc.entity.Seckill;\nimport org.apache.ibatis.annotations.Param;\n\nimport java.util.D"
  },
  {
    "path": "seckill-service-provider/src/main/java/com/imooc/dao/SuccessKilledDao.java",
    "chars": 552,
    "preview": "package com.imooc.dao;\n\nimport com.imooc.entity.SuccessKilled;\nimport org.apache.ibatis.annotations.Param;\n\npublic inter"
  },
  {
    "path": "seckill-service-provider/src/main/java/com/imooc/dao/cache/RedisDao.java",
    "chars": 1841,
    "preview": "package com.imooc.dao.cache;\n\nimport com.dyuproject.protostuff.LinkedBuffer;\nimport com.dyuproject.protostuff.Protostuff"
  },
  {
    "path": "seckill-service-provider/src/main/java/com/imooc/service/impl/App.java",
    "chars": 774,
    "preview": "package com.imooc.service.impl;\n\nimport com.imooc.client.SeckillService;\nimport com.imooc.entity.Seckill;\nimport org.spr"
  },
  {
    "path": "seckill-service-provider/src/main/java/com/imooc/service/impl/SeckillServiceImpl.java",
    "chars": 4994,
    "preview": "package com.imooc.service.impl;\n\nimport com.imooc.dao.SeckillDao;\nimport com.imooc.dao.SuccessKilledDao;\nimport com.imoo"
  },
  {
    "path": "seckill-service-provider/src/main/resources/dubbo.proerpties",
    "chars": 141,
    "preview": "dubbo.application.name=seckill-service\ndubbo.registry.address=zookeeper://127.0.0.1:2181\ndubbo.registry.check=false\ndubb"
  },
  {
    "path": "seckill-service-provider/src/main/resources/jdbc.properties",
    "chars": 270,
    "preview": "jdbc.driver=com.mysql.cj.jdbc.Driver\njdbc.url=jdbc:mysql://127.0.0.1:3306/seckill?useUnicode=true&characterEncoding=utf8"
  },
  {
    "path": "seckill-service-provider/src/main/resources/logback.xml",
    "chars": 440,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<configuration debug=\"true\">\n\t<appender name=\"STDOUT\" class=\"ch.qos.logback.core."
  },
  {
    "path": "seckill-service-provider/src/main/resources/mapper/SeckillDao.xml",
    "chars": 1203,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE mapper\n    PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n    \"http://myba"
  },
  {
    "path": "seckill-service-provider/src/main/resources/mapper/SuccessKilledDao.xml",
    "chars": 984,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE mapper\n    PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n    \"http://myba"
  },
  {
    "path": "seckill-service-provider/src/main/resources/mybatis-config.xml",
    "chars": 529,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE configuration\n  PUBLIC \"-//mybatis.org//DTD Config 3.0//EN\"\n  \"http://"
  },
  {
    "path": "seckill-service-provider/src/main/resources/spring/applicationContext.xml",
    "chars": 335,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<beans xmlns=\"http://www.springframework.org/schema/beans\"\n       xmlns:xsi=\"http"
  },
  {
    "path": "seckill-service-provider/src/main/resources/spring/spring-dao.xml",
    "chars": 3350,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<beans xmlns=\"http://www.springframework.org/schema/beans\"\n\txmlns:xsi=\"http://www"
  },
  {
    "path": "seckill-service-provider/src/main/resources/spring/spring-dubbo-config.xml",
    "chars": 776,
    "preview": "<beans xmlns=\"http://www.springframework.org/schema/beans\"\n       xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
  },
  {
    "path": "seckill-service-provider/src/main/resources/spring/spring-dubbo-provider.xml",
    "chars": 681,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<beans xmlns=\"http://www.springframework.org/schema/beans\"\n       xmlns:xsi=\"http"
  },
  {
    "path": "seckill-service-provider/src/main/resources/spring/spring-service.xml",
    "chars": 1006,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<beans xmlns=\"http://www.springframework.org/schema/beans\"\n\txmlns:xsi=\"http://www"
  },
  {
    "path": "seckill-service-provider/src/main/resources/spring/spring-web.xml",
    "chars": 1633,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<beans xmlns=\"http://www.springframework.org/schema/beans\"\n\t   xmlns:xsi=\"http://"
  },
  {
    "path": "seckill-service-provider/src/main/webapp/WEB-INF/web.xml",
    "chars": 1105,
    "preview": "<web-app xmlns=\"http://xmlns.jcp.org/xml/ns/javaee\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n  xsi:schemaLo"
  },
  {
    "path": "seckill-service-provider/src/main/webapp/index.jsp",
    "chars": 52,
    "preview": "<html>\n<body>\n<h2>Hello World!</h2>\n</body>\n</html>\n"
  }
]

About this extraction

This page contains the full source code of the justinbaby/spring-mybatis GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 53 files (68.6 KB), approximately 22.4k tokens, and a symbol index with 118 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!