如果我的博客能够帮到大家能够点个赞,关注一下,以后还会更新更过JavaWeb的高级技术,大家的支持就是我继续更新的动力。谢谢咯。
在日常得开发中,JavaWeb项目中经常需要使用缓存,加快系统得访问速度。有利于用户更好的用户体验。以下是SpringBoot整合Redis的案例,仅供参考。
一、环境搭建
- 导入依赖
<!--引入缓存组件--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency>
- 编写实体类 DepartMent.java 和 Employee.java
package com.nyist.cache.model;
import java.io.Serializable;
public class Department implements Serializable {
private Integer id;
private String departmentName;
public Department() {
super();
// TODO Auto-generated constructor stub
}
public Department(Integer id, String departmentName) {
super();
this.id = id;
this.departmentName = departmentName;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getDepartmentName() {
return departmentName;
}
public void setDepartmentName(String departmentName) {
this.departmentName = departmentName;
}
@Override
public String toString() {
return "Department [id=" + id + ", departmentName=" + departmentName + "]";
}
}
package com.nyist.cache.model;
import java.io.Serializable;
public class Employee implements Serializable {
private Integer id;
private String lastName;
private String email;
private Integer gender; //性别 1男 0女
private Integer dId;
public Employee() {
super();
}
public Employee(Integer id, String lastName, String email, Integer gender, Integer dId) {
super();
this.id = id;
this.lastName = lastName;
this.email = email;
this.gender = gender;
this.dId = dId;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Integer getGender() {
return gender;
}
public void setGender(Integer gender) {
this.gender = gender;
}
public Integer getdId() {
return dId;
}
public void setdId(Integer dId) {
this.dId = dId;
}
@Override
public String toString() {
return "Employee [id=" + id + ", lastName=" + lastName + ", email=" + email + ", gender=" + gender + ", dId="
+ dId + "]";
}
}
- 配置数据源
spring: datasource: username: root password: root url: jdbc:mysql://localhost:3306/spring_cache?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8 type: com.alibaba.druid.pool.DruidDataSource initialSize: 5 minIdle: 5 maxActive: 20 maxWait: 60000 timeBetweenEvictionRunsMillis: 60000 minEvictableIdleTimeMillis: 300000 validationQuery: SELECT 1 FROM DUAL testWhileIdle: true testOnBorrow: false testOnReturn: false poolPreparedStatements: true # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙 filters: stat,wall,logback maxPoolPreparedStatementPerConnectionSize: 20 useGlobalDataSourceStat: true connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500 #指定链接的Redis redis: host: 192.168.1.110 #mybatis 开启驼峰命名法 mybatis: configuration: map-underscore-to-camel-case: true #设置日志等级 logging: level: com.nyist.cache.mapper: debug #打开控制报告 #debug: true
- 配置Mapper DepartmentMapper.java 和 EmployeeMapper.java
package com.nyist.cache.mapper;
import com.nyist.cache.model.Department;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
@Mapper
public interface DepartmentMapper {
@Select("select * from department where id=#{id}")
Department getDeptById(Integer id);
}
package com.nyist.cache.mapper;
import com.nyist.cache.model.Employee;
import org.apache.ibatis.annotations.*;
@Mapper
public interface EmployeeMapper {
@Select("select * from employee where id = #{id}")
public Employee getEmpById(Integer id);
@Update("update employee set lastName = #{lastName},email=#{email},gender=#{gender} where id=#{id}")
public void updateEmp(Employee employee);
@Delete("delete from employee where id = #{id}")
public void deleteEmp(Integer id);
@Insert("insert into employee(lastName,email,gender,d_id) values(#{lastName},#{email},#{gender},#{d_id})")
public void insertEmp(Employee employee);
@Select("select * from employee where lastName = #{lastName}")
Employee getEmpByLastName(String lastName);
}
- config配置 MyRedisConfiguration.java
package com.nyist.cache.comfig;
import com.nyist.cache.model.Employee;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
//开启自定义序列化
@Configuration
public class MyRedisConfiguration {
@Bean //加入到容器中去
public RedisTemplate<Object, Employee> empredisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Employee> redisTemplate = new RedisTemplate<Object, Employee>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
//转换为json 保存到redis数据库中
Jackson2JsonRedisSerializer<Employee> serializer = new Jackson2JsonRedisSerializer<Employee>(Employee.class);
redisTemplate.setDefaultSerializer(serializer);
return redisTemplate;
}
}
- servic层 DeptService.java 和 EmployeeService.java
package com.nyist.cache.service;
import com.nyist.cache.mapper.EmployeeMapper;
import com.nyist.cache.model.Employee;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.*;
import org.springframework.stereotype.Service;
//用于抽取公共配置
@CacheConfig(cacheNames = "emp")
@Service
public class EmployeeService {
@Autowired
EmployeeMapper employeeMapper;
/**
* 将方法的运行结果进行缓存,以后再要使用相同的数据,直接从缓存中拿,不调用方法。
* CacheManager 管理多个缓存Cache组件,对缓存的真正CRUD操作在Cache 组件中,每一个缓存组件有一个唯一一个名字
* 几个属性:
* cacheNames/valye:指定缓存组件的名字
* key:缓存数据时的key,可以用它来指定。 默认使用方法参数的值 1-方法的返回值
* 可以编写SPEL 表达式 #id;参数id的值, #a0 #p0 #root.args[0]
*
* keyGenerator:key 得生成器,可以自己指定key的生成器的组件ID
* key/keyGenerator:二选一
* cacheManager:指定缓存管理器,或者cacheResolver指定获取缓存解析器。
* condition:符合条件的情况下才缓存。
* unless:是否缓存,当unless指定的条件为true,方法的返回值不会被缓存,可以根据结果进行判断
* sync:是否使用异步模式
* @param id
* @return
*/
/***
* @Cacheable(condition="#id>0",cacheNames={"emp"})
* //指定key getEmp(2)
* @Cacheable(cacheNames = {"emp"},key="#root.methodName+'['+#id+']'")
* @Cacheable(cacheNames = {"emp"},keyGenerator = "myKeyGenerator",condition = "#a0>1 and #root.methodName eq 'aaa'")
*
* @param id
* @return
*/
@Cacheable(cacheNames = {"emp"},key = "#id")/*,keyGenerator = "myKeyGenerator",condition = "#a0>1",unless = "#p0==2")*/
public Employee getEmp(Integer id){
System.out.println("查询:"+id);
Employee empById = employeeMapper.getEmpById(id);
return empById;
}
//更新的调用
@CachePut(key = "#employee.id",value = "emp")
public Employee updateEmp(Employee employee){
employeeMapper.updateEmp(employee);
return employee;
}
//allEntries默认为fale 若改为true 则删除缓存的时候 会全部和删除
//beforeInvocation 是否在方法之前调用,默认为false,当等于true的时候 即为在方法之前调用
//删除 清空缓存
@CacheEvict(cacheNames = "emp",key = "#id")
public void deleteEmp(Integer id){
System.out.println("DeleteId:"+id);
employeeMapper.deleteEmp(id);
}
//定义复杂缓存规则
/***
* 1.使用 lastName查询数据库将查询的结果放入缓存中
* 2.在使用 id 和 email 查询 同样可以查询到 不需要发送SQL查询数据库,只查询缓存就可以查询到数据
* 3.所以配置的Caching 正确
* @param lastName
* @return
*/
@Caching(
cacheable = {
//根据 lastName查询缓存 如果缓存中没有这条数据记录,将其放入缓存中
@Cacheable(cacheNames="emp",key = "#lastName")
},
put = {
//可以根据id 和 邮箱更新缓存
@CachePut(cacheNames = "emp",key = "#result.id"),
@CachePut(cacheNames="emp",key = "#result.email")
}
)
public Employee getEmoByLastName(String lastName){
Employee employee = employeeMapper.getEmpByLastName(lastName);
return employee;
}
}
package com.nyist.cache.service;
import com.nyist.cache.mapper.DepartmentMapper;
import com.nyist.cache.model.Department;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.stereotype.Service;
//使用缓存管理器
@CacheConfig(cacheManager = "redisCacheManager")
@Service
public class DeptService {
@Autowired
DepartmentMapper departmentMapper;
@Autowired
RedisCacheManager redisCacheManager;
//默认key 为Id
@Cacheable(cacheNames = "dept")
public Department getDept(Integer id){
System.out.println("查询部门:"+id);
Department department = departmentMapper.getDeptById(id);
return department;
}
//编码方式 用来缓存数据
public Department getDeptById(Integer id){
//使用编码的方式 来缓存数据
Department department = null;
Cache dept = redisCacheManager.getCache("dept");
department = departmentMapper.getDeptById(id);
//获取某个缓存
dept.put("dept:1",department);
return department;
}
}
- controller DeptController 和 EmployeeController
package com.nyist.cache.controller;
import com.nyist.cache.model.Department;
import com.nyist.cache.service.DeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DeptController {
@Autowired
DeptService deptService;
//缓存的数据能够保存到Redis
//第二次从缓存中查询不能够被反序列化
@GetMapping("/dept/{id}")
public Department getDeptById(@PathVariable("id") Integer id){
Department dept = deptService.getDept(id);
return dept;
}
@GetMapping("/getDeptById/{id}")
public Department getDept(@PathVariable("id") Integer id){
Department department = deptService.getDeptById(id);
return department;
}
}
package com.nyist.cache.controller;
import com.nyist.cache.model.Employee;
import com.nyist.cache.service.EmployeeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class EmployeeController {
@Autowired
EmployeeService employeeService;
@GetMapping("/emp/{id}")
public Employee getEmp(@PathVariable("id") Integer id){
Employee emp = employeeService.getEmp(id);
return emp;
}
@GetMapping("/emp")
public Employee update(Employee employee){
System.out.println("employee:"+employee);
Employee employee1 = employeeService.updateEmp(employee);
return employee1;
}
@GetMapping("/demp/{id}")
public void deleteEmp(@PathVariable("id") Integer id){
System.out.println("deleteEmp:"+id);
employeeService.deleteEmp(id);
System.out.println("删除成功!!!");
}
@GetMapping("/getEmpByLastName/{lastName}")
public Employee getEmpByLastName(@PathVariable("lastName") String lastName){
Employee emoByLastName = employeeService.getEmoByLastName(lastName);
return emoByLastName;
}
}
- 测试类
package com.nyist.cache;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.JSONSerializer;
import com.nyist.cache.mapper.EmployeeMapper;
import com.nyist.cache.model.Employee;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.jackson.JsonObjectDeserializer;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class Springboot01CacheApplicationTests {
@Autowired
EmployeeMapper employeeMapper;
//操作k-v都是字符串
@Autowired
StringRedisTemplate stringRedisTemplate;
//操作k-v都是对象
@Autowired
RedisTemplate redisTemplate;
@Autowired
RedisTemplate<Object,Employee> empredisTemplate;
/***
* String(字符串)、List(列表)、Set(集合)、Hash(散列)、ZSet(有序集合)
stringRedisTemplate.opsForValue(); 操作字符串
stringRedisTemplate.opsForList(); 操作列表的
stringRedisTemplate.opsForSet(); 操作集合的
stringRedisTemplate.opsForHash(); 操作散列的
stringRedisTemplate.opsForZSet(); 操作有序集合的
*
*/
@Test
public void testRedis(){
//给redis中保存了一个数据
// stringRedisTemplate.opsForValue().append("msg","hello");
String msg = stringRedisTemplate.opsForValue().get("msg");
System.out.println(msg);
System.out.println("\n*****************操列表*******************\n");
stringRedisTemplate.opsForList().leftPush("myList","1");
stringRedisTemplate.opsForList().leftPush("myList","2");
}
//测试保存对象
@Test
public void save(){
//默认如果保存对象,使用jdk序列化机制,序列化后的数据保存在redis中。
//redisTemplate.opsForValue().set("emp01",empById);
//1.将数据库以json的格式保存
//(1)将自己的对象转换为json
//(2)redisTemplats默认的序列化规则;改变默认的序列化规则
Employee empById = employeeMapper.getEmpById(3);
// redisTemplate.opsForValue().set("emp01",empById);
// JSONObject jsonObject = JSONObject.parseObject(JSON.toJSONString(empById));
// redisTemplate.opsForValue().set("emp02",jsonObject.toJSONString());
empredisTemplate.opsForValue().set("emp04",empById);
}
@Test
public void contextLoads() {
Employee empById = employeeMapper.getEmpById(1);
System.out.println(empById);
}
}
- 使用Docker做Redis容器
- 在中央仓库查找redis docker search redis
- 从中央仓库下载到本地 docker pull redis
- 下载好本地镜像 开始制作容器 docker run -d -p 6379:6379 --name myRedis [tag名称]
- 查看启动的Redis docker ps
- 使用Redis Desktop Manager 连接虚拟机中的Docker容器中启动的Redis容器
项目结构图: