springboot 用redis做缓存。缓存可以用。可是存对象的时候,只有key,没有值,是?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了springboot 用redis做缓存。缓存可以用。可是存对象的时候,只有key,没有值,是?相关的知识,希望对你有一定的参考价值。
实体类已经序列化了,用redis工具打开,只能看到两个乱码符号。没有看到值,直接测试存数据到redis是,是可以看到以json的格式存的,用缓存存的,就是两个乱码符号,可是能用,能缓存数据。
参考技术A 默认是Jdk序列化,改成json序列化就不是乱码了追问明白,用了,存取都没有问题,就是用redis客户端看。就是两符号。
SpringBoot整合redis缓存
准备工作
1.Linux系统
2.安装redis(也可以安装docker,然后再docker中装redis,本文章就直接用Linux安装redis做演示)
redis下载地址:http://download.redis.io/releases/redis-4.0.14.tar.gz
修改redis,开启远程访问
找到redis中的redis.conf文件并编辑(在安装路径中找到)
vim ./redis.conf
1、找到bind 127.0.0.1并注释掉
默认127.0.0.1只能本地访问,注释掉即可ip访问
2、修改 protected-mode 属性值为no
注释掉并把保护模式禁用以后可以IP访问
3、修改daemonize属性将no 改为yes
将daemonize设置为yes即启动后台运行
4、开放6379端口
/sbin/iptables -I INPUT -p tcp --dport 6379 -j ACCEPT
默认不对外开放6379
5、启动redis
redis-server /myconf/redis.conf
redis-server默认在/usr/local/bin路径下,redis.conf在redis的安装路径下
6、测试连接
redis-cli -h 192.168.126.129 -p 6379
redis-cli -h redis服务器IP -p 6379 -a 密码(没有设置redis密码不要写空,否则报错)
Java代码编写
目录结构
项目源码结构
一个user表
代码
pom.xml文件(可以根据自己的需要来添加或修改)
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- mybatis 与 spring boot 2.x的整合包 --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.2</version> </dependency> <!--mysql JDBC驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.39</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> </dependencies>
下面是springboot的配置文件application.yml,配置redis(里面都有注释解释)
server: port: 8081 #数据库连接 spring: datasource: url: jdbc:mysql://localhost:3306/mytest_springboot_cache?useUnicode=true driver-class-name: com.mysql.jdbc.Driver username: root password: lzh ## Redis 配置 redis: ## Redis数据库索引(默认为0) database: 0 ## Redis服务器地址 host: 192.168.126.129 ## Redis服务器连接端口 port: 6379 ## Redis服务器连接密码(默认为空) password: jedis: pool: ## 连接池最大连接数(使用负值表示没有限制) #spring.redis.pool.max-active=8 max-active: 8 ## 连接池最大阻塞等待时间(使用负值表示没有限制) #spring.redis.pool.max-wait=-1 max-wait: -1 ## 连接池中的最大空闲连接 #spring.redis.pool.max-idle=8 max-idle: 8 ## 连接池中的最小空闲连接 #spring.redis.pool.min-idle=0 min-idle: 0 ## 连接超时时间(毫秒) timeout: 1200 #将themilef的默认缓存禁用,热加载生效 thymeleaf: cache: false #mybatis的下划线转驼峰配置 configuration: map-underscore-to-camel-case: true #另外一种打印语句的方式 log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #打印sql时的语句 logging: level: com: acong: dao: debug file: d:/logs/bsbdj.log
接着是实体类,这个比较简单就不多说了
package com.lzh.springbootstudytest.bean; import java.io.Serializable; /** * @author lzh * create 2019-09-18-22:32 */ public class User implements Serializable private static final long serialVersionUID = 1L; private int uid; private String userName; private String passWord; private int salary; public int getUid() return uid; public void setUid(int uid) this.uid = uid; public String getUserName() return userName; public void setUserName(String userName) this.userName = userName; public String getPassWord() return passWord; public void setPassWord(String passWord) this.passWord = passWord; public int getSalary() return salary; public void setSalary(int salary) this.salary = salary; public User(int uid, String userName, String passWord, int salary) super(); this.uid = uid; this.userName = userName; this.passWord = passWord; this.salary = salary; public User() super();
这是controller类,用于暴露接口访问
package com.lzh.springbootstudytest.controller; import com.lzh.springbootstudytest.bean.User; import com.lzh.springbootstudytest.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; import java.util.HashMap; import java.util.List; import java.util.Map; /** * @author lzh * create 2019-09-18-22:36 */ @RestController public class TestController @Autowired private UserService userService; @RequestMapping("/queryAll") public List<User> queryAll() List<User> lists = userService.queryAll(); return lists; @RequestMapping("/findUserById") public Map<String, Object> findUserById(@RequestParam int id) User user = userService.findUserById(id); Map<String, Object> result = new HashMap<>(); result.put("uid", user.getUid()); result.put("uname", user.getUserName()); result.put("pass", user.getPassWord()); result.put("salary", user.getSalary()); return result; @RequestMapping("/updateUser") public String updateUser() User user = new User(); user.setUid(1); user.setUserName("cat"); user.setPassWord("miaomiao"); user.setSalary(4000); int result = userService.updateUser(user); if(result != 0) return "update user success"; return "fail"; @RequestMapping("/deleteUserById") public String deleteUserById(@RequestParam int id) int result = userService.deleteUserById(id); if(result != 0) return "delete success"; return "delete fail";
接着是Mapper持久层Dao,这里主要用注解写比较方便,也可以使用mybatis的xml配置文件写sql语句
package com.lzh.springbootstudytest.mapper; import com.lzh.springbootstudytest.bean.User; import org.apache.ibatis.annotations.*; import java.util.List; /** * @author lzh * create 2019-09-18-22:32 */ @Mapper public interface UserDao @Select("select * from user") List<User> queryAll(); @Select("select * from user where uid = #id") User findUserById(int id); @Update("UPDATE USER SET username = CASE WHEN (#userName != NULL) AND (#userName != ‘‘) THEN #userName,PASSWORD = CASE WHEN (#passWord != NULL) AND (#passWord != ‘‘) THEN #passWord,salary = CASE WHEN (#salary != 0) THEN #salary WHERE uid = #uid") int updateUser(@Param("user") User user); @Delete("delete from user where uid = #id") int deleteUserById(int id);
service层,这里主要是使用redis模板来写
package com.lzh.springbootstudytest.service; import com.lzh.springbootstudytest.bean.User; import com.lzh.springbootstudytest.mapper.UserDao; 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 java.util.List; import java.util.concurrent.TimeUnit; /** * @author lzh * create 2019-09-18-22:33 */ @Service public class UserService @Autowired private UserDao userDao; @Autowired private RedisTemplate redisTemplate; public List<User> queryAll() return userDao.queryAll(); /** * 获取用户策略:先从缓存中获取用户,没有则取数据表中 数据,再将数据写入缓存 */ public User findUserById(int id) String key = "user_" + id; ValueOperations<String, User> operations = redisTemplate.opsForValue(); //判断redis中是否有键为key的缓存 boolean hasKey = redisTemplate.hasKey(key); if (hasKey) User user = operations.get(key); System.out.println("从缓存中获得数据:"+user.getUserName()); System.out.println("------------------------------------"); return user; else User user = userDao.findUserById(id); System.out.println("查询数据库获得数据:"+user.getUserName()); System.out.println("------------------------------------"); // 写入缓存 operations.set(key, user, 5, TimeUnit.HOURS); return user; /** * 更新用户策略:先更新数据表,成功之后,删除原来的缓存,再更新缓存 */ public int updateUser(User user) ValueOperations<String, User> operations = redisTemplate.opsForValue(); int result = userDao.updateUser(user); if (result != 0) String key = "user_" + user.getUid(); boolean haskey = redisTemplate.hasKey(key); if (haskey) redisTemplate.delete(key); System.out.println("删除缓存中的key-----------> " + key); // 再将更新后的数据加入缓存 User userNew = userDao.findUserById(user.getUid()); if (userNew != null) operations.set(key, userNew, 3, TimeUnit.HOURS); return result; /** * 删除用户策略:删除数据表中数据,然后删除缓存 */ public int deleteUserById(int id) int result = userDao.deleteUserById(id); String key = "user_" + id; if (result != 0) boolean hasKey = redisTemplate.hasKey(key); if (hasKey) redisTemplate.delete(key); System.out.println("删除了缓存中的key:" + key); return result;
这里主要是使用RedisTemplate来对远程redis操作,每次访问controller暴露的接口,首先判断redis缓存中是否存在该数据,若不存在就从数据库中读取数据,然后保存到redis缓存中,当下次访问的时候,就直接从缓存中取出来。这样就不用每次都执行sql语句,能够提高访问速度。 但是在保存数据到缓存中,通过设置键和值和超时删除,注意设置超时删除缓存时间不要太长,否则会给服务器带来压力。
执行spring boot的启动类,访问http://localhost:8081/findUserById?id=1
再次访问http://localhost:8081/findUserById?id=1就是从缓存中获取保存的数据
以上是关于springboot 用redis做缓存。缓存可以用。可是存对象的时候,只有key,没有值,是?的主要内容,如果未能解决你的问题,请参考以下文章
2022-03-12 SpringBoot 使用redis做缓存,设置失效时间以及序列化
Springboot学习SpringBoot集成Shiro前后端分离使用redis做缓存个人博客搭建