SpringBootのRedis

 

 

 

 

 

什么是Redis?http://www.redis.cn/

Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。 Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。

 

docker中安装redis

docker pull redis

 

运行redis

docker run  -d -p 6379:6379 --name myredis redis 

redis的端口号为6379,

如果之前启动过redis,可以通过docker start id进行启动

扫描二维码关注公众号,回复: 11218886 查看本文章

 

 

在springbot中如何应用Redis

1.引入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2.yml配置redis访问路径

spring:
  datasource:
    # 配置监控服务器
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      #   druid 数据源其他配置 当添加了如下配置,我们需要在程序中增加configuration配置来将这些配置映射到系统默认配置参数上去。
      driver-class-name: com.mysql.cj.jdbc.Driver
      username: root
      password: root
      url: jdbc:mysql://192.168.100.158:3306/spring_cache?characterEncoding=utf-8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&useSSL=false
      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'用于防火墙
      filter:
        config:
          enabled: true
        stat:
          enabled: true
          db-type: mysql
        wall:
          enabled: true
          db-type: mysql
      maxPoolPreparedStatementPerConnectionSize: 20
      useGlobalDataSourceStat: true
      connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
      stat-view-servlet:
        login-username: admin
        login-password: admin
        reset-enable: false
        url-pattern: /druid/*
      web-stat-filter:
        url-pattern: /*
        exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"
  redis:
    host: 192.168.100.158
mybatis:
  configuration:
    # 开启驼峰命名法
    map-underscore-to-camel-case: true
logging:
  level:
    # 设置包下日志输出级别
   com.seegot.mapper: debug
debug: true

3.创建数据库spring_cache

/*
Navicat MySQL Data Transfer
​
Source Server         : vm
Source Server Version : 50729
Source Host           : 192.168.100.158:3306
Source Database       : spring_cache
​
Target Server Type    : MYSQL
Target Server Version : 50729
File Encoding         : 65001
​
Date: 2020-05-18 13:48:39
*/SET FOREIGN_KEY_CHECKS=0;
​
-- ----------------------------
-- Table structure for department
-- ----------------------------
DROP TABLE IF EXISTS `department`;
CREATE TABLE `department` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `departmentName` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
​
-- ----------------------------
-- Records of department
-- ----------------------------
INSERT INTO `department` VALUES ('1', '研发部');
INSERT INTO `department` VALUES ('2', '测试部');
INSERT INTO `department` VALUES ('3', '财务部');
​
-- ----------------------------
-- Table structure for employee
-- ----------------------------
DROP TABLE IF EXISTS `employee`;
CREATE TABLE `employee` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `lastName` varchar(255) DEFAULT NULL,
  `email` varchar(255) DEFAULT NULL,
  `gender` int(2) DEFAULT NULL,
  `d_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
​
-- ----------------------------
-- Records of employee
-- ----------------------------
INSERT INTO `employee` VALUES ('1', 'Tom', '1', '0', '1');
INSERT INTO `employee` VALUES ('2', 'Jerry', '[email protected]', '2', '2');
​

4.创建bean

Department部门 和 Employee员工

package com.seegot.bean;
​
import lombok.Data;
​
/**
 * @program: spring-boot-01-cache
 * @description:
 * @author: PP Zhang
 * @create: 2020-04-27 10:46
 */
@Data
public class Department {
    private Integer id;
    private String departmentName;
}
package com.seegot.bean;
​
import lombok.Data;
​
import java.io.Serializable;
​
/**
 * @program: spring-boot-01-cache
 * @description:
 * @author: PP Zhang
 * @create: 2020-04-27 10:47
 */
@Data
public class Employee  {
    private Integer id;
    private String lastName;
    private String email;
    private Integer gender;
    private Integer dId;
}

5.创建mapper

package com.seegot.mapper;
​
import com.seegot.bean.Department;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
​
/**
 * @program: spring-boot-01-cache
 * @description:
 * @author: PP Zhang
 * @create: 2020-04-27 11:06
 */
@Mapper
public interface DepartmentMapper {
    @Select("select * from department where id = #{id}")
    Department getDeptById(Integer id);
}
package com.seegot.mapper;
​
import com.seegot.bean.Employee;
import org.apache.ibatis.annotations.*;
​
/**
 * @program: spring-boot-01-cache
 * @description:
 * @author: PP Zhang
 * @create: 2020-04-27 11:06
 */
@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},d_id=#{dId} where id=#{id}")
    public void updateEmp(Employee emp);
    @Delete("delete from employee where id=#{id}")
    public void deleteEmpById(Integer id);
    @Insert("insert into employee(lastName,email,gender,d_id) values (#{lastName}),#{email},#{gender},#{dId}")
    public  void insertEmp(Employee emp);
    @Select("select * from employee where lastName = #{name}")
    public Employee getEmpName(String name);
}

6.创建service

package com.seegot.service;
​
import com.seegot.bean.Department;
import com.seegot.mapper.DepartmentMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
​
/**
 * @program: spring-boot-01-cache
 * @description:
 * @author: PP Zhang
 * @create: 2020-05-18 10:37
 */
@Service
public class DeptService {
    @Autowired
    DepartmentMapper departmentMapper;
    @Cacheable(cacheNames = "dept")
    public Department getDeptById(Integer id){
        System.out.println("查询部门:"+id);
        Department dept =  departmentMapper.getDeptById(id);
        return  dept;
    }
}
package com.seegot.service;
​
import com.seegot.bean.Employee;
import com.seegot.mapper.EmployeeMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.*;
import org.springframework.stereotype.Service;
​
/**
 * @program: spring-boot-01-cache
 * @description:
 * @author: PP Zhang
 * @create: 2020-04-27 11:15
 */
@CacheConfig(cacheNames = "emp") // 抽取公共的缓存部分,
@Service
public class EmployeeService {
    @Autowired
    EmployeeMapper employeeMapper;
    /**
    * @Description:
     *      将方法运行的结果进行缓存,以后再要相同的数据,直接从缓存中获取,不用调用方法去数据库查询。
     *  CacheManager管理多个Cache组件的,对缓存真正的CRUD操作在Cache组件中,每个缓存组件有自己唯一的名字;
     * @Cacheable几个属性:(key-value)
     *      cacheNames/values:指定缓存组件的名字。讲方法的反馈结果放在哪个缓存中,而且可以使数组的方式,可以指定多个缓存
     *      key:缓存数据时用的key;可以用它来指定,如果不指定Key默认是使用方法参数的值;
     *          编写SpEL:
     *              #id 是参数id的值。
     *      keyGenerator:key的生成器,可以自定义key的生成器组件id
     *      指定了Key 就不要再指定keyGenerator 二选一
     *      cacheManager:指定缓存管理器;或者cacheResolver指定获取解析器
     *      condition:指定符合条件的情况下才会缓存。@Cacheable(cacheNames = "emp",condition = "#id>0")
     *      unless:否定缓存,当unless指定的条件为true,方法返回值就不被缓存。可以获取到结果进行判断。unless = "#result==null
     *      sync:是否开启异步模式
     *
     *  原理:
     *      1.自动配置类:CacheAutoConfiguration
     *      2.缓存配置类
     *
     *      3.哪些配置类生效?
     *          SimpleCacheConfiguration
     *
     *   运行流程:
     * @Cacheable
     *      1.方法运行之前,先去查询Cache(缓存组件),按照cacheNames指定的名字获取;
     *      (CacheManager先获取相应的缓存),第一次获取缓存,如果没有Cache组件会自动创建,
     *      2.去Cache中查找缓存的内容,按使用一个Key,默认就是方法的参数;
     *        key是按照某种策略生成的。默认是使用keyGenerator生成的,默认使用SimpleKeyGenerator生成。
     *        SimpleKeyGenerator生成Key的默认策略:
     *          如果没有参数;key=new SimpleKey();
     *          如果有一个参数:key=参数的值()
     *          如果有多个参数:key=new SimpleKey(params);
     *      3.没有查到缓存就调用目标方法;
     *      4.将目标方法返回的结果,放进缓存中
     *
     *       @Cacheable标注的方法执行之前下来检查缓存中有没有这个数据,默认按照参数的值作为key去查询缓存,
     *       如果没有就运行方法并将结果放到缓存;以后在来调用,就可以直接使用缓存中的数据;
     *
     *
     *       核心:
     *          1)使用CacheManager【ConcurrentMapCacheManager】按照名字得到Cache【ConcurrentMapCache】组件
     *          2)key使用keyGenerator生成的,默认是SimpleKeyGenerator生成的。
    * @Param:
    * @return:
    * @Author: PP Zhang
    * @Date: 2020/4/27
    */
    // @Cacheable(value="emp",keyGenerator=myKeyGenerator)
    //  @Cacheable(cacheNames = "emp",key = "#root.methodName+'['+#id+']'",condition = "#a0>1 and #root.nethodName eq['aaa']")
    //   @Cacheable(cacheNames = "emp",key = "#id") 当不在类上进行@CacheConfig()的时候,用它
    @Cacheable(/*cacheNames = "emp",*/key = "#id")
    public Employee getEmp(Integer id){
        System.out.println("查询"+id+"号的员工信息");
        Employee employee = employeeMapper.getEmpById(id);
        return  employee;
    }
    /**
     * @CachePut:即调用方法,又更新缓存数据;
     * 修改了数据库的某个数据,同时更新缓存;
     * 运行时机:
     *  1.先调用目标方法
     *  2.将目标方法结果缓存起来
     *
     * 测试步骤:
     *  1.查询1号员工;查到的结果会放到缓存中。
     *  key:1  value:lastName:Lilei
     *  2.以后查询还是之前的结果。
     *  3.更新1号员工信息。【lastName:zhangsan;gender=1】
     *      使用 @CachePut(value = "emp") 其实也将该条结果存入了缓存,
     *      由于没有指定缓存名称,所以默认是参数也就是 employee
     *      key:employee  value:返回的employee对象。
     *      @Cacheable是不可能用#result的。
     *  4.查询1号员工
     *     应该是更新的员工
     *     key = "#employee.id" 使用传入的参数员工id;
     *     key="#result.id" 是返回后的Id
     *
     *     为什么是没有更新前的?
     * */
    @CachePut(/*value = "emp",*/key = "#result.id")
    public  Employee updateEmp(Employee employee){
        System.out.println("updateEmp"+employee);
        employeeMapper.updateEmp(employee);
        return  employee;
    }
    /**
     * @CacheEvict:清除缓存
     * key 指定要清除的Key
     *
     * allEntries = true 删除指定缓存中的所有数据
     *
     * beforeInvocation = false 缓存的清除是否在方法之前执行?
     *  默认缓存清除是在方法执行之后执行的,如果方法出现异常,缓存就不会被清除。
     *
     *  beforeInvocation = true
     *   代表清除缓存操作是在方法运行之前执行的,无论方法是否出现异常,缓存都被清除。
     * */
    @CacheEvict(/*value = "emp",*//*key = "#id",*//*allEntries = true*/beforeInvocation = true)
    public  void deleteEmp(Integer id){
        System.out.println("deleteEmp"+id);
        // employeeMapper.deleteEmpById(id);
        int i = 10/0;
    }
​
    // 定义复杂的注解
    @Caching(
            cacheable = {
                    @Cacheable(/*value="emp",*/key = "#name")
            },
            put = {
                    @CachePut(/*value="emp",*/key = "#result.id"),
                    @CachePut(/*value = "emp",*/key = "#result.email")
            }
    )
    public  Employee getEmpByName(String name){
        Employee employee = employeeMapper.getEmpName(name);
        return  employee;
    }
}

7.创建config

package com.seegot.config;
​
import com.fasterxml.jackson.annotation.JsonAutoDetect;
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.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
​
/**
 * @program: spring-boot-01-cache
 * @description:
 * @author: PP Zhang
 * @create: 2020-05-15 13:56
 */
@Configuration
public class MyRedisConfig { 
​
    @Bean
    public RedisTemplate<String,Object>redisTemplate(RedisConnectionFactory redisConnectionFactory){
        RedisTemplate<String,Object>template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(valueSerializer());
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(valueSerializer());
        return  template;
    }
    @Bean
    public RedisCacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory){
        RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory);
        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer()));
        redisCacheConfiguration.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()));
        return new RedisCacheManager(redisCacheWriter, redisCacheConfiguration);
    }
    private RedisSerializer<Object> valueSerializer() {
        Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<Object>(Object.class);
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        // objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        //因为上面那句代码已经被标记成作废,因此用下面这个方法代替,仅仅测试了一下,不知道是否完全正确
        objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,ObjectMapper.DefaultTyping.NON_FINAL);
        serializer.setObjectMapper(objectMapper);
        return serializer;
    }
}
 

猜你喜欢

转载自www.cnblogs.com/pengpengzhang/p/12910180.html
今日推荐