redis在web开发中使用的场景很多,其中缓存是其中一个很重要的使用场景,之所以用作缓存,得益于redis的读写数据,尤其是在读取数据的时候是直接走内存的,这样在高并发访问数据的时候,和查询数据库相比,redis读取数据的高效性、快速性的优势可见一斑
- 在看代码前先看看目录结构
- 启动类
@SpringBootApplication
@EnableCaching
public class RedisdemoApplication {
public static void main(String[] args) {
SpringApplication.run(RedisdemoApplication.class, args);
}
}
- application.yml配置
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 123456
url: jdbc:mysql://127.0.0.1:3306/schooldb?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true
#redis配置
redis:
host: 127.0.0.1
password: 123456
port: 6379
jedis:
pool:
max-active: 20
max-idle: 8
min-idle: 0
max-wait: 5000
#mybatis的配置
mybatis:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
mapper-locations: classpath:mapper/*.xml
- 实体类
public class Dept implements Serializable {
private Integer id;
private String dname;
private String loc;
@Override
public String toString() {
return "Dept{" +
"id=" + id +
", dname='" + dname + '\'' +
", loc='" + loc + '\'' +
'}';
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
public String getLoc() {
return loc;
}
public void setLoc(String loc) {
this.loc = loc;
}
}
public class RespBean {
private Integer status;
private String msg;
private Object obj;
public RespBean(Integer status, String msg) {
this.status = status;
this.msg = msg;
}
public static final RespBean DELETE_SUCCESS = new RespBean(200,"删除成功");
public static final RespBean DELETE_ERROR = new RespBean(-1,"删除失败");
public static final RespBean ADD_SUCCESS = new RespBean(200,"添加成功");
public static final RespBean ADD_ERROR = new RespBean(-1,"添加失败");
public static final RespBean UPDATE_SUCCESS = new RespBean(200,"更新成功");
public static final RespBean UPDATE_ERROR = new RespBean(-1,"更新失败");
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Object getObj() {
return obj;
}
public void setObj(Object obj) {
this.obj = obj;
}
private RespBean(Integer status, String msg, Object obj) {
this.status = status;
this.msg = msg;
this.obj = obj;
}
private RespBean() {
}
}
- mapper层
@Mapper
public interface DeptMapper {
Integer addDept(Dept dept);
Integer deleteById(Integer id);
Integer updateDeptById(Dept dept);
Dept findAllDept(Integer id);
}
- service层
public interface DeptService {
Dept addDept(Dept dept);
Integer deleteById(Integer id);
Dept updateDeptById(Dept dept);
Dept findAllDept(Integer id);
}
- serviceimpl层
@Service
public class DeptServiceImpl implements DeptService {
@Autowired
private DeptMapper deptMapper;
@Autowired
private RedisTemplate redisTemplate;
/**
* 添加用户策略:将数据添加到缓存
*/
@Override
public Dept addDept(Dept dept) {
ValueOperations ops = redisTemplate.opsForValue();
Integer d = deptMapper.addDept(dept);
if(d!=0){
String kay="dept:"+dept.getId();
ops.set(kay,dept);
}
return dept;
}
/**
* 删除用户策略:删除数据表中数据,然后删除缓存
*/
@Override
public Integer deleteById(Integer id) {
Integer d = deptMapper.deleteById(id);
if(d!=0){
String kay="dept:"+id;
Boolean hasKey = redisTemplate.hasKey(kay);
if(hasKey){
redisTemplate.delete(kay);
}
}
return d;
}
/**
* 更新用户策略:先更新数据表,成功之后,删除原来的缓存,再更新缓存
*/
@Override
public Dept updateDeptById(Dept dept) {
ValueOperations ops = redisTemplate.opsForValue();
Integer d = deptMapper.updateDeptById(dept);
if(d!=0){
String key = "dept:" + dept.getId();
Boolean hasKey = redisTemplate.hasKey(key);
if(hasKey){
redisTemplate.delete(key);
System.out.println("删除缓存中的key-----> " + key);
// 再将更新后的数据加入缓存
Dept newDept = deptMapper.findAllDept(dept.getId());
if(newDept!=null){
ops.set(key,newDept);
}
}
}
return dept;
}
/**
* 获取用户策略:先从缓存中获取用户,没有则取数据表中 数据,再将数据写入缓存
*/
@Override
public Dept findAllDept(Integer id) {
String key = "dept:" + id;
ValueOperations ops = redisTemplate.opsForValue();
Boolean hasKey = redisTemplate.hasKey(key);
if(hasKey){
Dept dept = (Dept) ops.get(key);
System.out.println("从缓存中获取到的"+dept);
return dept;
}else {
Dept dept = deptMapper.findAllDept(id);
System.out.println("从数据库中获取到的"+dept);
//写入缓存
ops.set(key,dept);
return dept;
}
}
}
- controller
@RestController
@RequestMapping("/dept")
public class DeptController {
@Autowired
private DeptService deptService;
@GetMapping("/{id}")
public Object findAll(@PathVariable Integer id){
Dept allDept = deptService.findAllDept(id);
return allDept;
}
/**
* 删除
* @param id
* @return
*/
@DeleteMapping("/{id}")
public RespBean deleteDept(@PathVariable Integer id){
try {
deptService.deleteById(id);
return RespBean.DELETE_SUCCESS;//删除成功
} catch (Exception e) {
e.printStackTrace();
return RespBean.DELETE_ERROR;//删除失败
}
}
/**
* 添加
* @param dept
* @return
*/
@PostMapping("/")
public RespBean addDept(@RequestBody Dept dept){
try {
deptService.addDept(dept);
return RespBean.ADD_SUCCESS;//添加成功
} catch (Exception e) {
e.printStackTrace();
return RespBean.ADD_ERROR;//添加失败
}
}
/**
* 更新
* @param dept
* @return
*/
@PutMapping("/")
public RespBean updateDept(@RequestBody Dept dept){
try {
deptService.updateDeptById(dept);
return RespBean.UPDATE_SUCCESS;//添加成功
} catch (Exception e) {
e.printStackTrace();
return RespBean.UPDATE_ERROR;//添加失败
}
}
}
- DeptMapper.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="com.song.mapper.DeptMapper">
<insert id="addDept" keyProperty="id" useGeneratedKeys="true" parameterType="com.song.entity.Dept" >
insert into dept(dname,loc)values (#{dname},#{loc})
</insert>
<delete id="deleteById">
delete from dept where id=#{id}
</delete>
<update id="updateDeptById" parameterType="com.song.entity.Dept">
update dept set dname=#{dname},loc=#{loc} where id=#{id}
</update>
<select id="findAllDept" resultType="com.song.entity.Dept" >
select*from dept where id=#{id}
</select>
</mapper>
- 配置redistemplate序列化
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
/**
* 选择redis作为默认缓存工具
* @param redisConnectionFactory
* @return
*/
/*@Bean
//springboot 1.xx
public CacheManager cacheManager(RedisTemplate redisTemplate) {
RedisCacheManager rcm = new RedisCacheManager(redisTemplate);
return rcm;
}*/
@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofHours(1)); // 设置缓存有效期一小时
return RedisCacheManager
.builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory))
.cacheDefaults(redisCacheConfiguration).build();
}
/**
* retemplate相关配置
* @param factory
* @return
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
// 配置连接工厂
template.setConnectionFactory(factory);
//使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)
Jackson2JsonRedisSerializer jacksonSeial = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
// 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jacksonSeial.setObjectMapper(om);
// 值采用json序列化
template.setValueSerializer(jacksonSeial);
//使用StringRedisSerializer来序列化和反序列化redis的key值
template.setKeySerializer(new StringRedisSerializer());
// 设置hash key 和value序列化模式
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(jacksonSeial);
template.afterPropertiesSet();
return template;
}
/**
* 对hash类型的数据操作
*
* @param redisTemplate
* @return
*/
@Bean
public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForHash();
}
/**
* 对redis字符串类型数据操作
*
* @param redisTemplate
* @return
*/
@Bean
public ValueOperations<String, Object> valueOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForValue();
}
/**
* 对链表类型的数据操作
*
* @param redisTemplate
* @return
*/
@Bean
public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForList();
}
/**
* 对无序集合类型的数据操作
*
* @param redisTemplate
* @return
*/
@Bean
public SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForSet();
}
/**
* 对有序集合类型的数据操作
*
* @param redisTemplate
* @return
*/
@Bean
public ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForZSet();
}
}
- 效果图