前言
一、导入依赖
<!-- redis依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
二、本地打开redis服务端,并在项目中配置
进入redis目录,打开redis服务端,注意不要关掉这个dos窗口
在springboot的application.properties
中配置
#Redis配置
redis.host=localhost
## Redis服务器连接端口
redis.port=6379
# 连接超时时间(毫秒)
redis.timeout=1000
## Redis服务器连接密码(默认为空)
redis.password="这里写你的密码"
# 连接池中的最大连接数
redis.poolMaxTotal=10
# 连接池中的最大空闲连接
redis.poolMaxIdle=10
# 连接池最大阻塞等待时间(使用负值表示没有限制)
redis.poolMaxWait=3
三、在项目进行测试
1. 打开测试文件
2. 完成我们对redis的第一条数据写入
Redis默认提供了StringRedisTemplate
和RedisTemplate
他们都是用于操作redis数据库的,区别在于:
StringRedisTemplate
是RedisTemplate
的一个实现,前者适用于键值对都是字符串的情况,后者适用于键值对都是对象类型的。
跑一下之后,可以查看是否被写入到了redis中。
@Autowired
StringRedisTemplate stringRedisTemplate; //操作kv都是字符串
@Autowired
RedisTemplate redisTemplate;// kv都是对象的
@Test
public void test() {
// 保存字符串
stringRedisTemplate.opsForValue().append("message","hello");
}
使用redis manager软件连接上我们的redis服务器,看看有没有刚才保存的这条数据。
可以看到我们的redis数据库中已经有了这条数据了。
redis有基本的数据类型,例如string
(字符串),hash
(哈希),list(列表),set
(集合)及zset
(sorted set:有序集合)等等,这里不再介绍。
三、将对象存入redis数据库
我们需要考虑的是:在项目中,我们往往需要将一个对象的信息保存到redis数据库中,以便利用redis的速度。
以用户为例,我们先编写一个用户类。
public class User implements Serializable {
private Integer id;
private String username;
public Date getBirthday() {
return birthday;
}
private Date birthday;
private String password;
private int age;
private String sex;
private String phone;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
需要注意的是,上面我们编写的用户类实现了Serializable
,以便实现序列化。
下面我们new一个对象并将其存储到redis数据库当中
@Test
public void test01() {
User user=new User();
user.setUsername("wyh");
user.setPassword("pwd");
user.setId(1);
// 保存字符串
redisTemplate.opsForValue().set("user",user);
}
可以看到确实是存进来了,但是很明显并不是我们想要的格式,我们想要的是像json那种,很直观的用户信息。
四、解决“乱码的问题”
解决这个问题的方法就是编写一个redis配置类,自定义redisTemplate来进行存放用户对象的操作。
@Configuration
public class redisConfig {
@Bean
@ConditionalOnMissingBean(
name = {"userRedisTemplate"}
)
public RedisTemplate<Object, User> userRedisTemplate
(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
RedisTemplate<Object, User> template = new RedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
Jackson2JsonRedisSerializer<User> jackson2JsonRedisSerializer=new Jackson2JsonRedisSerializer<User>(User.class);
template.setDefaultSerializer(jackson2JsonRedisSerializer);//附加内容
return template;
}
}
在上面配置类中,我们注意template.setDefaultSerializer(jackson2JsonRedisSerializer);
,这一步是实际上是为redistemplate
指定了一个jackson
的序列化器,而之前出现"乱码"的原因其实就是redistemplate
默认使用的是jdk的序列化器。
并且最终将usertemplate
交给spring来管理,以便解耦。
自动注入userRedisTemplate
并且让我们测试一下。
@Autowired
RedisTemplate<Object,User> userRedisTemplate;
@Test
public void test01() {
User user=new User();
user.setUsername("wyh");
user.setPassword("pwd");
user.setId(1);
// 保存字符串
userRedisTemplate.opsForValue().set("user",user);
}
可以看到redis存放的用户对象是以一个json的形式存储了起来。
五、以登录为例测试redis在项目中的应用
我们本次测试的实现思想是:首先查redis,如果redis中没有,便去数据库中查找,并且将查到的数据存储到数据库中。
编写返回对象。
public class RespBean {
private Integer status;
private String msg;
private Object obj;
private RespBean() {
}
public static RespBean build() {
return new RespBean();
}
public static RespBean ok(String msg, Object obj) {
return new RespBean(200, msg, obj);
}
public static RespBean ok(String msg) {
return new RespBean(200, msg, null);
}
public static RespBean error(String msg, Object obj) {
return new RespBean(500, msg, obj);
}
public static RespBean error(String msg) {
return new RespBean(500, msg, null);
}
private RespBean(Integer status, String msg, Object obj) {
this.status = status;
this.msg = msg;
this.obj = obj;
}
public Integer getStatus() {
return status;
}
public RespBean setStatus(Integer status) {
this.status = status;
return this;
}
public String getMsg() {
return msg;
}
public RespBean setMsg(String msg) {
this.msg = msg;
return this;
}
public Object getObj() {
return obj;
}
public RespBean setObj(Object obj) {
this.obj = obj;
return this;
}
}
编写userController,这里使用了mybatis
@Controller
@RequestMapping("/User")
public class UserController {
Logger logger=LoggerFactory.getLogger(getClass());
@Autowired
public UserService userService;
@Autowired
public RedisTemplate<Object,User> userRedisTemplate;
@RequestMapping(value="/login" )
@ResponseBody
public RespBean login(HttpServletRequest httpServletRequest) {
String username=httpServletRequest.getParameter("username");
String pwd=httpServletRequest.getParameter("password");
User user=null;
user=userRedisTemplate.opsForValue().get(username);
if(user==null)
{
user=userService.findUserByName(username);
userRedisTemplate.opsForValue().set(username.toString(),user);
logger.info("从数据库中查询用户...");
}
if(user==null)
{
logger.info("进行了查询,结果为空");
return RespBean.error("error");
}else
{
if(user.getPassword().equals(pwd))
{
logger.info("用户登录成功");
return RespBean.ok("success");
}
else
{
return RespBean.error("error");
}
}
}
}
如果redis中不存在,则去mysql数据库中查找,并将查找到的用户信息以用户名-用户对象的形式保存在redis中。
第一次登录测试,可以看到会去数据库中查找该用户信息。
再次登录,可以看到不再去mysql中查找用户信息,可以直接进行判断。
六、使用RedisCallback和SessionCallback接口
RedisCallback和SessionCallback接口主要是为了解决多个命令使用多条连接的问题,而多条命令我们其实是可以使用一个连接来实现的。
SessionCallback接口(推荐使用)
@Test
public void testRedis() {
redisTemplate.execute(new SessionCallback() {
@Override
public Object execute(RedisOperations redisOperations) throws DataAccessException {
redisOperations.opsForValue().set("w", "wu");
redisOperations.opsForValue().set("w1", "wu1");
return null;
}
});
}
RedisCallback接口(当需要进行底层的修改时使用)
@Test
public void testRedisRedisCallback() {
redisTemplate.execute(new RedisCallback() {
@Override
public Object doInRedis(RedisConnection redisConnection) throws DataAccessException {
redisConnection.set("w".getBytes(), "wu".getBytes());
redisConnection.set("w1".getBytes(), "wu1".getBytes());
return null;
}
});
}