SpringBoot 2.xのキャッシュオブジェクト

53107 ワード

前言


Redisといえば、ほとんどの人がまず思い浮かべるのがキャッシュかもしれませんが、Javaプロジェクトではどのようにオブジェクトをキャッシュしますか?これが、次に説明するキャッシュオブジェクトです.この文書では、SpringBootプロジェクトを通じて、Jedisを通じてオブジェクトをRedisにキャッシュすることを迅速に理解します.
SpringBootプロジェクトの構築方法を理解する必要があります.また、SpringBootバージョンは2.1.0です.RELEASE.SpringBoot統合Jedisについては、SpringBoot 2を参照してください.xの高速統合Jedisクライアント(一般版)
次に、具体的なコードケースの紹介を始めましょう.

コードケース


プレゼンテーションでは、次のUserクラスで作成したオブジェクトをRedisにキャッシュします.具体的には、シーケンス化、Jsonの2つの方法があります.Userクラスの具体的なコードは以下の通りです.
public class User implements Serializable {

    private String name;
    private Integer age;

    public User(String name,Integer age){
        this.name = name;
        this.age = age;
    }
    //   getter and setter   
}

期限切れの処理とJedisスレッドに戻る操作からスレッドプールに戻る操作についてJedisCacheServiceSupportにカプセル化されています.具体的なコードは次のとおりです.
public abstract class JedisCacheServiceSupport {
    public static final long EXPIRE_MILLISECONDS_DEFAULT_LONG = 3*60*60*1000;

    public Long getExpireTime(Long expireTime) {
        expireTime = (expireTime == null || expireTime.longValue() <= 0) ? EXPIRE_MILLISECONDS_DEFAULT_LONG : expireTime;
        return expireTime;
    }

    public void close(Jedis jedis){
        if(jedis != null){
            jedis.close();
        }
    }
}

シーケンシャル方式


