模拟某个热点数据,优先从redis中查找,若找不到,则从mysql中查找,并缓存到redis中。
有些业务需求需要读取的速度快,所以常常把这些热点的数据优先从Redie中进行读取,因为Redis是将数据存储在内存,所以速度比MySQL等关系型数据库的读取速度快很多。
步骤如下:<br/>
**1. 导入依赖的JAR包**
| JAR包 |
| --- |
| **c3p0-0.9.5.2.jar:** 用于连接MySQL数据库 <br/>**commons-dbutils-1.6.jar:** 用于操作MySQL数据库<br/>**commons-pool2-2.6.2.jar**:Redis的连接池<br/>**fastjson-1.2.52.jar**:JSON转换工具<br/>**jedis-3.1.0.jar**:Redis的驱动包<br/>**mchange-commons-java.0.2.11.jar**:配合commons-dbutils-1.6.jar操作数据库<br/>**mysql-connector-java-5.1.48.jar**:MySQL驱动包<br/>**slf4j-api-1.7.25.jar**:与commons-pool2-2.6.2.jar配合使用 |
**2. MySQL和Redis的配置文件**
**`resources/c3p0-config.xml`**(该名字不能更改)
```xml
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<named-config name="class2"><!-- 代码读取的逻辑名,可以随便取 -->
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl"> jdbc:mysql://localhost:3306/class2?useUnicode=true&characterEncoding=utf-8&</property>
<property name="user">root</property>
<property name="password">admin</property>
<property name="maxPoolSize">20</property>
<property name="minPoolSize">3</property>
<property name="maxStatements">30</property>
<property name="maxIdleTime">150</property>
</named-config>
</c3p0-config>
```
**`resources/jedis.properties`**
```
host=localhost
port=6379
maxTotal=50
maxIdle=10
#...当然还有很多的配置,这里就不配置了
```
**3. 封装实体类**
**`pojo/Province.java`**
```java
package pojo;
/**
* 对应数据库的province表
*/
public class Province {
private Integer province_id; // 城市id
private String province_code; // 城市代码
private String province_name; // 城市名称
private String short_name; // 城市简称
....请提供上面属性的Getter和Setter方法,这里省略...
```
**4. 封装dao层的接口和实现类**
**`dao/ProvinceDao.java`**
```java
package dao;
import pojo.Province;
import java.util.List;
public interface ProvinceDao {
/**
* 查询所有的城市
* @return List<Province>
*/
List<Province> queryProvinceList();
}
```
**`dao/ProvinceDaoImpl.java`**
```java
package dao.impl;
import common.MySQLUtils;
import dao.ProvinceDao;
import pojo.Province;
import java.util.List;
public class ProvinceDaoImpl implements ProvinceDao {
@Override
public List<Province> queryProvinceList() {
String sql = "select * from province";
return MySQLUtils.queryBeanList(sql, Province.class);
}
}
```
**5. 封装service层的接口及实现类**
**`service/ProvinceService.java`**
```java
package service;
import pojo.Province;
import java.util.List;
public interface ProvinceService {
/**
* 查询所有的城市
* @return List<Province>
*/
List<Province> queryProvinceList();
}
```
**`service/ProvinceServiceImpl.java`**
```java
package service.impl;
import com.alibaba.fastjson.JSON;
import common.JedisPoolUtils;
import dao.ProvinceDao;
import dao.impl.ProvinceDaoImpl;
import pojo.Province;
import redis.clients.jedis.Jedis;
import service.ProvinceService;
import java.util.List;
public class ProvinceServiceImpl implements ProvinceService {
private ProvinceDao provinceDao = new ProvinceDaoImpl();
/**
* 先从Redis中读取provinces数据,如果没有再从MySQL中读取,然后将从MySQL中读取的数据
* 缓存到Redis中,当第二次访问时Redis中已有数据,直接从Redis中读取数据
* @return List
*/
@Override
public List<Province> queryProvinceList() {
Jedis jedis = JedisPoolUtils.getJedis();
System.out.println("---尝试从Redis中读取province---");
// 从Redis中读取数据
String provinces = jedis.get("provinces");
if (provinces == null) { // Redis中没有数据
System.out.println("---Redis中没有province数据---");
// 从MySQL中读取数据
List<Province> provinceList = provinceDao.queryProvinceList();
if (provinceList.size() < 1) { // MySQL没有数据
System.out.println("---MySQL中没有province数据---");
return provinceDao.queryProvinceList();
}
System.out.println("---从MySQL中读取到province,准备存入到Redis中作为缓存");
provinces = JSON.toJSONString(provinceList); // 将List数据类型转换为String类型
jedis.set("provinces", provinces); // 将从MySQl中读取的数据缓存到Redis中
return provinceDao.queryProvinceList();
} else { // Redis中有数据
System.out.println("---从Redis中读取数据成功---");
return provinceDao.queryProvinceList();
}
}
}
```
**6. 在测试类中进行测试**
**`test/Test.java`**
```java
package test;
import pojo.Province;
import service.ProvinceService;
import service.impl.ProvinceServiceImpl;
import java.util.List;
public class Test {
private ProvinceService provinceService = new ProvinceServiceImpl();
@org.junit.Test
public void test() throws InterruptedException {
List<Province> provinceList = provinceService.queryProvinceList();
System.out.println("-----测试结果----");
for(Province province : provinceList) {
System.out.println(province.getProvince_id()+"\t" + province.getProvince_code() + "\t"
+ "\t" + province.getProvince_name() + "\t" + province.getShort_name());
}
}
}
```
第一次运行的结果:
```
---尝试从Redis中读取province---
---Redis中没有province数据---
---从MySQL中读取到province,准备存入到Redis中作为缓存---
-----测试结果----
1 110000 北京 北京
2 120000 天津 天津
3 130000 河北省 河北
4 140000 山西省 山西
```
第二次运行的结果:第二次运行Redis中已有数据
```
---尝试从Redis中读取province---
---从Redis中读取数据成功---
-----测试结果----
1 110000 北京 北京
2 120000 天津 天津
3 130000 河北省 河北
4 140000 山西省 山西
```
- 网络通信
- 网络协议
- 端口和套接字
- TCP网络程序
- UDP网络程序
- 多线程聊天室
- 多线程
- 线程相关概念
- 线程实现方式
- 中断线程
- 线程生命周期
- 线程优先级
- 优先级规则
- 案例演示
- 线程同步机制
- 线程同步机制
- synchronized关键字
- ReentrantLock类
- Condition类
- 监视器概念
- volatile关键字
- final变量
- 死锁
- 线程局部变量
- 读/写锁
- 原子类
- 阻塞队列
- 工作规则
- 案例演示
- 常用阻塞队列
- 线程安全集合
- 高效的映射/集/队列
- 并发集视图
- 写数组的拷贝
- Arrays类的并行数组算法
- 同步包装器
- Callable与Future
- 执行器
- 线程池
- 预定执行
- 控制任务组
- Fork-Join框架
- 同步器
- 同步器
- 信号量
- CountDownLatch类
- CyclicBarrier类
- Exchanger类
- SynchronousQueue类
- 线程与Swing
- Swing与线程问题
- 两个原则
- Swing工作线程
- 单一线程规则
- 文件IO
- File类
- 文件输入输出
- ZIP压缩文件
- 集合
- 集合框架
- 集合接口
- 集合实现类
- 线程安全集合
- 集合算法
- 迭代器
- 集合排序
- JDBC
- JDBC是什么
- JDBC-ODBC桥
- JDBC驱动程序类型
- JDBC常用类与接口
- 数据库操作
- 连接数据库
- 增/删/改/查/预处理
- 事务
- 批处理
- commons-dbutils工具
- 安全问题
- Jedis
- 使用Jedis操作Redis数据库
- JSON转换
- 使用连接池
- 案例
- 单例破坏
- 单例定义
- 单例实现方式
- 懒汉式实现单例
- 饿汉式实现单例
- 单例破坏
- 类的单例破坏
- 枚举的单例破坏
- 克隆
- 克隆是什么
- 浅克隆
- 深克隆
- 注解
- 注解是什么
- 三大注解
- 内置注解
- 元注解
- 自定义注解
- NIO
- 相关概念
- BIO/NIO/AIO
- 多线程编程
- 线程同步
- 线程通信
- NIO
- NIO三大核心组件
- NIO网络编程
- NIO文件读写
- AIO
- Java8新特性
- Lambda表达式
- 方法引用
- 函数式接口
- 默认方法
- 什么是默认方法
- 默认方法语法格式
- 多个同名的默认方法问题
- 静态默认方法
- 默认方法实例
- Stream
- Stream是什么
- Stream示例
- Optional容器
- 新的日期时间API
- Base64
- SPI
- SPI是什么
- SPI与API的区别
- 常见场景
- 使用SPI需遵循的约定
- SPI使用步骤