1. Project overview
1.1 SSM framework advantages
- The framework is easy to use and lightweight
- Low code intrusion
- Mature community and user base
1.2 introduction to relevant technologies
1.MySQL
- Table design
- SQL skills
- Transaction and row level locks
2.MyBatis
- Design and development of DAO layer
- MyBatis rational use
- MyBatis and Spring integration
3.Spring
- Spring IOC integration Service
- Declarative transaction application
4.SpringMVC
- Restful interface design and use
- Framework operation process
- Controller development skills
5. Front end
- Interaction design
- Bootstrap
- jQuery
6. High concurrency
- High concurrency point and high concurrency analysis
- Optimize ideas and implement
1.3 second kill business analysis
1.3. 1. Business process of second kill system
1.3. 2. The core of second kill business: inventory processing
1.3. 3 why transactions are needed
1.3. 4. Data landing
MySQL VS NoSQL
NoSQL: the transaction support is not very good, and the pursuit is performance, high availability and distributed
MySQL: the built-in transaction mechanism is still the most effective and reliable data landing scheme at present - > inventory reduction and purchase behavior can be recorded more reliably
1.4 difficulty analysis of MySQL second kill
Difficult problem: Competition - > transaction + row level lock
Transaction working mechanism:
- Start Transaction
- Update inventory quantity - > competition appears here
- Insert purchase details
- Commit
Row level lock - > with competition
How to deal with competition efficiently: high concurrency
1.5 what second kill functions can be realized
- Second kill interface exposure
- Execute second kill
- Related query: List query and detail page query
Code development phase
- DAO design coding: database table design, Dao interface, and how MyBatis implements Dao
- Service design code:
Service interface design and coding implementation, managing services through Spring, and labeling services through Spring declarative transactions. The method is a transaction operation to simplify transaction control - Web design coding: Restful interface, front-end interaction
2. Create projects and dependencies
2.1 description before creation
-
Create from scratch
-
Obtain relevant configurations from the official website
1. More comprehensive and authoritative documents
2. Avoid obsolescence or errors
-
Create a project using Maven
2.2 start creating project
- New Maven project
Maven installation and its configuration and use in IDEA (nanny tutorial)
- New Web project
Java learning [framework (III)] spring MVC (I) review MVC Architecture & Servlet
The results are as follows:
2.3 import dependency
<?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"> <modelVersion>4.0.0</modelVersion> <groupId>org.seckill</groupId> <artifactId>seckill</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <!-- use junit4(3.0 Programming mode is used by default, 4.0 Run in annotation mode later junit)--> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <!-- Complete project dependency --> <!-- 1:journal java journal: slf4j, log4j, logback, common-logging slf4j Is the norm/Interface Log implementation: log4j, logback, common-logging use: slf4j + logback --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.12</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>1.1.1</version> </dependency> <!-- realization slf4j Interface and integration --> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.1.1</version> </dependency> <!-- 2. Database dependency --> <!-- mysql drive--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.35</version> <scope>runtime</scope> </dependency> <!-- Database connection pool--> <dependency> <groupId>c3p0</groupId> <artifactId>c3p0</artifactId> <version>0.9.1.2</version> </dependency> <!-- 3. DAO Frame: MyBatis rely on --> <!-- MyBatis Self dependence --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.3.0</version> </dependency> <!-- MyBatis Self implemented Spring Integration dependence --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.2.3</version> </dependency> <!-- 3. Servlet web Correlation dependency --> <!-- jsp Corresponding label --> <dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>1.1.2</version> </dependency> <!-- js Default label Library --> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <!-- SpringMVC Default needs jackson --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.5.4</version> </dependency> <!-- servlet --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> </dependency> <!-- 4. Spring rely on--> <!-- 1)Spring Core dependency--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.1.7.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 Layer dependence --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>4.1.7.RELEASE</version> </dependency> <!-- Spring Transaction dependency --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>4.1.7.RELEASE</version> </dependency> <!-- 3) Spring web Correlation dependency--> <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 Related dependencies (for unit testing) --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>4.1.7.RELEASE</version> </dependency> </dependencies> </project>
3. Database design code
Java learning [framework (II)] MyBatis (I) the first MyBatis query program
- Create a new schema under main sql
(I connected to the database, but I didn't connect to MyBatis - > crazy MyBatis was configured in the resource. As of this step, I haven't configured it yet)
schema. The SQL statements in SQL are as follows:
-- Database initialization script -- Create database CREATE DATABASE `seckill`;
-- Use database use `seckill`;
-- Create a second kill inventory table CREATE TABLE `seckill`( `seckill_id` bigint NOT NULL AUTO_INCREMENT COMMENT 'Commodity inventory id', `name` varchar(120) NOT NULL COMMENT 'Trade name', `number` int NOT NULL COMMENT 'Inventory quantity', `start_time` datetime NOT NULL COMMENT 'Spike start time', `end_time` datetime NOT NULL COMMENT 'Spike end time', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Creation time', -- Design index -- idx by index abbreviation 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 = 1000 DEFAULT CHARSET = utf8 COMMENT 'Second kill inventory Watch';
-- Initialization data insert into `seckill`(`name`, `number`, `start_time`, `end_time`) values ('1000 Yuan second kill iphone6', 100, '2015-11-01 00:00:00', '2015-11-02 00:00:00'), ('500 Yuan second kill ipad2', 200, '2015-11-01 00:00:00', '2015-11-02 00:00:00'), ('300 Yuan spike millet 4', 300, '2015-11-01 00:00:00', '2015-11-02 00:00:00'), ('200 Yuan second kill red rice note', 400, '2015-11-01 00:00:00', '2015-11-02 00:00:00');
-- Second kill success details -- Information related to user login authentication create table `success_killed`( `seckill_id` bigint NOT NULL COMMENT 'Second kill commodity id', `user_phone` bigint NOT NULL COMMENT 'User mobile number', `state` tinyint NOT NULL DEFAULT -1 COMMENT 'Status identification: -1: Invalid 0: Success 1: Paid 2: Shipped', `create_time` datetime NOT NULL COMMENT 'Creation time', PRIMARY KEY (`seckill_id`, `user_phone`), -- composite keys key idx_create_time(create_time) )ENGINE = InnoDB DEFAULT CHARSET = utf8 COMMENT 'Second kill success details';
Modify database field properties:
ALTER TABLE `success_killed` MODIFY `create_time` datetime;
Show how tables are created:
show CREATE TABLE `success_killed`;
CREATE TABLE `success_killed` ( `seckill_id` bigint(20) NOT NULL COMMENT 'Second kill commodity id', `user_phone` bigint(20) NOT NULL COMMENT 'User mobile number', `state` tinyint(4) NOT NULL DEFAULT '-1' COMMENT 'Status identification: -1: Invalid 0: Success 1: Paid 2: Shipped', `create_time` datetime DEFAULT NULL, PRIMARY KEY (`seckill_id`,`user_phone`), KEY `idx_create_time` (`create_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Second kill success details'
The results are as follows:
4. DAO layer entity and interface coding
Correspondence between label and entity
- The table corresponds to the entity class in Java
- Column corresponds to the attribute in the entity
Create entity package & Dao layer package
org.seckill.entity
org.seckill.dao
4.1 writing entity classes
4.1.1 Seckill entity class
package org.seckill.entity; import java.util.Date; public class Seckill { private long seckillId; private String name; private int number; private Date startTime; private Date endTime; private Date createTime; // Alt + insert 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 + '}'; } }
4.1. 2 class successkilled
package org.seckill.entity; import java.util.Date; public class SuccessKilled { private long skillId; private long userPhone; private short state; private Date createTime; // Flexible // Many to one (composite attribute): one Seckill entity corresponds to multiple successful Seckill records private Seckill seckill; public long getSkillId() { return skillId; } public void setSkillId(long skillId) { this.skillId = skillId; } 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 getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } public Seckill getSeckill() { return seckill; } public void setSeckill(Seckill seckill) { this.seckill = seckill; } @Override public String toString() { return "SuccessKilled{" + "skillId=" + skillId + ", userPhone=" + userPhone + ", state=" + state + ", createTime=" + createTime + '}'; } }
4.2 design DAO interface
4.2.1 SeckillDao interface
Naming convention: corresponding entity + Dao - > e.g. SeckillDao
package org.seckill.dao; import org.seckill.entity.Seckill; import java.util.Date; import java.util.List; public interface SeckillDao { // Inventory reduction (killTime the time when inventory reduction is performed corresponds to the createtime in the database) // If the number of affected rows > 1, it indicates the number of updated record rows int reduceNumber(long seckillId, Date killTime); // Query requirements (query the second kill object according to id) Seckill queryById(long seckillId); // Query the second kill product list according to the offset // Offset: offset, limit: how many records are taken after the offset List<Seckill> queryAll(int offet, int limit); }
4.2. 2 successkilledao interface
package org.seckill.dao; import org.seckill.entity.SuccessKilled; public interface SuccessKilledDao { // Insert purchase details to filter duplicates (joint unique primary key) // Number of rows inserted int insertSuccessKilled(long seckillId, long userPhone); // Query SuccessKilled by id and carry the second kill product object entity SuccessKilled queryByIdWithSeckill(long seckillId); }