您的位置:首页 > 数据库 > Redis

Redis的缓存优化案例

2019-10-23 16:24 746 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/q961250375/article/details/102703931

1.准备事项

需求简要:在index.html中添加一个下拉列表,显示省份信息。当页面加载完成后,发送ajax请求,从服务器端获取数据回显到页面。在服务器端使用Redis缓存优化(在服务器接收到客户端的请求后,会先去缓存中找数据如果缓存中有该数据,则直接响应给客户端,不会使用数据库的资源。如果缓存中没有该数据,则再去使用数据库的资源去找数据并将该数据存储在缓存中以供下次使用)。

参考文档
(1)非关系型数据库Redis的入门学习。https://blog.csdn.net/q961250375/article/details/102680405
(2)Jedis学习,一款Java操作Redis数据库的工具。https://blog.csdn.net/q961250375/article/details/102688899

案例源码下载【百度网盘mnlq】

2.案例实现

2.1.创建数据库

CREATE DATABASE demo CHARACTER SET utf8 COLLATE utf8_general_ci;
USE demo;
CREATE TABLE province(
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(20) NOT NULL
)CHARACTER SET utf8 COLLATE utf8_general_ci;
-- 插入数据
INSERT INTO province VALUES(NULL,"北京");
INSERT INTO province VALUES(NULL,'上海');
INSERT INTO province VALUES(NULL,'广州');
INSERT INTO province VALUES(NULL,'深圳');
INSERT INTO province VALUES(NULL,'湖北');

2.2.项目结构及相关Jar包


2.3.项目具体代码

(1)数据库连接池配置文件:druid.properties

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///demo
username=root
password=root
initialSize=5
maxActive=10
maxWait=3000

(2)Redis连接池配置文件:jedis.properties

host=127.0.0.1
port=6379
maxTotal=50
maxIdle=10

(3)JDBC工具类:JDBCUtils

package com.atlantis.util;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

/**
* JedisPoolUtils
* 记载配置文件,配置连接池参数,提供获取连接的方法
*/
public class JedisPoolUtils {
private static JedisPool jedisPool;

static {
// 读取jedis.properties配置文件
InputStream inputStream = JedisPoolUtils.class.getClassLoader().getResourceAsStream("jedis.properties");
// 创建Properties对象
Properties properties = new Properties();
// 关联配置文件
try {
properties.load(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
// 获取数据并设置到JedisPoolConfig中
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();

// 在此处设置JedisPool的配置信息 START
jedisPoolConfig.setMaxTotal(Integer.parseInt(properties.getProperty("maxTotal")));
jedisPoolConfig.setMaxIdle(Integer.parseInt(properties.getProperty("maxIdle")));
// .........
// 在此处设置JedisPool的配置信息 END

// 初始化JedisPool
jedisPool = new JedisPool(jedisPoolConfig, properties.getProperty("host"), Integer.parseInt(properties.getProperty("port")));
}

/**
* 获取连接
*/
public static Jedis getJedis() {
return jedisPool.getResource();
}
}

(4)JedisPool工具类:JedisPoolUtils

package com.atlantis.util;

import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

/**
* JDBC工具类 使用Durid连接池
*/
public class JDBCUtils {
private static DataSource ds ;
static {
try {
// 1.加载配置文件
Properties pro = new Properties();
//使用ClassLoader加载配置文件,获取字节输入流
InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties");
pro.load(is);

// 2.初始化连接池对象
ds = DruidDataSourceFactory.createDataSource(pro);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}

/**
* 获取连接池对象
*/
public static DataSource getDataSource(){
return ds;
}

/**
* 获取连接Connection对象
*/
public static Connection getConnection() throws SQLException {
return  ds.getConnection();
}
}

(5)Province省份实体类设计

package com.atlantis.entity;

public class Province {
private int id;
private String name;

// 省略构造方法
// 省略get和set方法
}

(6)数据持久层Dao:只贴ProvinceDaoImpl.java实现接口代码

package com.atlantis.dao.impl;

import com.atlantis.dao.ProvinceDao;
import com.atlantis.entity.Province;
import com.atlantis.util.JDBCUtils;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import java.util.List;

public class ProvinceDaoImpl implements ProvinceDao {
private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());

@Override
public List<Province> findAll() {
String sql = "select * from province ";
List<Province> list = template.query(sql, new BeanPropertyRowMapper<Province>(Province.class));
return list;
}
}

(7)服务持久层Service:只贴ProvinceServiceImpl.java实现接口代码

package com.atlantis.service.impl;

import com.atlantis.dao.ProvinceDao;
import com.atlantis.dao.impl.ProvinceDaoImpl;
import com.atlantis.entity.Province;
import com.atlantis.service.ProvinceService;
import java.util.List;

public class ProvinceServiceImpl implements ProvinceService {
//声明dao
private ProvinceDao dao = new ProvinceDaoImpl();

@Override
public List<Province> findAll() {
return dao.findAll();
}
}

(8)控制层Servlet:ProvinceServlet

package com.atlantis.web.servlet;

import com.atlantis.entity.Province;
import com.atlantis.service.ProvinceService;
import com.atlantis.service.impl.ProvinceServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

@WebServlet("/provinceServlet")
public class ProvinceServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.调用service查询
ProvinceService service = new ProvinceServiceImpl();
List<Province> list = service.findAll();
//2.序列化list为json
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(list);
//System.out.println(json);
//3.响应结果
response.setContentType("application/json;charset=utf-8");
response.getWriter().write(json);

}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}

