SpringBoot使用Redis和MyBatis完成缓存数据的增删改查

1.在Spring Boot中集成Redis

1)添加依赖
pom.xml
添加的依赖包含Redis,Mysql,MyBatis,fastjson,junit

		<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.47</version>
		</dependency>

		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>2.0.0</version>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>

2)配置application.properties

application.properties
配置mysql,redis服务器



spring.datasource.url=jdbc:mysql://127.0.0.1/book?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=true
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.properties.hibernate.hbm2ddl.auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.show-sql= true

spring.datasource.initialization-mode=always
spring.datasource.schema=classpath:db/schema.sql


# Redis数据库索引(默认为0)
spring.redis.database=1
# Redis服务器地址
spring.redis.host=127.0.0.1
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=

# 连接池最大连接数(使用负值表示没有限制)
spring.redis.jedis.pool.max-active=8


# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.jedis.pool.max-wait=-1


# 连接池中的最大空闲连接
spring.redis.jedis.pool.max-idle=8


# 连接池中的最小空闲连接
spring.redis.jedis.pool.min-idle=0

# 连接超时时间(毫秒)
spring.redis.timeout=5000

3)在入口类加上@EnableCaching注解,开启缓存支持

RedisDemoApplication.java

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;

@SpringBootApplication
@EnableCaching
public class RedisDemoApplication {

	public static void main(String[] args) {
		SpringApplication.run(RedisDemoApplication.class, args);
	}

}

4)建立下面的项目结构
在这里插入图片描述

2.配置Redis类

要想启动Spring缓存支持,需要创建一个CacheManager的Bean。

RedisConfig.java

package com.example.demo.config;

import  com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import  org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.lang.reflect.Method;

@Configuration

public class RedisConfig extends  CachingConfigurerSupport{
    @Bean
    public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
            @Override
            public Object generate(Object target, Method method, Object... params) {
                StringBuilder sb = new StringBuilder();
                sb.append(target.getClass().getName());
                sb.append(method.getName());
                for (Object obj : params) {
                    sb.append(obj.toString());
                }
                return sb.toString();
            }
        };
    }

    @SuppressWarnings("rawtypes")
    @Bean
    //缓存管理器

    public CacheManager cacheManager(RedisConnectionFactory connectionFactory) {
        RedisCacheManager cacheManager = RedisCacheManager.create(connectionFactory);
        //设置缓存过期时间

        return cacheManager;
    }

    @Bean
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
        //配置连接工厂
        StringRedisTemplate template = new StringRedisTemplate(factory);

        //使用Jackson2JsonRedisSerializer来序列化和反序列化redis 的value值
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();

        //指定要序列化的域,field,get和set,以及修饰符范围
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        //om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);

        //指定序列化输入的类型,类必须是非final类
        om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance ,
                ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
        jackson2JsonRedisSerializer.setObjectMapper(om);

        //序列化配置为String格式
        template.setValueSerializer(new StringRedisSerializer());

        //
        template.setKeySerializer(new StringRedisSerializer());
        template.afterPropertiesSet();
        return template;
    }

}


关于Redis Template中序列化和反序列化配置的解释

关于数据的“序列化/反序列化”,提供了多种可选择策略(RedisSerializer)

序列化/发序列化 解释
JdkSerializationRedisSerializer POJO对象的存取场景,使用JDK本身序列化机制,将pojo类通过ObjectInputStream/ObjectOutputStream进行序列化操作,最终redis-server中将存储字节序列。
StringRedisSerializer 适用于Key或者value为字符串的场景,根据指定的charset对数据的字节序列编码成string
JacksonJsonRedisSerializer 提供了javabean与json之间的转换能力,可以将pojo实例序列化成json格式存储在redis中,也可以将json格式的数据转换成pojo实例。
OxmSerializer 提供了将javabean与xml之间的转换能力,目前可用的三方支持包括jaxb,apache-xmlbeans;redis存储的数据将是xml工具。

上面4种策略中:

JdkSerializationRedisSerializerStringRedisSerializer是最基础的策略,在设计时仍然不推荐直接使用后面两种,即JacksonJsonRedisSerializerOxmSerializer,因为无论是json还是xml,他们本身仍然是String。

如果数据需要被第三方工具解析,那么数据应该使用StringRedisSerializer而不是JdkSerializationRedisSerializer

如果数据格式必须为json或者xml,那么在编程级别,在redisTemplate配置中仍然使用StringRedisSerializer,在存储之前或者读取之后,使用“SerializationUtils”工具转换转换成json或者xml

3.创建测试实体类

User.java

package com.example.demo.model;

import lombok.Data;

import java.io.Serializable;

@Data
public class User implements Serializable {
    private  String id;
    private  String name;
    private int age;
}

这里需要注意的是spring boot在启动时会自动创建user表
在项目的resources目录下新建db目录,并添加schema.sql文件,写入创建user表的sql语句
当然还需要配置数据库连接,并加上数据表初始化的配置(配置工作前面的文件中已经包含)
这里是schema.sql

DROP TABLE IF EXISTS user;
--IF object_id('user','U') is not NULL drop table 'user';
CREATE TABLE user(
    id int(11) NOT NULL AUTO_INCREMENT,
    name varchar(255) DEFAULT NULL,
    age int(11) DEFAULT NULL,
    PRIMARY KEY (id)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

4.实现实体和数据表的映射关系

UserMapper.java

package com.example.demo.mapper;

import com.example.demo.model.User;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import  org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import  org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import org.springframework.stereotype.Repository;

@Repository
@Mapper
public interface UserMapper {
    @Insert("insert into user(name,age) values(#{name},#{age})")
    int addUser(@Param("name")String name,@Param("age")String age);

    @Select("select * from user where id=#{id}")
    User findById(@Param("id")String id);
    @Update("update user set name=#{name},age=#{age} where id=#{id}")
    int updateById(User user);

    @Delete("delete from user where id=#{id}")
    void deleteById(@Param("id")String id);
}


5.创建Redis缓存服务器

创建Redis缓存服务器,即缓存在服务器层面
UserService.java

代码解释
@Cacheable:将查询结果缓存到Redis中
key="#p0":指定传入的第一个参数作为Redis的key
@CachePut:指定key,将更新的结果同步到Redis中
@CacheEvict:指定key,删除缓存数据
allEntries:方法调用后将立即清除缓存

package com.example.demo.service;

import com.example.demo.model.User;
import com.example.demo.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

//Redis缓存服务层
@Service
@CacheConfig(cacheNames = "users")
public class UserService {
    @Autowired
    UserMapper userMapper;
    @Cacheable(key="#p0")
    public User selectUser(String id){
        System.out.println("select");
        return userMapper.findById(id);
    }

    @CachePut(key="#p0")
    public  void updateById(User user){
        System.out.println("uddate");
        userMapper.updateById(user);
    }
    //如果allEntries指定为true,则调用CacheEvict方法后将立即清空所有缓存

    @CacheEvict(key="#p0",allEntries = true)
    public void deleteById(String id){
        System.out.println("delete");
        userMapper.deleteById(id);
    }
}

6.完成增删改查测试API

RedisController.java

package com.example.demo.controller;
import com.example.demo.service.UserService;
import com.example.demo.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;


@RestController
@RequestMapping("/user")
public class RedisController {
    @Autowired
    UserService userService;

    @RequestMapping("/{id}")
    public User ForTest(@PathVariable String id){
        return userService.selectUser(id);
    }

    @RequestMapping( "/update/")
    public String update(User user){

        userService.updateById(user);
        return "success";
    }


    @RequestMapping( "/delete/{id}")
    public String delete (@PathVariable String id){
        userService.deleteById(id);
        return "delete success";
    }

}

7.启动测试

1)启动Redis服务
由于没有设置环境变量,需要手动进入到Redis安装目录cd /d D:\Redis-x64-3.2.100,然后启动服务

redis-server.exe redis.windows.conf

在cmd窗口打开的情况下,运行项目
在这里插入图片描述
2)多次访问

http://localhost:8080/user/2

第一次时控制台会出现select信息,代表对数据库进行了查询操作。后面再访问则不会出现提示,表示没有对数据库执行操作,而是使用Redis中的缓存数据。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章