首先说一下本章的简单需求: 当SpringBoot项目启动的时候,从MySQL初始化数据到Redis中。
我们要实现的功能:
- 配置redis连接
- 配置MySQL和Druid连接
- 编写数据库代码
- 编写SpringBoot controller,service,dao,mapper以及初始化init方法
一、首先编写SpringBoot相关配置
配置文件application.properties,请注意mybatis.mapper的相关配置中mybatis.mapper-locations扫描的路径
#thymeleaf
spring.thymeleaf.cache=false
spring.thymeleaf.check-template=true
spring.thymeleaf.check-template-location=true
spring.thymeleaf.enabled=true
spring.thymeleaf.enable-spring-el-compiler=false
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.mode=HTML
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.servlet.content-type=text/html
spring.thymeleaf.suffix=.html
#redis
redis.host=192.168.3.104
redis.port=6379
redis.timeout=10
redis.password=553571
redis.poolMaxTotal=10
redis.poolMaxIdle=5
redis.poolMaxWait=5
#mybatis
mybatis.mapper-locations=classpath:mapping/*.xml
# druid
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/umbrelladatabase?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
二、编写SQL库测试Demo数据及相应mybatis mapper
CREATE TABLE `product` (
`productId` bigint(64) NOT NULL,
`originalPrice` double(10,2) DEFAULT NULL,
`productTitle` varchar(500) DEFAULT NULL,
`productName` varchar(500) DEFAULT NULL,
`productDescription` varchar(5000) DEFAULT NULL,
`stockCount` int(255) DEFAULT NULL,
`saleNum` int(255) DEFAULT NULL,
`productImg` varchar(500) DEFAULT NULL,
PRIMARY KEY (`productId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
测试Demo数据
INSERT INTO `umbrelladatabase`.`product`(`productId`, `originalPrice`, `productTitle`, `productName`, `productDescription`, `stockCount`, `saleNum`, `productImg`) VALUES (0, 12.00, 'qwe', 'qwe', 'qwe', 1, 12, NULL);
INSERT INTO `umbrelladatabase`.`product`(`productId`, `originalPrice`, `productTitle`, `productName`, `productDescription`, `stockCount`, `saleNum`, `productImg`) VALUES (1, 13.00, 'ewrezdszf', 'sa', 'asdf', 2, 2, NULL);
INSERT INTO `umbrelladatabase`.`product`(`productId`, `originalPrice`, `productTitle`, `productName`, `productDescription`, `stockCount`, `saleNum`, `productImg`) VALUES (2, 24.00, 'fsdz', 'sdf', 'sf', 4, 234, NULL);
INSERT INTO `umbrelladatabase`.`product`(`productId`, `originalPrice`, `productTitle`, `productName`, `productDescription`, `stockCount`, `saleNum`, `productImg`) VALUES (3, 345.00, 'sdfsdszd', 'adf', 'fasdsdf', 344, 423, NULL);
INSERT INTO `umbrelladatabase`.`product`(`productId`, `originalPrice`, `productTitle`, `productName`, `productDescription`, `stockCount`, `saleNum`, `productImg`) VALUES (4, 456.00, 's', 'sad', 'f', 34, 423, NULL);
INSERT INTO `umbrelladatabase`.`product`(`productId`, `originalPrice`, `productTitle`, `productName`, `productDescription`, `stockCount`, `saleNum`, `productImg`) VALUES (5, 576.00, 'zfdxf', 'f', 'sdf', 43, 23, NULL);
INSERT INTO `umbrelladatabase`.`product`(`productId`, `originalPrice`, `productTitle`, `productName`, `productDescription`, `stockCount`, `saleNum`, `productImg`) VALUES (6, 78.00, 'sdf', 'saf', 'sdf', 4234, NULL, NULL);
INSERT INTO `umbrelladatabase`.`product`(`productId`, `originalPrice`, `productTitle`, `productName`, `productDescription`, `stockCount`, `saleNum`, `productImg`) VALUES (7, 456.00, 'df', 'f', 'sad', 3, 234234, NULL);
INSERT INTO `umbrelladatabase`.`product`(`productId`, `originalPrice`, `productTitle`, `productName`, `productDescription`, `stockCount`, `saleNum`, `productImg`) VALUES (8, 4.00, 'zfdsadf', 'asdadf', 'asdf', 423, 4234, NULL);
INSERT INTO `umbrelladatabase`.`product`(`productId`, `originalPrice`, `productTitle`, `productName`, `productDescription`, `stockCount`, `saleNum`, `productImg`) VALUES (9, 423123.00, 'sadf', 'sdaf', 'sda', 34543, 234, NULL);
mybatis 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.umbrella.armsmerchant.product_manage.dao.ProductManageDao" >
<resultMap id="DefaultProductVOtMap" type="com.umbrella.armsmerchant.product_manage.model.DefaultProductVO" >
<id column="productId" property="productId" jdbcType="BIGINT" />
<result column="originalPrice" property="originalPrice" jdbcType="DOUBLE" />
<result column="productTitle" property="productTitle" jdbcType="VARCHAR" />
<result column="productImg" property="productImg" jdbcType="VARCHAR" />
<result column="stockCount" property="stockCount" jdbcType="INTEGER" />
</resultMap>
<resultMap id="DefaultProductDetailVOMap" type="com.umbrella.armsmerchant.product_manage.model.DefaultProductDetailVO" >
<id column="productId" property="productId" jdbcType="BIGINT" />
<result column="originalPrice" property="originalPrice" jdbcType="DOUBLE" />
<result column="productTitle" property="productTitle" jdbcType="VARCHAR" />
<result column="productImg" property="productImg" jdbcType="VARCHAR" />
<result column="productName" property="productName" jdbcType="VARCHAR" />
<result column="productDescription" property="productDescription" jdbcType="VARCHAR" />
<result column="saleNum" property="saleNum" jdbcType="VARCHAR" />
<result column="stockCount" property="stockCount" jdbcType="INTEGER" />
</resultMap>
<sql id="DefaultProduct" >
productId, originalPrice, productTitle, stockCount, productImg
</sql>
<sql id="DefaultProductDetail" >
productId, originalPrice, productTitle, productName, productDescription, stockCount, saleNum, productImg
</sql>
<select id="queryDefaultProducts" resultMap="DefaultProductDetailVOMap">
select
<include refid="DefaultProduct" />
from product
</select>
<select id="queryDefaultProductDetails" resultMap="DefaultProductDetailVOMap">
select
<include refid="DefaultProductDetail" />
from product
</select>
</mapper>
三、编写相关Controller、Service、Dao
相关product_manage目录 | 相关通用工具类目录 |
四、关键方法细节展示
4.1 匹配redis连接配置的bean
@PropertySource("application.properties") 即获取配置文件的名称
@ConfigurationProperties("redis") 即配置的前缀
package com.umbrella.armsmerchant.common.redis_manage;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.annotation.PropertySources;
import org.springframework.stereotype.Component;
@Component
@PropertySource("application.properties")
@ConfigurationProperties("redis")
public class RedisConfig {
// 以下成员变量请与配置文件中redis.开头的配置信息保持一致
private String host;
private int port;
private int timeout;//秒
private String password;
private int poolMaxTotal;
private int poolMaxIdle;
private int poolMaxWait;//秒
public String getHost() {return host;}
public void setHost(String host) {this.host = host;}
public int getPort() {return port;}
public void setPort(int port) {this.port = port;}
public int getTimeout() {return timeout;}
public void setTimeout(int timeout) {this.timeout = timeout;}
public String getPassword() {return password;}
public void setPassword(String password) {this.password = password;}
public int getPoolMaxTotal() {return poolMaxTotal;}
public void setPoolMaxTotal(int poolMaxTotal) {this.poolMaxTotal = poolMaxTotal;}
public int getPoolMaxIdle() {return poolMaxIdle;}
public void setPoolMaxIdle(int poolMaxIdle) {this.poolMaxIdle = poolMaxIdle;}
public int getPoolMaxWait() {return poolMaxWait;}
public void setPoolMaxWait(int poolMaxWait) {this.poolMaxWait = poolMaxWait;}
}
4.2 redis连接池相关代码
@Service
public class RedisPoolFactory {
@Autowired
RedisConfig redisConfig;
@Bean
public JedisPool JedisPoolFactory() {
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxIdle(redisConfig.getPoolMaxIdle());
poolConfig.setMaxTotal(redisConfig.getPoolMaxTotal());
poolConfig.setMaxWaitMillis(redisConfig.getPoolMaxWait() * 1000);
JedisPool jp = new JedisPool(poolConfig, redisConfig.getHost(), redisConfig.getPort(),
redisConfig.getTimeout()*1000, redisConfig.getPassword(), 0);
return jp;
}
}
4.3 redis通用接口
前期先实现主要的增删查基础功能接口
package com.umbrella.armsmerchant.common.redis_manage;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSON;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.ScanParams;
import redis.clients.jedis.ScanResult;
@Service
public class RedisService {
@Autowired
JedisPool jedisPool;
//获取数据
public <T> T get(String key) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
T t = (T) jedis.get(key);
return t;
}finally {
if(jedis != null) {
jedis.close();
}
}
}
//保存数据
public <T> boolean set(String key, T value) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
if(key == null || key.length() <= 0) {
return false;
}
jedis.set(key, value.toString());
return true;
}finally {
if(jedis != null) {
jedis.close();
}
}
}
//删除数据
public boolean delete(String key) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
long ret = jedis.del(key);
return ret > 0;
} finally {
if (jedis != null) {
jedis.close();
}
}
}
}
4.4 redis key生成工具
由于我们后期将会有多种类型的数据都要存放于redis中,所以为了避免key重复和具有一定的业务性,每个key我们统一加一个前缀,下面代码就是简单实现这种功能。
首先定义前缀常量:
package com.umbrella.armsmerchant.common.common_constant;
public class KeyCodeConstant {
public static final String DEFAULT_PRODUCT_KEY_PREFIX_CODE = "PROD_";
public static final String DEFAULT_PRODUCT_DETAIL_KEY_PREFIX_CODE = "PROD_D_";
public static final String USER_KEY_PREFIX_CODE = "USER_";
}
产品类是PROD_开头,产品详情是PROD_D_开头。
其次我们定义生成key的工具类:
package com.umbrella.armsmerchant.common.common_util;
import com.umbrella.armsmerchant.common.common_constant.KeyCodeConstant;
import com.umbrella.armsmerchant.product_manage.model.DefaultProductDetailVO;
import com.umbrella.armsmerchant.product_manage.model.DefaultProductVO;
import com.umbrella.armsmerchant.user_manage.model.UserVO;
/**
* @program: com.umbrella.armsmerchant.common.common_util
* @description:
* @author: liujinghui
* @create: 2018-11-24 11:12
**/
public class RedisKeyGen {
public static String KeyGen(Class clazz,String key){
if(null == key || "".equals(key)){
return "";
}
if(clazz == DefaultProductVO.class){
return KeyCodeConstant.DEFAULT_PRODUCT_KEY_PREFIX_CODE+key;
}else if(clazz == DefaultProductDetailVO.class){
return KeyCodeConstant.DEFAULT_PRODUCT_DETAIL_KEY_PREFIX_CODE+key;
}else if(clazz == UserVO.class){
return KeyCodeConstant.USER_KEY_PREFIX_CODE+key;
}else{
return key;
}
}
}
可以看出我们按照传入的类型来生成特定的key,至于mysql关于商品id的生成方式我采用的是snowflake工具。具体自己随意。
4.5 SpringBoot与MyBatis和Redis的集成
ProductManageDao :
package com.umbrella.armsmerchant.product_manage.dao;
import com.umbrella.armsmerchant.product_manage.model.DefaultProductDetailVO;
import com.umbrella.armsmerchant.product_manage.model.DefaultProductVO;
import com.umbrella.armsmerchant.product_manage.model.FastSaleProductVO;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface ProductManageDao {
List<DefaultProductVO> queryDefaultProducts();
List<DefaultProductDetailVO> queryDefaultProductDetails();
}
ProductManageServiceImpl :
@Service("ProductManageService")
@Transactional
public class ProductManageServiceImpl implements IProductManageService {
@Autowired
ProductManageDao productManageDao;
@Autowired
RedisService redisService;
@Override
public void initProductsToRedis() {
List<DefaultProductDetailVO> defaultProductDetailVOlist = productManageDao.queryDefaultProductDetails();
for (DefaultProductDetailVO defaultProductDetailVO : defaultProductDetailVOlist){
redisService.set(RedisKeyGen.KeyGen(DefaultProductDetailVO.class,defaultProductDetailVO.getProductId()+""), defaultProductDetailVO.toString());
}
for(int i=0;i<10;i++){
System.out.println((String)redisService.get("PROD_D_"+i));
}
}
}
4.6 SpringBoot初始化方法的编写:
所谓初始化方法其实就是SpringBoot加载完资源后,自动调用执行的方法, 只需要实现InitializingBean的afterPropertiesSet方法即可。具体Controller类不过多阐述,不是重点。
package com.umbrella.armsmerchant.init_main;
import com.umbrella.armsmerchant.product_manage.service.IProductManageService;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
/**
* @program: com.umbrella.armsmerchant.main
* @description:
* @author: liujinghui
* @create: 2018-11-24 12:13
**/
@Component
public class InitServlet implements InitializingBean {
@Autowired
@Qualifier("ProductManageService")
IProductManageService iProductManageService;
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("***************");
iProductManageService.initProductsToRedis();
}
}
5、测试启动我们的项目
可以看到下图中,******为初始化方法的开始。