Spring Boot 整合 Redis 实现电商秒杀项目
项目总览
一、 技术介绍
后端:springboot、 Mybatis
中间件:Redis、 druid
SpringBoot
1、 什么是SpringBoot
springBoot的设计模式简单的可以理解为 就是为了写最少的配置文件,跑最快的Spring应用程序。
2、SpringBoot四个主要特性
- SpringBoot
Starter:
依赖整合,就在一个文件中配置所有依赖 - 自动配置:合理的推测应用所需要的bean并自动化配置。
- 命令行接口:(Command-line-interface,
CLI):SpringBoot的CLI进一步的简化开发。 - Actuatir:它为SpringBoot应用的所有特性构建一个小型的应用程序。但首先,我们快速了解每项特性,更好的体验他们如何简化Spring编程模型。
mybatis
-
ORM【对象关系映射】
O:Object R:Relationship M:Mapping
作用:就是将Java的面向对象的数据【实体】转换成MySQL的面向关系的数据【表】
-
原生态jdbc程序的问题及总结
数据库连接,使用时就创建,不使用立即释放,对数据库进行频繁连接开启和关闭,造成数据库资源浪费,影响数据库性能。 解决办法:使用数据库连接池管理数据库连接。 将sql语句硬编码到java代码中,如果sql 语句修改,需要重新编译java代码,不利于系统维护。 期望:就如同我们jdbc的url、user和password等信息单独的配置在一个配置文件中一样,期望可以将sql语句配置在配置文件中,即使sql变化,不需要对java代码进行重新编译。 向preparedStatement中设置参数,对占位符号位置和设置参数值,硬编码在java代码中,不利于系统维护。 期望:将sql语句及占位符号和参数全部配置在配置文件中。 从resutSet中遍历结果集数据时,存在硬编码,将获取表的字段进行硬编码,如果表的字段修改了则代码也需要修改,不利于系统维护。 期望:将查询的结果集,自动映射成java对象。
-
如何解决
使用MyBatis。 mybatis让开发者将主要精力放在sql上,通过mybatis提供的映射方式可以很灵活的写出满足需要sql语句. mybatis可以将向preparedStatement中的输入参数自动进行输入映射,将查询结果集灵活映射成java对象。
-
总结
MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。 MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。 MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的实体映射成数据库中的记录。
Redis
-
Redis 简介
是一个高性能的key-value数据库。
-
Redis 优势
性能极高 丰富的数据类型 原子 – Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。
Druid
-
Druid的简介
Druid首先是一个数据库连接池。Druid是目前最好的数据库连接池
-
Druid功能
充当数据库连接池。 可以监控数据库访问性能 获得SQL执行日志
二、项目目录
三、依赖展示
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.8.RELEASE</version>
</parent>
<groupId>com.example</groupId>
<artifactId>test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>test</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.5</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.38</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.6</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<!--<plugin>-->
<!--<artifactId>maven-project-info-reports-plugin</artifactId>-->
<!--<version>3.0.0</version>-->
<!--</plugin>-->
</plugins>
</pluginManagement>
</build>
</project>
四、 具体实现
配置文件的编写
1. jdbc.properties
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/miaosha?characterEncoding=utf-8&serverTimezone=UTC&useSSL=false
jdbc.username=root
jdbc.password=123456
idleConnectionTestPeriod=60
maxIdleTime=240
acquireIncrement=5
initialPoolSize=10
maxPoolSize=30
minPoolSize=10
autoCommitOnClose=false
checkoutTimeout=1000
acquireRetryAttempts=2
2. application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/miaosha?characterEncoding=utf-8&serverTimezone=UTC&useSSL=false
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.filters=stat
spring.datasource.maxActive=2
spring.datasource.initialSize=1
spring.datasource.maxWait=60000
spring.datasource.minIdle=1
spring.datasource.timeBetweenEvictionRunsMillis=60000
spring.datasource.minEvictableIdleTimeMillis=30000
spring.datasource.validationQuery=select 'x'
spring.datasource.testWhileIdle=true
spring.datasource.testOnBorrow=false
spring.datasource.testOnReturn=false
spring.datasource.poolPreparedStatements=true
spring.datasource.maxPoolPreparedStatementPerConnectionSize=20
spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
spring.datasource.useGlobalDataSourceStat=true
#redis
redis.host=127.0.0.1
redis.port=6379
redis.timeout=3
redis.password=123456
redis.poolMaxTotal=10
redis.poolMaxIdle=10
redis.poolMaxWait=3
spring.http.encoding.charset=UTF-8
#thymeleaf
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
spring.thymeleaf.cache=false
spring.thymeleaf.content-type=text/html
spring.thymeleaf.enabled=true
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.mode=HTML5
mybatis.mapper-locations=classpath:mapper/*.xml
3. generatorConfig.xml
这个xml文件配置好之后,添加合适依赖,既可以自动按照数据库设计格式自动生成entity、mapper、dao层。
依赖展示:
xml文件展示:
Controller层展示:
package com.example.test.controller;
import com.example.test.dao.UserMapper;
import com.example.test.entity.User;
import com.example.test.redis.RedisService;
import com.example.test.redis.UserKey;
import com.example.test.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import redis.clients.jedis.Jedis;
/**
* @author Admin
* @date 2020/5/11
*/
@RestController
@RequestMapping("/demo")
public class UserController {
@Autowired
UserMapper userMapper;
@Autowired
UserService userService;
@Autowired
RedisService redisService;
@RequestMapping("/db/get")
public User getById(){
User user = userMapper.getById(1);
return user;
}
// 事物测试
@RequestMapping("/db/tx")
@ResponseBody
public boolean dbTx(){
return userService.tx();
}
//
// //redis 测试
// @RequestMapping("/redis/get1")
// @ResponseBody
// public String redisGet1(){
// //视频的要求,但是不能实现
// String v1 = redisService.get("key1",String.class);
// return v1;
// }
//redis 测试
@RequestMapping("/redis/get")
@ResponseBody
public String redisGet(){
//自己找的方法
Jedis jedis = new Jedis("localhost");
jedis.auth("123456");
String v2 = jedis.get("key1");
return v2;
}
@RequestMapping("/redis/set")
@ResponseBody
public String redisSet(){
//视频的要求,但是不能实现
// Long v1 = redisService.get("key1",Long.class);
//自己找的方法
Jedis jedis = new Jedis("localhost");
jedis.auth("123456");
String ret = jedis.set("age", "25");
ret = jedis.get("age");
return ret;
}
//前缀
@RequestMapping("/redis/preGet")
@ResponseBody
public User redisPreGet(){
User user = redisService.get(UserKey.getById,"" + 1,User.class);
return user;
}
//前缀
@RequestMapping("/redis/preSet")
@ResponseBody
public Boolean redisPreSet(){
User user = new User();
user.setId(1);
user.setName("1111111111");
Boolean bool = redisService.set(UserKey.getById,"" + 1,user);//UserKey:id1
return bool;
}
//
// @RequestMapping("/redis/set1")
// @ResponseBody
// public String redisSet1(){
//
// //避免出现迭代,用前缀
// boolean ret = redisService.set("key45", "hellotest");
// String str = redisService.get("key45",String.class);
// return str;
// }
//
}
Service层展示:
Service展示:
package com.example.test.service;
import com.example.test.entity.User;
/**
* @author Admin
* @date 2020/5/11
*/
public interface UserService {
public User getById(int id);
boolean tx();
}
ServiceImpl展示:
package com.example.test.service.impl;
import com.example.test.dao.UserMapper;
import com.example.test.entity.User;
import com.example.test.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @author Admin
* @date 2020/5/11
*/
@Service("userService")
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public User getById(int id) {
return userMapper.getById(id);
}
@Override
// @Transactional
// @Transactional 不设置事物的时候,数据二是可以被插进去的
public boolean tx() {
User u1 = new User();
u1.setId(2);
u1.setName("利尔");
userMapper.insert(u1);
User u2 = new User();
u2.setId(1);
u2.setName("1111");
userMapper.insert(u2);
return true;
}
}
Dao层展示:
package com.example.test.dao;
import com.example.test.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
//这个注解可不能忘啊
@Mapper
public interface UserMapper {
User getById(int id);
int insert(User user);
}
Mapper层展示
<?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.example.test.dao.UserMapper">
<resultMap id="BaseResultMap" type="com.example.test.entity.User">
<id column="id" jdbcType="INTEGER" property="id" />
<result column="username" jdbcType="VARCHAR" property="name" />
</resultMap>
<sql id="Base_Column_List">
id, name
</sql>
<insert id="insert">
INSERT into user(id,name)VALUES (#{id},#{name})
</insert>
<select id="getById" resultType="com.example.test.entity.User">
SELECT
*
FROM USER
WHERE id = #{id}
</select>
</mapper>
Entity展示:
package com.example.test.entity;
import java.util.Date;
public class User {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}