【Redis】利用Redis优化数据案例
一、环境搭建
业务分析:编写一个简单的前端页面,选择用一个 <select>
列表,页面加载完成后发送Ajax请求, 加载所有省份。
数据库环境
创建如下的数据库以及数据表:
create database province;
use province;
create table province(id int primary key not null auto_increment,name varchar(20) not null
);insert into province(name) value("北京");
insert into province(name) value("天津");
insert into province(name) value("上海");
insert into province(name) value("重庆");
配置环境
使用druid.properties文件:
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql:///province
username=root
password=123456
initialSize=5
maxActive=10
maxWait=3000
使用redis.properties文件:
redis.host=127.0.0.1
redis.port=6379
redis.maxTotal=30
redis.maxIdle=10
依赖文件pom.xml为:
<dependencies><dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.2</version></dependency><dependency><groupId>commons-beanutils</groupId><artifactId>commons-beanutils</artifactId><version>1.7.0</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.6</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-annotations</artifactId><version>2.12.2</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>2.12.1</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.12.1</version></dependency><dependency><groupId>jstl</groupId><artifactId>jstl</artifactId><version>1.2</version></dependency><dependency><groupId>org.glassfish.web</groupId><artifactId>jstl-impl</artifactId><version>1.2</version></dependency><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.23</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId><version>5.2.4.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.2.4.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>5.2.4.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>5.2.4.RELEASE</version></dependency>
</dependencies>
其中,创建servlet需要的核心依赖为:
<dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version>
</dependency>
创建web包,并且引入jQuery框架包。在web包下编写主页代码,其中body主题如下所示:
<body>
<select id="province"><option>--请选择省份--</option>
</select>
</body>
二、编写业务
业务逻辑
整个业务逻辑:
HTML页面发送请求——Servlet接收请求处理——调用Service层——调用dao层——数据库查询
dao层
创建com.company.dao.ProvinceDao接口
public interface ProvinceDao {List<Province> findAll();
}
创建对应的实现类com.company.dao.impl.ProvinceDaoImpl类
public class ProvinceDaoImpl implements ProvinceDao {// 1. 声明JdbcTemplate对象private final JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());@Overridepublic List<Province> findAll() {// 2. 定义sqlString sql = "select * from province";// 3. 执行sql语句List<Province> provinces = jdbcTemplate.query(sql, new BeanPropertyRowMapper<Province>(Province.class));return provinces;}
}
domain层
创建实体类com.company.domain.Province类
public class Province {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;}@Overridepublic String toString() {return "Province{" +"id=" + id +", name='" + name + '\'' +'}';}
}
service层
创建service层com.company.service.ProvinceService接口
public interface ProvinceService {List<Province> findAll();
}
创建对应的实现类com.company.service.impl.ProvinceServiceImpl类
public class ProvinceServiceImpl implements ProvinceService {// 声明dao变量,service调用dao层private final ProvinceDao dao = new ProvinceDaoImpl();@Overridepublic List<Province> findAll() {return dao.findAll();}
}
util包
创建jdbc工具类com.company.util.JDBCUtils类
public class JDBCUtils {public static DataSource ds;static {try {// 1. 加载配置文件Properties pro = new Properties();// 2. 获取字节输入流InputStream stream = JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties");pro.load(stream);// 3. 初始化连接池对象ds = DruidDataSourceFactory.createDataSource(pro);} catch (Exception e) {e.printStackTrace();}}// 获取数据源对象public static DataSource getDataSource() {return ds;}// 获取连接对象public static Connection getConnection() throws SQLException {return ds.getConnection();}}
web.servlet包
创建com.company.web.servlet.ProvinceServlet类
@WebServlet(name = "ProvinceServlet", value = "/provinceServlet")
public class ProvinceServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 1. 调用service查询ProvinceService service = new ProvinceServiceImpl();List<Province> list = service.findAll();// 2. 序列化list为jsonObjectMapper mapper = new ObjectMapper();String json = mapper.writeValueAsString(list);System.out.println(json);// 3. 响应结果response.setContentType("application/json;charset=utf-8");response.getWriter().write(json);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
}
三、Ajax请求
在主页中编写响应的请求代码,发起Ajax连接。
<script src="js/jquery-3.5.1.min.js"></script>
<script>$(function () {// 发送Ajax请求,加载所有省份数据$.get("provinceServlet", {}, function (data) {// [{"id":1,"name":"北京"},{"id":2,"name":"天津"}// {"id":3,"name":"上海"},{"id":4,"name":"重庆"}]// 1. 获取selectlet province = $("#province");// 2. 遍历json数组$(data).each(function () {// 3. 创建option标签let option = "<option name='" + this.id + "'>" + this.name + "</option>";// 4. 调用select的append方法,追加optionprovince.append(option);});});});
</script>
四、Redis优化
使用Redis对整个业务进行优化,主要的使用方式是使用Redis的缓存优化。
在整个业务的Service层进行操作,逻辑如下:
- 从Redis中查询数据
- 没有
- 再从数据库中查询
- 将数据存入Redis
- 返回数据
- 有
- 直接返回数据
- 没有
这样的操作,可以减少数据库的查询次数,加快整个业务的运行速度。
准备阶段
导入新的jedis的依赖包:
<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>3.6.0</version>
</dependency>
编写jedis连接池工具类com.company.util.JedisPoolUtils类:
public class JedisPoolUtils {private static JedisPool jedisPool;static {// 读取配置文件InputStream resource = JedisPoolUtils.class.getClassLoader().getResourceAsStream("redis.properties");Properties properties = new Properties();try {properties.load(resource);} catch (IOException e) {e.printStackTrace();}// 获取数据,设置到JedisPoolConfig中JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();jedisPoolConfig.setMaxTotal(Integer.parseInt(properties.getProperty("redis.maxTotal")));jedisPoolConfig.setMaxIdle(Integer.parseInt(properties.getProperty("redis.maxIdle")));// 初始化JedisPool对象jedisPool = new JedisPool(jedisPoolConfig, properties.getProperty("redis.host"), Integer.parseInt(properties.getProperty("redis.port")));}/*** 获取连接方法* @return 返回Jedis连接对象*/public static Jedis getJedis() {return jedisPool.getResource();}
}
添加方法
在service接口层添加新的方法:
public interface ProvinceService { List<Province> findAll(); String findAllJson();}
实现类中添加新的方法:
/*** 使用redis缓存优化业务*/
@Override
public String findAllJson() {// 先从redis中查询数据// 创建jedis对象Jedis jedis = JedisPoolUtils.getJedis();System.out.println("连接成功");String provinceJson = jedis.get("province");// 判断provinceJson是否有值if (provinceJson == null || provinceJson.length() == 0) {System.out.println("redis中无数据,查询数据库...");// redis中没有数据,需要从数据库中获取List<Province> provinces = dao.findAll();// 将list序列化成jsonObjectMapper mapper = new ObjectMapper();try {provinceJson = mapper.writeValueAsString(provinces);System.out.println(provinceJson);} catch (JsonProcessingException e) {e.printStackTrace();}try {// 将json数据存入redis中String set = jedis.set("province", provinceJson);if ("OK".equals(set)) {System.out.println("数据存入成功");}} catch (Exception e) {e.printStackTrace();} finally {// 释放资源jedis.close();}} else {System.out.println("redis中有数据,查询缓存...");}return provinceJson;
}
最后在servlet中替换新的方法调用:
// 1. 查询json
ProvinceService service = new ProvinceServiceImpl();
// 2. 序列化结果
String json = service.findAllJson();
System.out.println(json);
// 3. 响应结果
response.setContentType("application/json;charset=utf-8");
response.getWriter().write(json);
五、注意
使用redis缓存一些内容不经常发生变化的数据更加合适
- 数据库的数据一 旦发生改变,则需要更新缓存。
- 数据库的表执行增删改的相关操作,需要将redis缓存数据情况,再次存入
- 在service对应的增删改方法中,将redis数据删除
遇见问题:
java.lang.ClassNotFoundException: org.apache.commons.pool2.impl.GenericObjectPoolConfig
原因是缺少必要的jar包:
<dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId><version>2.6.0</version>
</dependency>
【Redis】利用Redis优化数据案例相关推荐
- 利用redis缓存对 list集合中的数据 进行分页操作(一)
先说 存储的结构: 这里做了两块缓存 绿色是存储索引的缓存 黑色是存数据的缓存 翻页时需要两个参数 向上查询/或向下查询 还一个是 从第二页开始查询时需要一个索引的参数 有了这两个参数 ...
- 某大型政务网站的优化咨询案例(视频点播VOD+GZIP压缩+静态文件CDN+Redis缓存+全文索引)
2022年圣诞节到来啦,很高兴这次我们又能一起度过~ 这次分享关于一个对某大型政务网站的优化咨询的案例,发生在今年的下半年,已过去一段时间,并取得了良好的成果!* 项目背景 某大型政务网站准备上线,需 ...
- Java 性能优化实战案例分析:Redis如何助力秒杀业务
在上一课时,我们以 Guava 的 LoadingCache 为例,介绍了堆内缓存的特点以及一些注意事项.同时,还了解了缓存使用的场景,这对分布式缓存来说,同样适用. 那什么叫分布式缓存呢?它其实是一 ...
- python—简单数据抓取七(采取蘑菇API代理设置scrapy的代理IP池并利用redis形成队列依次使用,利用ip池访问网页并将scrapy爬取转移到items的数据存入到数据库)
学习目标: Python学习二十七-简单数据抓取七 学习内容: 1.采取蘑菇API代理设置scrapy的代理IP池并利用redis形成队列依次使用 2.利用ip池访问网页并将scrapy爬取转移到it ...
- 利用Redis解决重复数据时候的并发异常和分布式锁解决方案
最近公司里有一个并发业务.多个线程消费一个kafka数据流,这个kafka数据流里数据的某个字段有重复.需要根据这个字段来做下去重. 一开始的方案是利用Redis来实现,先查Redis如果没有的话则s ...
- 【Java项目中 利用Redis实现数据缓存】
文章目录 Java SpringBoot项目中 用Redis实现数据缓存 1 环境搭建 1.1 maven坐标 1.2 配置文件 1.3 配置类 2 实现缓存短信验证码 3 缓存菜品数据 4 Spri ...
- NoSQL之 Redis配置与优化
NoSQL之 Redis配置与优化 前言 一.缓存概念 (1)系统缓存 ①buffer与cache (2)缓存保存位置及分层结构 ①DNS缓存 ②应用层缓存 ③数据层缓存 ④硬件缓存 二.关系数据库和 ...
- c#获取对象的唯一标识_在 Java 中利用 redis 实现分布式全局唯一标识服务
作者: 杨高超 juejin.im/post/5a4984265188252b145b643e 获取全局唯一标识的方法介绍 在一个IT系统中,获取一个对象的唯一标识符是一个普遍的需求.在以前的单体应用 ...
- NoSQL(2)之 Redis配置与优化
文章目录 一.关系数据库和非关系数据库 1.1 关系型数据库 1.2 非关系型数据库 1.3 非关系型数据库的产生背景 1.4 关系型数据库和非关系型数据库区别 1.数据存储方式不同 2.扩展方式不同 ...
最新文章
- 【Android 组件化】路由组件 ( 注解处理器获取被注解的节点 )
- java银行管理系统_java实现银行管理系统
- Why SAP SQL view is not recommended to use in SQL ?
- C++学习之路 | PTA(天梯赛)—— L2-010 排座位 (25分)(带注释)(并查集)(精简)
- 给控件做数字签名之三:进行数字签名
- 21 世纪最需要的 7 种人才素质 - 李开复
- Hive时间戳TIMESTAMP使用的限制
- vue中:class实现样式的绑定
- 前端多个圆圈均匀横向排列_web前端工程师必须掌握的24条宝贵经验!让你在前端路上更轻松!...
- php yii2模块,Yii2 中关于模块(Modules)的使用及配置
- 哈密顿图、哈密顿回路
- 在python中的占位符中、请你选出不属于占位符的选项_2020年超星尔雅微表情识别·读脸读心 作业答案...
- DTOJ3704 威士忌(whiskey)
- linux文件夹可视化工具,4款简单实用的的服务器文件管理工具推荐
- PubWin不知道密码情况下卸载
- 2022年全网最新 Windows10 安装 JDK1.8
- linux系统搭建论坛,Linux下搭建discuz论坛
- python如何期货交易_能用python的期货交易软件
- html 绘制体温单,使用zrender.js绘制体温单效果
- 扇贝单词里有计算机英语吗,一个人背单词,一群人学英语:扇贝单词