シーケンス化は,現時点でオブジェクトをバイナリのストリーム(シーケンス化)に変換してRedisに保存し,keyによりバイナリを取得し,バイナリストリームをオブジェクト(逆シーケンス化)に変換する.
オブジェクトを保存する具体的な操作は次のとおりです.
Userオブジェクトは、ObjectOutputStream.writeObject(object)によってbyte配列に変換され、psetex(byte[] key, long milliseconds, byte[] value)によってbyte[]配列がRedisに格納される.内
  • byte[]key:keyをbyte配列に変換する必要があります.
  • long milliseconds:オブジェクトがRedisで生存する時間です.ミリ秒単位です.
  • byte[]value:オブジェクトが変換されたbtye配列.

  • オブジェクトを取得する具体的な操作は次のとおりです.get(byte[] key)でUserオブジェクト変換のbyte配列を取得し、ObjectInputStream.readObject()でUserオブジェクトに変換します.
    シーケンス化によってオブジェクトの具体的なコードを保存および取得するには、次のようにします.
    
    @Service
    public class JedisCacheService extends JedisCacheServiceSupport  {
    
        private static Logger logger = LoggerFactory.getLogger(JedisCacheService.class);
    
    
    
        @Autowired
        private JedisPool jedisPool;
    
        /**
         *         
         * @param key
         * @return
         */
        public Object getObject(String key) {
            Jedis jedis = null;
            Object object = null;
            try {
                jedis = jedisPool.getResource();
                byte[] ObjectByteArray = jedis.get(key.getBytes());
                object = unserialize(ObjectByteArray);
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                close(jedis);
            }
            return object;
        }
    
        /**
         *        Redis ,        
         * @param key
         * @param value
         */
        public void putObject(String key, Object value) {
            putObject(key,value,null);
        }
        /**
         *        Redis ,        
         * @param key
         * @param value
         */
        public void putObject(String key, Object value, Long expireTime) {
            Jedis jedis = null;
            try {
                jedis = jedisPool.getResource();
                jedis.psetex(key.getBytes(),getExpireTime(expireTime),serialize(value));
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                close(jedis);
            }
        }
    
    
        /**
         *    
         * @param object
         * @return
         */
        public static byte[] serialize(Object object) {
            ObjectOutputStream oos = null;
            ByteArrayOutputStream baos = null;
            try {
                baos = new ByteArrayOutputStream();
                oos = new ObjectOutputStream(baos);
                oos.writeObject(object);
                byte[] bytes = baos.toByteArray();
                return bytes;
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
            } finally {
                IOUtil.closeStream(oos);
                IOUtil.closeStream(baos);
            }
            return null;
        }
    
        /**
         *     
         * @param bytes
         * @return
         */
        public static Object unserialize(byte[] bytes) {
            if (bytes == null) return null;
    
            ByteArrayInputStream bais = null;
            ObjectInputStream ois = null;
            try {
                bais = new ByteArrayInputStream(bytes);
                ois = new ObjectInputStream(bais);
                return ois.readObject();
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
            } finally {
                IOUtil.closeStream(bais);
                IOUtil.closeStream(ois);
            }
            return null;
        }
    }
    

    入力フローと出力フローを閉じるツールクラスの具体的なコードは次のとおりです.
    
    public class IOUtil {
        public static void closeStream(InputStream inputStream) {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
    
            }
        }
    
        public static void closeStream(OutputStream outputStream) {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
    
            }
        }
    }
    

    シーケンス化されたデモ


    JedisCacheService putObject(オブジェクトをキャッシュに入れる)、getObject(キャッシュからオブジェクトを取得する)をテストします.具体的なコードは次のとおりです.
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class JedisCacheServiceTest {
        private  Logger logger = LoggerFactory.getLogger(JedisCacheService.class);
        @Autowired
        private JedisCacheService jedisCacheService;
    
        @Test
        public void putObject() {
            User user = new User("zhuoqiammingyue",19);
            jedisCacheService.putObject("user01",user);
            logger.info("      !");
        }
    
        @Test
        public void getObject() {
            User user = (User)jedisCacheService.getObject("user01");
            logger.info("User name={},age={}",user.getName(),user.getAge());
        }
    }
    

    PutObjectログ情報:
    2020-02-26 22:08:50.320  INFO 26748 --- [           main] cn.lijunkui.cache.JedisCacheServiceTest  : Started JedisCacheServiceTest in 7.157 seconds (JVM running for 9.357)
    2020-02-26 22:08:51.144  INFO 26748 --- [           main] cn.lijunkui.cache.JedisCacheService      : 
    

    getObjectログ情報:
    2020-02-26 22:09:57.492  INFO 9612 --- [           main] cn.lijunkui.cache.JedisCacheServiceTest  : Started JedisCacheServiceTest in 7.07 seconds (JVM running for 8.902)
    2020-02-26 22:09:58.143  INFO 9612 --- [           main] cn.lijunkui.cache.JedisCacheService      : User name=zhuoqiammingyue,age=19
    

    Json方式


    Jsonはオブジェクトを読めるJson列に変換してRedisに保存し、keyでJson列を取得してJson列をオブジェクトにする方式です.オブジェクトをJson列に変換するのはグーグルのGsonによって行われるので、Gsonの依存を導入する必要があります.具体的な依存コードは以下の通りです.
    <dependency>
    	<groupId>com.google.code.gson</groupId>
    	<artifactId>gson</artifactId>
    	<version>2.8.5</version>
    </dependency>
    

    Jsonがオブジェクトを保存する具体的な操作は以下の通りです.
    Gsonを通してtoJson(Object src)は、UserオブジェクトをJson列に変換し、psetex(String key, long milliseconds, String value)を介してJson列をRedisに格納する.
    Jsonがオブジェクトを取得する具体的な操作は以下の通りです.get(String key)によってUserオブジェクトのJson列が取得され、Gson.fromJson(String json, Class classOfT)によってJson列がUserオブジェクトに変換される.
    Json方式でオブジェクトの具体的なコードを保存して取得するのは以下の通りです.
    @Service
    public class JedisJsonCacheService extends JedisCacheServiceSupport {
    
        private static Logger logger = LoggerFactory.getLogger(JedisJsonCacheService.class);
    
        @Autowired
        private JedisPool jedisPool;
    
        /**
         *         
         * @param key
         * @param clazz
         * @return
         */
        public Object getObject(String key,Class clazz) {
            Jedis jedis = null;
            Object object = null;
            try {
                jedis = jedisPool.getResource();
                String objectJson = jedis.get(key);
                 object = toObjce(objectJson,clazz);
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                close(jedis);
            }
            return object;
        }
        
        /**
         *       Redis ,        
         * @param key
         * @param value
         */
        public void putObject(String key, Object value) {
            putObject(key, value,null);
        }
    
        /**
         *       Redis ,        
         * @param key
         * @param value
         * @param expireTime
         */
        public void putObject(String key, Object value, Long expireTime) {
            Jedis jedis = null;
            try {
                jedis = jedisPool.getResource();
                jedis.psetex(key,getExpireTime(expireTime),toJson(value));
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                close(jedis);
            }
        }
    
    
    
        /**
         *       Json 
         * @param value
         * @return
         */
        private String toJson(Object value) {
            Gson gson = new Gson();
            return gson.toJson(value);
        }
    
        /**
         *  Json      
         * @param json
         * @param clazz
         * @return
         */
        private Object  toObjce(String json,Class clazz) {
            Gson gson = new Gson();
            return gson.fromJson(json,clazz);
        }
    }
    

    シーケンス化されたデモ


    JedisJsonCacheServiceTest putObject(キャッシュにオブジェクトを入れる)、getObject(キャッシュからオブジェクトを取得する)をテストします.具体的なコードは次のとおりです.
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class JedisJsonCacheServiceTest {
    
        private Logger logger = LoggerFactory.getLogger(JedisJsonCacheServiceTest.class);
        @Autowired
        private JedisJsonCacheService jedisJsonCacheService;
    
        @Test
        public void putObject() {
            User user = new User("zhuoqiammingyue2",20);
            jedisJsonCacheService.putObject("user02",user);
            logger.info("      !");
        }
    
        @Test
        public void getObject() {
            User user = (User)jedisJsonCacheService.getObject("user02",User.class);
            logger.info("User name={},age={}",user.getName(),user.getAge());
        }
    }
    

    PutObjectログ情報:
    2020-02-27 07:57:16.184  INFO 3692 --- [           main] c.l.cache.JedisJsonCacheServiceTest      : Started JedisJsonCacheServiceTest in 7.92 seconds (JVM running for 10.786)
    2020-02-27 07:57:16.852  INFO 3692 --- [           main] c.l.cache.JedisJsonCacheServiceTest      : 
    

    getObjectログ情報:
    2020-02-27 07:57:56.359  INFO 27624 --- [           main] c.l.cache.JedisJsonCacheServiceTest      : Started JedisJsonCacheServiceTest in 7.364 seconds (JVM running for 9.256)
    2020-02-27 07:57:56.824  INFO 27624 --- [           main] c.l.cache.JedisJsonCacheServiceTest      : User name=zhuoqiammingyue2,age=20
    

    小結


    シーケンス化とJsonの2つの方法は、実際の開発ではあなたの好みに合わせて自分で選ぶことができます.Json方式はGsonを使用しています.もちろんFastJsonも使用できます.シーケンス化はJavaオリジナルのシーケンス化と逆シーケンス化を採用しています.同時に、より効率的なHessianに切り替えてシーケンス化と逆シーケンス化を行うこともできます.

    コードの例


    ローカル環境は次のとおりです.
  • SpringBoot Version: 2.1.0.RELEASE
  • Apache Maven Version: 3.6.0
  • Java Version: 1.8.0_144
  • IDEA:IntellJ IDEA

  • 操作プロセスに問題が発生した場合、私のGitHub倉庫springbootexamplesのモジュール名はspring-boot-2です.x-redis-jedis-objectcacheプロジェクトで比較表示
    GitHub:https://github.com/zhuoqianmingyue/springbootexamples