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に格納される.内オブジェクトを取得する具体的な操作は次のとおりです.
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に切り替えてシーケンス化と逆シーケンス化を行うこともできます.
コードの例
ローカル環境は次のとおりです.
操作プロセスに問題が発生した場合、私のGitHub倉庫springbootexamplesのモジュール名はspring-boot-2です.x-redis-jedis-objectcacheプロジェクトで比較表示
GitHub:https://github.com/zhuoqianmingyue/springbootexamples