Springboot Redis

Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。从2010年3月15日起,Redis的开发工作由VMware主持。从2013年5月开始,Redis的开发由Pivotal赞助。
项目源码免费下载地址:https://download.csdn.net/download/HumorChen99/15834374

  • 创建项目

    使用idea的spring initializer来创建一个项目,maven依赖如下

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.1.3.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>com.example</groupId>
        <artifactId>springboot_redis_demo</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>springboot_redis_demo</name>
        <description>Demo project for Spring Boot</description>
    
        <properties>
            <java.version>1.8</java.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <optional>true</optional>
            </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-devtools</artifactId>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.2.47</version>
            </dependency>
        </dependencies>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    
    
注解方式的
  • 项目结构

在这里插入图片描述

  • 配置application.yml

    server:
      port: 80
    spring:
      redis:
        #数据库索引
        database: 1
        host: 192.168.0.198
        port: 6379
        #密码有就填没有就不要写
        password: 123456
        jedis:
          pool:
            max-active: 8
            max-wait: -1ms
            max-idle: 8
            min-idle: 0
        timeout: 3s
    
  • 配置类

    • 键生成器(你也可以自己指定键,也可指定键生成器去生成)

      package com.example.springboot_redis_demo.config;
      
      import org.springframework.cache.interceptor.KeyGenerator;
      import org.springframework.context.annotation.Bean;
      import org.springframework.context.annotation.Configuration;
      
      import java.lang.reflect.Method;
      
      /**
       * 注解自动缓存所需键生成器
       */
      @Configuration
      public class MyKeyGenerator {
      
          @Bean(name = "keyGenerator")
          public KeyGenerator myKeyGenerator(){
              return new KeyGenerator() {
                  @Override
                  public Object generate(Object o, Method method, Object... objects) {
      
                      String id=o.getClass().getName()+"."+method.getName();
                      if (objects.length>0){
                          for(Object obj:objects){
                              id+="."+obj.toString();
                              break;
                          }
                      }
                      System.err.println(id);
                      return id;
                  }
              };
          }
      }
      
    • Redis配置类

      package com.example.springboot_redis_demo.config;
      
      import com.example.springboot_redis_demo.serializer.FastJson2JsonRedisSerializer;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.cache.CacheManager;
      import org.springframework.cache.annotation.CachingConfigurerSupport;
      import org.springframework.cache.annotation.EnableCaching;
      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.connection.RedisConnectionFactory;
      import org.springframework.data.redis.core.RedisTemplate;
      import org.springframework.data.redis.serializer.RedisSerializationContext;
      import org.springframework.data.redis.serializer.RedisSerializer;
      import org.springframework.data.redis.serializer.StringRedisSerializer;
      
      /**
       * 注解自动缓存所需配置
       */
      @Configuration
      public class RedisConfig {
          @Autowired
          private FastJson2JsonRedisSerializer fastJson2JsonRedisSerializer;
          @Bean
          public CacheManager cacheManager(RedisConnectionFactory factory) {
              RedisSerializer<String> redisSerializer = new StringRedisSerializer();
      
              // 配置序列化
              RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                      .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
                      .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(fastJson2JsonRedisSerializer));
              RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
                      .cacheDefaults(config)
                      .build();
              return cacheManager;
          }
      }
      
  • 序列化器(查询结果存入redis需要被序列化为文本,采用FastJSON)

    package com.example.springboot_redis_demo.serializer;
    
    import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.parser.ParserConfig;
    import com.alibaba.fastjson.serializer.SerializerFeature;
    import org.springframework.data.redis.serializer.RedisSerializer;
    import org.springframework.data.redis.serializer.SerializationException;
    import org.springframework.stereotype.Component;
    
    import java.nio.charset.Charset;
    
    /**
     * @Author:humorchen
     * @Date 2020/11/8 13:32
     */
    @Component
    public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T> {
    
        public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
        static {
            //由于fastjson有autotype检查,将自己的包前缀加进去防止反序列化失败
            ParserConfig.getGlobalInstance().addAccept("com");
        }
    
        private Class<T> clazz;
        public FastJson2JsonRedisSerializer() {
            this((Class<T>) Object.class);
        }
        public FastJson2JsonRedisSerializer(Class<T> clazz) {
            super();
            this.clazz = clazz;
        }
    
        @Override
        public byte[] serialize(T t) throws SerializationException {
            if (t == null) {
                return new byte[0];
            }
    
            return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
        }
    
        @Override
        public T deserialize(byte[] bytes) throws SerializationException {
            if (bytes == null || bytes.length <= 0) {
                return null;
            }
            String str = new String(bytes, DEFAULT_CHARSET);
    
            return (T) JSON.parseObject(str, clazz);
        }
    
    }
    
    
  • 测试用的接口Controller

    package com.example.springboot_redis_demo.controller;
    
    import org.springframework.cache.annotation.CacheEvict;
    import org.springframework.cache.annotation.CachePut;
    import org.springframework.cache.annotation.Cacheable;
    import org.springframework.web.bind.annotation.DeleteMapping;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PutMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    /**
     * 注解自动缓存测试
     * key可以通过keyGenerator生成也可以直接指定key
     */
    @RestController
    public class TestController {
        private static final  String cacheName="TestController";
        private static final  String keyGenerator="keyGenerator";
    
        /**
         * 开启缓存(缓存一次后参数相同不再执行方法直接返回缓存内容)
         */
        @Cacheable(cacheNames =cacheName,key ="#id")
        @GetMapping("/query")
        public String query(int id){
            return "Cacheable";
        }
    
        /**
         * 清除缓存(需要键相同,才能清除)
         * @return
         */
        @CacheEvict(cacheNames =cacheName,key = "#id")
        @DeleteMapping("/delete")
        public String delete(int id){
            return "CacheEvict";
        }
    
        /**
         * 开启缓存(每次缓存且每次执行方法将结果缓存)
         * 清除这个的缓存也需要会生成同样键的方法上边加@CacheEvict
         * @return
         */
        @CachePut(cacheNames =cacheName,keyGenerator = keyGenerator)
        @GetMapping("/query_put")
        public String query_put(){
            return "CachePut";
        }
    
    
    }
    
    

    首先访问localhost/query?id=1,然后可以看到redis里已经有了缓存

在这里插入图片描述

在这里插入图片描述

​ 然后访问清除缓存的接口,参数还是一样,可以看到缓存被清除了

在这里插入图片描述
在这里插入图片描述

​ 再访问下用@CachePut注解标注的接口,可以看到缓存好了(这个接口使用的键生成器生成的)

在这里插入图片描述

在这里插入图片描述

直接指定key的时候呢,用#id来引用请求里的参数id,作为键,而指定keyGenerator的时候,键是通过传入对象,方法,参数过去给键生成器,生成器返回一个键。注解操作的时候是区分键的。

你也可以不指定key或者keyGenerator,只指定cacheNames,那么不管参数是什么结果都是同样的

例如:

@Cacheable(cacheNames = cacheName)
@GetMapping("/get")
public String get(){
 return "get";
}

在这里插入图片描述
在这里插入图片描述

手动缓存式(RedisTemplate)

不全部列出可用操作,可使用redisTemplate.然后看下有哪些可用的方法

  • 配置类

    package com.example.springboot_redis_demo.annotation_cache.config;
    
    import com.example.springboot_redis_demo.annotation_cache.serializer.FastJson2JsonRedisSerializer;
    import org.springframework.beans.factory.annotation.Autowired;
    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.connection.RedisConnectionFactory;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.data.redis.serializer.RedisSerializationContext;
    import org.springframework.data.redis.serializer.RedisSerializer;
    import org.springframework.data.redis.serializer.StringRedisSerializer;
    
    /**
     * 注解自动缓存所需配置
     */
    
    @Configuration
    public class RedisConfig {
        @Autowired
        private FastJson2JsonRedisSerializer fastJson2JsonRedisSerializer;
    
    
        /**
         * 手动注入使用的RedisTemplate
         * @param connectionFactory
         * @return
         */
        @Bean
        public RedisTemplate<String , Object> redisTemplate(RedisConnectionFactory connectionFactory) {
            RedisTemplate<String, Object> template = new RedisTemplate<>();
            template.setConnectionFactory(connectionFactory);
            template.setValueSerializer(fastJson2JsonRedisSerializer);
            template.afterPropertiesSet();
            return template;
        }
    }
    
    
    
  • 序列化器

    还是上面那个

    package com.example.springboot_redis_demo.annotation_cache.serializer;
    
    import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.parser.ParserConfig;
    import com.alibaba.fastjson.serializer.SerializerFeature;
    import org.springframework.data.redis.serializer.RedisSerializer;
    import org.springframework.data.redis.serializer.SerializationException;
    import org.springframework.stereotype.Component;
    
    import java.nio.charset.Charset;
    
    /**
     * 基于FastJSON的一个序列化器
     * @Author:humorchen
     * @Date 2020/11/8 13:32
     */
    @Component
    public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T> {
    
        public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
        static {
            //由于fastjson有autotype检查,将自己的包前缀加进去防止反序列化失败
            ParserConfig.getGlobalInstance().addAccept("com");
        }
    
        private Class<T> clazz;
        public FastJson2JsonRedisSerializer() {
            this((Class<T>) Object.class);
        }
        public FastJson2JsonRedisSerializer(Class<T> clazz) {
            super();
            this.clazz = clazz;
        }
    
        @Override
        public byte[] serialize(T t) throws SerializationException {
            if (t == null) {
                return new byte[0];
            }
    
            return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
        }
    
        @Override
        public T deserialize(byte[] bytes) throws SerializationException {
            if (bytes == null || bytes.length <= 0) {
                return null;
            }
            String str = new String(bytes, DEFAULT_CHARSET);
    
            return (T) JSON.parseObject(str, clazz);
        }
    
    }
    
    
  • 测试用的controller NonautomaticController

    package com.example.springboot_redis_demo.nonautomatic_cache.controller;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    @RequestMapping("/nonautomatic")
    public class NonautomaticTestController {
        @Autowired
        private RedisTemplate<String,Object> redisTemplate;
    
        /**
         * 读取接口
         * @param id
         * @return
         */
        @GetMapping("/query")
        public String query(int id){
            //先从缓存读取读取不到再去数据库
            Object object=redisTemplate.opsForValue().get(id+"");
            if(object!=null){
                return object.toString();
            }else{
                //查询数据库
            }
            return "not found";
        }
    
        /**
         * 写入接口
         * @param id
         * @param value
         * @return
         */
        @RequestMapping("/set")
        public String set(int id,String value){
            //先写入数据库成功再写缓存
            redisTemplate.opsForValue().set(id+"",value);
            return "set success";
        }
    }
    
    
Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