程序员:SpringBoot和Redis实现Java缓存技术
缓存在大家工作中被广泛应用,特别是一些互联网公司的程序员。
今天给大家讲解一个实例,基于SpringBoot环境下的RedisTemplate来对redis数据库进行操作,同时也使用到SSM来进行数据库操作,进而实现Java缓存技术的实例开发,下面我开始详细讲解具体的实现过程:
项目的目录结构:
该项目为maven项目结构,相信有学习SpringBoot框架的读者应该都会创建这种项目,此处笔者就不讲解,有需要了解的读者可以在评论区下留言,笔者提供创建链接。
在pom.xml文件中添加依赖:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>SpringBootDemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>SpringBootDemo</name>
<description>Demo project for Spring Boot</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<!-- 热部署用,改变代码不需要重启项目 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
<scope>true</scope>
</dependency>
<!-- 配置JSP访问视图 -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<!-- mysql连接 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 添加 Mysql 依赖 -->
<!-- 添加 Spring Data JPA 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- redis依赖配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.44</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<!-- fork : 如果没有该选项,那这个热部署的devtools不会起作用,即应用不会自动restart -->
<fork>true</fork>
</configuration>
</plugin>
</plugins>
</build>
</project>
在配置文件application.properties中添加以下信息:
server.port: 8081
# mysql
spring.datasource.url: jdbc:mysql://localhost:3306/jsp?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
spring.datasource.username: root
spring.datasource.password: root
# spring.datasource.driver-class-name: com.mysql.jdbc.Driver not can use
spring.datasource.driver-class-name: com.mysql.jdbc.Driver
spring.datasource.dbcp2.validation-query: 'select 1'
spring.datasource.dbcp2.test-on-borrow: true
spring.datasource.dbcp2.test-while-idle: true
spring.datasource.dbcp2.time-between-eviction-runs-millis: 27800
spring.datasource.dbcp2.initial-size: 5
spring.datasource.dbcp2.min-idle: 5
spring.datasource.dbcp2.max-idle: 100
spring.datasource.dbcp2.max-wait-millis: 10000
# mybatis
# 指mapper映射文件会绑定到src/main/resource/mapper目录下
mybatis.mapper-locations: classpath*:mapper/**/*.xml
mybatis.configuration.map-underscore-to-camel-case: true
# JSP use's configution spring.mvc.view.prefix
spring.mvc.view.prefix = /WEB-INF/views/
spring.mvc.view.suffix = .jsp
#解决sql Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set 的问题
spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect
#本地主机名
spring.redis.host=127.0.0.1
#redis默认的端口值
spring.redis.port=6379
#redis数据库,总共有0-15可以输入
spring.redis.database=1
注意:
①此处的mysql数据库信息配置读者可以根据自己的本地数据库信息进行修改;
②配置信息中“classpath*:mapper/**/*.xml”是指映射到mapper/路径下所有目录的xml文件;
③spring.redis.database=1的“1”代表redis数据库下对应的编号,如图所示:
设计思路:
在获取数据前,先对跟数据是否存在于redis缓存中进行判断,如果存在,则直接从缓存中把数据读取出来;否则,先把数据从mysql或SQL Server数据库中查询出来,然后再把查询出来的数据添加到redis缓存中。
① 实体类的编写:
import javax.persistence.Id;
import javax.persistence.Table;
/*
* @time:2020/1/2
* @descrition:学生实体类,用于封装学生的基本信息
**/
@Table(name="student")
public class Student {
@Id
String id;//主键
String name;//姓名
String sno;//学号
String sex;//性别
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSno() {
return sno;
}
public void setSno(String sno) {
this.sno = sno;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
在此说明一下,本文并没有单独把数据库文件导出来给大家使用,读者们可以自己去创建一个数据库及表来进行测试,相信能学到这里的读者都应该具备较好的编程基础,对于这种简单的数据库设计应该只需要几分钟就能完成的,实在不会可以在评论区下留言,笔者一一帮忙解答。
②dao层的编写:
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import Test.entity.Student;
/*
* @time: 2020/1/3
* @description: 映射对应xml配置文件
*
**/
@Mapper
public interface TestDao {
//查询学生信息
public List<Student> getStuList();
}
③TestMapper.xml配置文件的编写:
<?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="Test.dao.TestDao">
<select id="getStuList" resultType="Test.entity.Student">
select * from student
</select>
</mapper>
此处也要注意一点,即namespace和resultType属性的值都要对应自己的项目路径来编写,否则一定会出错,请各位读者认真查阅,避免不必要的错误。
④业务逻辑层的编写:
import java.lang.reflect.Type;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import Test.dao.TestDao;
import Test.entity.Student;
/*
* @time: 2020/1/3
* @description: 测试业务逻辑类,用于编写代码的具体实现逻辑
*
**/
@Service
public class TestService {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private TestDao testDao;
/*
* 此处为redis缓存技术的核心代码
* 这是基于一种相对简单方式去进行缓存的,适合刚入门的新手去学习
**/
public List<Student> getStuList(){
String key = "student_list";
ValueOperations<String, String> operations = redisTemplate.opsForValue();
//如果该键存在,说明缓存中存在,则直接从缓存中把数据读出即可,而不需要查询数据库进行获取。
if (redisTemplate.hasKey(key)) {
//从缓存中
String redisList = (String) operations.get(key);
Type type = new TypeToken<List<Student>>() {}.getType();
List<Student> list = new Gson().fromJson(redisList, type);
System.out.println("从缓存取得数据"+ list.size()+"条数" );
return list;
}
//此处是笔者在后端数据库中获取的list数据集合,读者可以根据自己的需求进行修改。
List<Student> list = studentMapper.selectAll();
System.out.println("从数据库中查询数据");
//再把list集合强制转化为json格式数据
String toJson = new Gson().toJson(list);
// 保存到redis数据库缓存中,第一个参数为键名,第二个参数为数据,第三个参数为有效时间,第四个为时间单位
operations.set(key, toJson, 60, TimeUnit.SECONDS);
System.out.println("已经把list集合保存到缓存中");
return list;
}
}
⑤控制层的编写:
import java.util.List;
import javax.servlet.ServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import Test.entity.Student;
import Test.service.TestService;
/*
* @time: 2020/1/3
* @description: 测试控制器,有设置到两层访问路径
**/
@Controller
@RequestMapping(value="student")
public class TestController {
@Autowired
private TestService testService;
//@ResponseBody注解可以让该方法映射对应数据返回到前端页面,而不是查找jsp视图
@RequestMapping(value="getStuList",produces = "application/json;charset=UTF-8")
@ResponseBody
public List<Student> getStuList(ServletRequest request) {
return testService.getStuList();
}
}
⑥最后在浏览器中输入:http://localhost:8081/student/getStuList。结果如下:
此处是把list集合以json数据格式显示在页面中,方便读者去查看效果。
同时,我们也可以注意到,当我们第一次在浏览器访问时,该集合是从mysql数据库进行获取的,当我们开始第二次访问时,会发现我们的数据是从redis缓存中进行获取,这些信息可以从编译器的控制台中查看,具体如下: