• 技术文章 >Java >java教程

    缓存机制中Spring Boot集成Redis的方法介绍

    Y2JY2J2017-04-21 16:40:33原创1021
    本文章牵涉到的技术点比较多:spring Data JPA、Redis、Spring MVC,Spirng Cache,所以在看这篇文章的时候,需要对以上这些技术点有一定的了解或者也可以先看看这篇文章,针对文章中实际的技术点在进一步了解(注意,您需要自己下载Redis Server到您的本地,所以确保您本地的Redis可用,这里还使用了MySQL数据库,当然你也可以内存数据库进行测试)。这篇文章会提供对应的Eclipse代码示例,具体大体的分如下几个步骤:

    (1)新建Java Maven Project;
    (2)在pom.xml中添加相应的依赖包;
    (3)编写Spring Boot启动类;
    (4)配置application.properties;
    (5)编写RedisCacheConfig配置类;
    (6)编写DemoInfo测试实体类;
    (7)编写DemoInfoRepository持久化类;
    (8)编写DemoInfoService类;
    (9)编写DemoInfoController类;
    (10)测试代码是否正常运行了
    (11)自定义缓存key;

    (1)新建Java Maven Project;

    这个步骤就不细说,新建一个spring-boot-redis Java maven project;

    (2)在pom.xml中添加相应的依赖包;

    在Maven中添加相应的依赖包,主要有:spring boot 父节点依赖;spring boot web支持;缓存服务spring-context-support;添加redis支持;JPA操作数据库;mysql 数据库驱动,具体pom.xml文件如下:

    <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>
     <groupId>com.kfit</groupId>
     <artifactId>spring-boot-redis</artifactId>
     <version>0.0.1-SNAPSHOT</version>
     <packaging>jar</packaging>
     <name>spring-boot-redis</name>
     <url>http://maven.apache.org</url>
     <properties>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
     <!-- 配置JDK编译版本. -->
     <java.version>1.8</java.version>
     </properties>
     <!-- spring boot 父节点依赖,
      引入这个之后相关的引入就不需要添加version配置,
      spring boot会自动选择最合适的版本进行添加。
     -->
     <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>1.3.3.RELEASE</version>
     </parent>
     <dependencies>
      <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
       <scope>test</scope>
      </dependency>
      <!-- spring boot web支持:mvc,aop... -->
      <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
      <!--
       包含支持UI模版(Velocity,FreeMarker,JasperReports),
       邮件服务,
       脚本服务(JRuby),
       缓存Cache(EHCache),
       任务计划Scheduling(uartz)。
      -->
      <dependency>
       <groupId>org.springframework</groupId>
       <artifactId>spring-context-support</artifactId>
      </dependency>
      <!-- 添加redis支持-->
      <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-redis</artifactId>
      </dependency>
      <!-- JPA操作数据库. -->
      <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-data-jpa</artifactId>
      </dependency>
      <!-- mysql 数据库驱动. -->
      <dependency>
       <groupId>mysql</groupId>
       <artifactId>mysql-connector-java</artifactId>
      </dependency>
      <!-- 单元测试. -->
      <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-test</artifactId>
       <scope>test</scope>
      </dependency>
     </dependencies>
    </project>

    上面是完整的pom.xml文件,每个里面都进行了简单的注释。

    (3)编写Spring Boot启动类(com.kfit.App);

    package com.kfit;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    /**
     * Spring Boot启动类;
     *
     * @author Angel(QQ:*********)
     * @version v.0.1
     */
    @SpringBootApplication
    public class App {
      /**
      * -javaagent:.\lib\springloaded-1.2.4.RELEASE.jar -noverify
      * @param args
      */
      public static void main(String[] args) {
        SpringApplication.run(App.class, args);
      }
    }

    (4)配置application.properties;

    这里主要是配置两个资源,第一就是数据库基本信息;第二就是redis配置;第三就是JPA的配置;

    Src/main/resouces/application.properties:
    ########################################################
    ###datasource 配置MySQL数据源;
    ########################################################
    spring.datasource.url = jdbc:mysql://localhost:3306/test
    spring.datasource.username = root
    spring.datasource.password = root
    spring.datasource.driverClassName = com.mysql.jdbc.Driver
    spring.datasource.max-active=20
    spring.datasource.max-idle=8
    spring.datasource.min-idle=8
    spring.datasource.initial-size=10
    ########################################################
    ###REDIS (RedisProperties) redis基本配置;
    ########################################################
    # database name
    spring.redis.database=0
    # server host1
    spring.redis.host=127.0.0.1 
    # server password
    #spring.redis.password=
    #connection port
    spring.redis.port=6379
    # pool settings ...
    spring.redis.pool.max-idle=8
    spring.redis.pool.min-idle=0
    spring.redis.pool.max-active=8
    spring.redis.pool.max-wait=-1
    # name of Redis server
    #spring.redis.sentinel.master=
    # comma-separated list of host:port pairs
    #spring.redis.sentinel.nodes=
    ########################################################
    ### Java Persistence Api 自动进行建表
    ########################################################
    # Specify the DBMS
    spring.jpa.database = MYSQL
    # Show or not log for each sql query
    spring.jpa.show-sql = true
    # hibernate ddl auto (create, create-drop, update)
    spring.jpa.hibernate.ddl-auto = update
    # Naming strategy
    spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy
    # stripped before adding them to the entity manager)
    spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect

    (5)编写RedisCacheConfig配置类;

    缓存主要有几个要实现的类:其一就是CacheManager缓存管理器;其二就是具体操作实现类;其三就是CacheManager工厂类(这个可以使用配置文件配置的进行注入,也可以通过编码的方式进行实现);其四就是缓存key生产策略(当然Spring自带生成策略,但是在Redis客户端进行查看的话是系列化的key,对于我们肉眼来说就是感觉是乱码了,这里我们先使用自带的缓存策略)。

    com.kfit.config/RedisCacheConfig:
    package com.kfit.config;
    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.RedisCacheManager;
    import org.springframework.data.redis.connection.RedisConnectionFactory;
    import org.springframework.data.redis.core.RedisTemplate;
    /**
     * redis 缓存配置;
     *
     * 注意:RedisCacheConfig这里也可以不用继承:CachingConfigurerSupport,也就是直接一个普通的Class就好了;
     *
     * 这里主要我们之后要重新实现 key的生成策略,只要这里修改KeyGenerator,其它位置不用修改就生效了。
     *
     * 普通使用普通类的方式的话,那么在使用@Cacheable的时候还需要指定KeyGenerator的名称;这样编码的时候比较麻烦。
     *
     * @author Angel(QQ:412887952)
     * @version v.0.1
     */
    @Configuration
    @EnableCaching//启用缓存,这个注解很重要;
    publicclass RedisCacheConfig extends CachingConfigurerSupport {
     /**
      * 缓存管理器.
      * @param redisTemplate
      * @return
      */
     @Bean
     public CacheManager cacheManager(RedisTemplate<?,?> redisTemplate) {
      CacheManager cacheManager = new RedisCacheManager(redisTemplate);
      returncacheManager;
     }
     /**
      * redis模板操作类,类似于jdbcTemplate的一个类;
      *
      * 虽然CacheManager也能获取到Cache对象,但是操作起来没有那么灵活;
      *
      * 这里在扩展下:RedisTemplate这个类不见得很好操作,我们可以在进行扩展一个我们
      *
      * 自己的缓存类,比如:RedisStorage类;
      *
      * @param factory : 通过Spring进行注入,参数在application.properties进行配置;
      * @return
      */
     @Bean
     public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
      RedisTemplate<String, String> redisTemplate = new RedisTemplate<String, String>();
      redisTemplate.setConnectionFactory(factory);
      //key序列化方式;(不然会出现乱码;),但是如果方法上有Long等非String类型的话,会报类型转换错误;
      //所以在没有自己定义key生成策略的时候,以下这个代码建议不要这么写,可以不配置或者自己实现ObjectRedisSerializer
      //或者JdkSerializationRedisSerializer序列化方式;
    //  RedisSerializer<String> redisSerializer = new StringRedisSerializer();//Long类型不可以会出现异常信息;
    //  redisTemplate.setKeySerializer(redisSerializer);
    //  redisTemplate.setHashKeySerializer(redisSerializer);
      returnredisTemplate;
     }
    }

    在以上代码有很详细的注释,在这里还是在简单的提下:

    RedisCacheConfig这里也可以不用继承:CachingConfigurerSupport,也就是直接一个普通的Class就好了;这里主要我们之后要重新实现 key的生成策略,只要这里修改KeyGenerator,其它位置不用修改就生效了。普通使用普通类的方式的话,那么在使用@Cacheable的时候还需要指定KeyGenerator的名称;这样编码的时候比较麻烦。

    (6)编写DemoInfo测试实体类;

    编写一个测试实体类:com.kfit.bean.DemoInfo:

    package com.kfit.bean;
    import java.io.Serializable;
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    /**
     * 测试实体类,这个随便;
     * @author Angel(QQ:412887952)
     * @version v.0.1
     */
    @Entity
    publicclass DemoInfo implements Serializable{
     privatestaticfinallongserialVersionUID = 1L;
     @Id@GeneratedValue
     privatelongid;
     private String name;
     private String pwd;
     publiclong getId() {
      returnid;
     }
     publicvoid setId(longid) {
      this.id = id;
     }
     public String getName() {
      returnname;
     }
     publicvoid setName(String name) {
      this.name = name;
     }
     public String getPwd() {
      returnpwd;
     }
     publicvoid setPwd(String pwd) {
      this.pwd = pwd;
     }
     @Override
     public String toString() {
      return"DemoInfo [id=" + id + ", name=" + name + ", pwd=" + pwd + "]";
     }
    }

    (7)编写DemoInfoRepository持久化类;

    DemoInfoRepository使用Spirng Data JPA实现:

    com.kfit.repository.DemoInfoRepository:
    package com.kfit.repository;
    import org.springframework.data.repository.CrudRepository;
    import com.kfit.bean.DemoInfo;
    /**
     * DemoInfo持久化类
     * @author Angel(QQ:412887952)
     * @version v.0.1
     */
    publicinterface DemoInfoRepository extends CrudRepository<DemoInfo,Long> {
    }

    (8)编写DemoInfoService类;

    编写DemoInfoService,这里有两个技术方面,第一就是使用Spring @Cacheable注解方式和RedisTemplate对象进行操作,具体代码如下:

    com.kfit.service.DemoInfoService:

    package com.kfit.service;
    import com.kfit.bean.DemoInfo;
    /**
     * demoInfo 服务接口
     * @author Angel(QQ:412887952)
     * @version v.0.1
     */
    publicinterface DemoInfoService {
     public DemoInfo findById(longid);
     publicvoid deleteFromCache(longid);
     void test();
    }
    com.kfit.service.impl.DemoInfoServiceImpl:
    package com.kfit.service.impl;
    import javax.annotation.Resource;
    import org.springframework.cache.annotation.CacheEvict;
    import org.springframework.cache.annotation.Cacheable;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.data.redis.core.ValueOperations;
    import org.springframework.stereotype.Service;
    import com.kfit.bean.DemoInfo;
    import com.kfit.repository.DemoInfoRepository;
    import com.kfit.service.DemoInfoService;
    /**
     *
     *DemoInfo数据处理类
     *
     * @author Angel(QQ:412887952)
     * @version v.0.1
     */
    @Service
    publicclass DemoInfoServiceImpl implements DemoInfoService {
     @Resource
     private DemoInfoRepository demoInfoRepository;
     @Resource
     private RedisTemplate<String,String> redisTemplate;
     @Override
     publicvoid test(){
      ValueOperations<String,String> valueOperations = redisTemplate.opsForValue();
      valueOperations.set("mykey4", "random1="+Math.random());
      System.out.println(valueOperations.get("mykey4"));
     }
     //keyGenerator="myKeyGenerator"
     @Cacheable(value="demoInfo") //缓存,这里没有指定key.
     @Override
     public DemoInfo findById(longid) {
      System.err.println("DemoInfoServiceImpl.findById()=========从数据库中进行获取的....id="+id);
      returndemoInfoRepository.findOne(id);
     }
     @CacheEvict(value="demoInfo")
     @Override
     publicvoid deleteFromCache(longid) {
      System.out.println("DemoInfoServiceImpl.delete().从缓存中删除.");
     }
    }

    (9)编写DemoInfoController类;

    package com.kfit.controller;
    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.ResponseBody;
    import com.kfit.bean.DemoInfo;
    import com.kfit.service.DemoInfoService;
    /**
     * 测试类.
     * @author Angel(QQ:412887952)
     * @version v.0.1
     */
    @Controller
    publicclass DemoInfoController {
     @Autowired
      DemoInfoService demoInfoService;
     @RequestMapping("/test")
     public@ResponseBody String test(){
      DemoInfo loaded = demoInfoService.findById(1);
    System.out.println("loaded="+loaded);
    DemoInfo cached = demoInfoService.findById(1);
      System.out.println("cached="+cached);
      loaded = demoInfoService.findById(2);
      System.out.println("loaded2="+loaded);
      return"ok";
     }
     @RequestMapping("/delete")
     public@ResponseBody String delete(longid){
      demoInfoService.deleteFromCache(id);
      return"ok";
     }
     @RequestMapping("/test1")
     public@ResponseBody String test1(){
      demoInfoService.test();
      System.out.println("DemoInfoController.test1()");
      return"ok";
     }
    }

    (10)测试代码是否正常运行了

    启动应用程序,访问地址:127.0.0.1:8080/test

    查看控制台可以查看:

    DemoInfoServiceImpl.findById()=========从数据库中进行获取的....id=1
    loaded=DemoInfo [id=1, name=张三, pwd=123456]
    cached=DemoInfo [id=1, name=张三, pwd=123456]
    DemoInfoServiceImpl.findById()=========从数据库中进行获取的....id=2
    loaded2=DemoInfo [id=2, name=张三, pwd=123456]

    如果你看到以上的打印信息的话,那么说明缓存成功了。

    访问地址:127.0.0.1:8080/test1

    random1=0.9985031320746356
    DemoInfoController.test1()

    二次访问:http://127.0.0.1:8080/test

    loaded=DemoInfo [id=1, name=张三, pwd=123456]
    cached=DemoInfo [id=1, name=张三, pwd=123456]
    loaded2=DemoInfo [id=2, name=张三, pwd=123456]

    这时候所有的数据都是执行缓存的。

    这时候执行删除动作:127.0.0.1:8080/delete?id=1

    然后在访问:127.0.0.1:8080/test

    DemoInfoServiceImpl.findById()=========从数据库中进行获取的....id=1
    loaded=DemoInfo [id=1, name=张三, pwd=123456]
    cached=DemoInfo [id=1, name=张三, pwd=123456]
    loaded2=DemoInfo [id=2, name=张三, pwd=123456]

    (11)自定义缓存key;

    在com.kfit.config.RedisCacheConfig类中重写CachingConfigurerSupport中的keyGenerator ,具体实现代码如下:

    /**
      * 自定义key.
      * 此方法将会根据类名+方法名+所有参数的值生成唯一的一个key,即使@Cacheable中的value属性一样,key也会不一样。
      */
     @Override
     public KeyGenerator keyGenerator() {
      System.out.println("RedisCacheConfig.keyGenerator()");
      returnnew KeyGenerator() {
       @Override
       public Object generate(Object o, Method method, Object... objects) {
        // This will generate a unique key of the class name, the method name
        //and all method parameters appended.
        StringBuilder sb = new StringBuilder();
        sb.append(o.getClass().getName());
        sb.append(method.getName());
        for (Object obj : objects) {
         sb.append(obj.toString());
        }
        System.out.println("keyGenerator=" + sb.toString());
        returnsb.toString();
       }
      };
     }

    这时候在redis的客户端查看key的话还是序列化的肉眼看到就是乱码了,那么我改变key的序列方式,这个很简单,redis底层已经有具体的实现类了,我们只需要配置下:

    //key序列化方式;(不然会出现乱码;),但是如果方法上有Long等非String类型的话,会报类型转换错误;
    //所以在没有自己定义key生成策略的时候,以下这个代码建议不要这么写,可以不配置或者自己实现ObjectRedisSerializer
    //或者JdkSerializationRedisSerializer序列化方式;
        RedisSerializer<String> redisSerializer = new StringRedisSerializer();//Long类型不可以会出现异常信息;
        redisTemplate.setKeySerializer(redisSerializer);
        redisTemplate.setHashKeySerializer(redisSerializer);

    综上以上分析:RedisCacheConfig类的方法调整为:


    package com.kfit.config;
    import java.lang.reflect.Method;
    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.serializer.RedisSerializer;
    import org.springframework.data.redis.serializer.StringRedisSerializer;
    /**
     * redis 缓存配置;
     *
     * 注意:RedisCacheConfig这里也可以不用继承:CachingConfigurerSupport,也就是直接一个普通的Class就好了;
     *
     * 这里主要我们之后要重新实现 key的生成策略,只要这里修改KeyGenerator,其它位置不用修改就生效了。
     *
     * 普通使用普通类的方式的话,那么在使用@Cacheable的时候还需要指定KeyGenerator的名称;这样编码的时候比较麻烦。
     *
     * @author Angel(QQ:412887952)
     * @version v.0.1
     */
    @Configuration
    @EnableCaching//启用缓存,这个注解很重要;
    publicclass RedisCacheConfig extends CachingConfigurerSupport {
      /**
       * 缓存管理器.
       * @param redisTemplate
       * @return
       */
      @Bean
      public CacheManager cacheManager(RedisTemplate<?,?> redisTemplate) {
        CacheManager cacheManager = new RedisCacheManager(redisTemplate);
        returncacheManager;
      }
      /**
       * RedisTemplate缓存操作类,类似于jdbcTemplate的一个类;
       *
       * 虽然CacheManager也能获取到Cache对象,但是操作起来没有那么灵活;
       *
       * 这里在扩展下:RedisTemplate这个类不见得很好操作,我们可以在进行扩展一个我们
       *
       * 自己的缓存类,比如:RedisStorage类;
       *
       * @param factory : 通过Spring进行注入,参数在application.properties进行配置;
       * @return
       */
      @Bean
      public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, String> redisTemplate = new RedisTemplate<String, String>();
        redisTemplate.setConnectionFactory(factory);
        //key序列化方式;(不然会出现乱码;),但是如果方法上有Long等非String类型的话,会报类型转换错误;
        //所以在没有自己定义key生成策略的时候,以下这个代码建议不要这么写,可以不配置或者自己实现ObjectRedisSerializer
        //或者JdkSerializationRedisSerializer序列化方式;
        RedisSerializer<String> redisSerializer = new StringRedisSerializer();//Long类型不可以会出现异常信息;
        redisTemplate.setKeySerializer(redisSerializer);
        redisTemplate.setHashKeySerializer(redisSerializer);
        returnredisTemplate;
      }
      /**
       * 自定义key.
       * 此方法将会根据类名+方法名+所有参数的值生成唯一的一个key,即使@Cacheable中的value属性一样,key也会不一样。
       */
      @Override
      public KeyGenerator keyGenerator() {
        System.out.println("RedisCacheConfig.keyGenerator()");
        returnnew KeyGenerator() {
          @Override
          public Object generate(Object o, Method method, Object... objects) {
           // This will generate a unique key of the class name, the method name
           //and all method parameters appended.
           StringBuilder sb = new StringBuilder();
           sb.append(o.getClass().getName());
           sb.append(method.getName());
           for (Object obj : objects) {
             sb.append(obj.toString());
           }
           System.out.println("keyGenerator=" + sb.toString());
           returnsb.toString();
          }
        };
      }
    }

    这时候在访问地址:127.0.0.1:8080/test

    这时候看到的Key就是:com.kfit.service.impl.DemoInfoServiceImplfindById1

    在控制台打印信息是:

    (1)keyGenerator=com.kfit.service.impl.DemoInfoServiceImplfindById1
    (2)DemoInfoServiceImpl.findById()=========从数据库中进行获取的....id=1
    (3)keyGenerator=com.kfit.service.impl.DemoInfoServiceImplfindById1
    (4)loaded=DemoInfo [id=1, name=张三, pwd=123456]
    (5)keyGenerator=com.kfit.service.impl.DemoInfoServiceImplfindById1
    (6)cached=DemoInfo [id=1, name=张三, pwd=123456]
    (7)keyGenerator=com.kfit.service.impl.DemoInfoServiceImplfindById2
    (8)keyGenerator=com.kfit.service.impl.DemoInfoServiceImplfindById2
    (10)DemoInfoServiceImpl.findById()=========从数据库中进行获取的....id=2
    (11)loaded2=DemoInfo [id=2, name=张三, pwd=123456]

    其中@Cacheable,@CacheEvict下节进行简单的介绍,这节的东西实在是太多了,到这里就打住吧,剩下的就需要靠你们自己进行扩展了。

    以上就是缓存机制中Spring Boot集成Redis的方法介绍的详细内容,更多请关注php中文网其它相关文章!

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    专题推荐:springboot redis,缓存
    上一篇:Java中出现内存泄漏情况的概述 下一篇:用java做一个简单的FTP连接管理模块(ftp软件开发一)
    PHP编程就业班

    相关文章推荐

    • JAVA-5NIO之Selector• J2ME程序开发全方位基础讲解汇总(一)• java对象的序列化和反序列化• java Hibernate多对多映射详解及实例代码• 快速入门Java中的Lambda表达式

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网