3.Redis缓存优化

可以发现,每次页面刷新或访问ProvinceServlet时都会访问数据库,耗时也耗资源。而且数据库中province表中的省份数据一般情况下是“固定”的,不会发生变化。

因此,可以通过Redis缓存优化的方案,将这些“固定”的数据放入缓存中。
服务器接收到客户端的请求后,会先去缓存中找数据。
如果缓存中有该数据,则直接响应给客户端,不会使用数据库的资源。如果缓存中没有该数据,则再去使用数据库的资源去找数据并将该数据存储在缓存中以供下次使用。
这样就大大降低了访问数据库的频率,提升了整体的查询性能。

3.1.代码改造

(1)在服务层Service的接口定义一个方法并且在ProvinceServiceImpl中实现这个方法,该方法用于从缓存中查询数据,返回类型是JSON,即String类型。

@Override
public String findAllJson() {
//1.先从redis中查询数据
//1.1获取redis客户端连接
Jedis jedis = JedisPoolUtils.getJedis();
String province_json = jedis.get("province");

//2判断 province_json 数据是否为null
if(province_json == null || province_json.length() == 0){
//redis中没有数据
System.out.println("redis中没数据,查询数据库...");
//2.1从数据中查询
List<Province> ps = dao.findAll();
//2.2将list序列化为json
ObjectMapper mapper = new ObjectMapper();
try {
province_json = mapper.writeValueAsString(ps);
} catch (JsonProcessingException e) {
e.printStackTrace();
}

//2.3 将json数据存入redis
jedis.set("province",province_json);
//归还连接
jedis.close();
}else{
System.out.println("redis中有数据,查询缓存...");
}
return province_json;
}

(2)最后在ProvinceServlet方法中,调用服务层Service的findAllJson()方法即可。

package com.atlantis.web.servlet;

import com.atlantis.entity.Province;
import com.atlantis.service.ProvinceService;
import com.atlantis.service.impl.ProvinceServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

@WebServlet("/provinceServlet")
public class ProvinceServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/*//1.调用service查询
ProvinceService service = new ProvinceServiceImpl();
List<Province> list = service.findAll();
//2.序列化list为json
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(list);*/

//1.调用service查询
ProvinceService service = new ProvinceServiceImpl();
String json = service.findAllJson();

System.out.println(json);
//3.响应结果
response.setContentType("application/json;charset=utf-8");
response.getWriter().write(json);

}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: