一、简单介绍

redis是一款高性能的NOSQL系列的非关系型数据库。主要用于缓存,可提升数据访问的性能。这里用于做缓存的数据是不经常做改变的数据。核心思想见下图:

redis

使用缓存机制,可以加快我们数据的访问。因为数据是暂存在内存中,直接访问内存的数据可以减少在访问数据库过程中的I/O操作,这样便可以提升系统的性能,查询速度。但是作为缓存也有一定的缺点:数据因为是暂存在内存上的,一旦redis服务端关闭,再次开启时,缓存数据将不复存在。因此在某些场合中,我们需要对redis缓存数据做持久化操作,将其持久化到硬盘上,当再次查询时,可将数据读取到缓存中。

从以上我们看出redis使用时的两点注意事项:

  1. 数据不会经常改变。如果,数据持续改变,就不断的访问数据库,再将数据放入到缓存中。
  2. 确定持久化操作的条件。不能随时随地的进行持久化(反而增加了IO操作),也不能对缓存中大量改变的数据不做持久化数据(会导致数据大量的丢失)。

二、案例实操

通过对redis的基本介绍,我们做一个小案例。案例需求如下:

  1. 提供index.html页面,页面中有一个省份下拉列表
  2. 当页面加载完成后,发送ajax请求,加载所有省份

思路:

当接收到请求时,做redis缓存的查询。如果缓存中存在所需要的数据,就将缓存数据进行返回;如果不存在,就进行数据库查询,同时将数据库中的数据加入到缓存中,再将数据进行返回。

前端接收到的数据是序列化后的Json数据,便于数据的读取,进行页面数据的展示。

思考:为什么这里要使用ajax
当我们对页面进行加载时,就需要自动显示后台传递的数据,而没有进行任何链接的操作(form表单提交、点击超链接等操作),而让页面主动对后端进行请求,所以我们这里需要使用ajax,简化我们的操作。

第二点是因为异步请求是为了获取服务器响应的数据,而前端使用的是html,不能够直接从servlet相关的域对象获取值,只能通过ajax获取相应的数据。

以下便是具体实现的代码:

dao层中findAll方法的实现
1
2
3
4
5
6
7
8
9
10
11
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;
}
}
service层中findAll方法的实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class ProvinceServiceImpl implements ProvinceService {

private ProvinceDao provinceDao = new ProvinceDaoImpl();

@Override
public String findAllByRedis() {
Jedis jedis = JedisUtils.getJedis(); // 创建Jedis对象,用于redis的操作
String province = jedis.get("province"); // 获取需要查询的对象
if (province == null || province.length() == 0) { // 若缓存中不存在则查询数据库
System.out.println("缓存中没有,先对数据库进行查询");
List<Province> list = provinceDao.findAll(); // 调用dao中,数据库查询操作
ObjectMapper mapper = new ObjectMapper(); // 数据序列化 -- Json格式
try {
province = mapper.writeValueAsString(list);
jedis.set("province", province);
} catch (JsonProcessingException e) {
e.printStackTrace();
} finally {
jedis.close();
}
} else {
System.out.println("查询的数据在缓存中");
}

return province;
}
}
web层中FindAllProvince类
1
2
3
4
5
6
7
8
9
10
11
12
13
@WebServlet("/findAllProvince")
public class FindAllProvince extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("application/json;charset=utf-8");// 设置编码格式
ProvinceService service = new ProvinceServiceImpl();
String json_list = service.findAllByRedis(); // Redis缓存机制
response.getWriter().write(json_list); // Ajax数据返回
}

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

2.1 Util包

JDBCUtils工具类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class JDBCUtils {

private static DataSource ds;

static {

InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties");// 配置文件的字节输入流
Properties properties = new Properties();
try {
properties.load(is); // 属性集的加载 -- map,key:value
ds = DruidDataSourceFactory.createDataSource(properties);// 初始化数据库连接池
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}


}

public static DataSource getDataSource() {
return ds;
}

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

}
JedisUtils工具类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class JedisUtils {

private static Jedis jedis;

static {

InputStream is = JedisUtils.class.getClassLoader().getResourceAsStream("jedis.properties");
Properties properties = new Properties();
try {
properties.load(is);
} catch (IOException e) {
e.printStackTrace();
}
JedisPoolConfig config = new JedisPoolConfig(); // 配置对象,可对redis进行配置
String password = (String) properties.get("password");
String port = properties.getProperty("port");
String host = (String) properties.get("host");
String maxTotal = (String) properties.get("maxTotal");
String maxIdle = (String) properties.get("maxIdle");
config.setMaxIdle(Integer.parseInt(maxIdle));
config.setMaxTotal(Integer.parseInt(maxTotal));
JedisPool jedisPool = new JedisPool(config, host, Integer.parseInt(port));
jedis = jedisPool.getResource();
jedis.auth(password);
}

public static Jedis getJedis() { // 返回Jedis对象
return jedis;
}
}

2.2前端代码

前端代码展示
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>省份导入</title>
<script src="js/jquery-3.3.1.min.js"></script>
</head>
<body>
<select id="province">
<option>--请选择省份--</option>
</select>

<script>
$.get("findAllProvince", {}, function (data) {
$(data).each(function () {
var option = "<option name=(''+this.id) value=(''+this.id)>"+this.name+"</option>"; // value中的值是被送往服务器作为请求参数,而标签中的值是作为前端的展示值不是作为请求参数。
$province.append(option)
});

});
</script>
</body>
</html>

2.3 注意事项

redis是用于缓存一些不经常发生变化的数据。

数据库的数据一旦发生改变,则需要更新缓存。

  • 数据库的表执行增删改的相关操作,需要将对应的redis缓存数据清空,再次存入
  • service对应的增删改方法中,将redis数据删除。

Comment