Redis MyBatis自定義註解實現快取

2021-08-08 12:52:28 字數 3423 閱讀 6276

在資料庫查詢前我想查詢是否存在快取,不存在則查詢,這樣的重複性操作寫在**裡很難看,通過aspectj的aop程式設計,可以很優雅地實現這個快取過程。

但是在使用過程中,發現spring自帶的@cacheable註解序列化物件時是使用jdk的序列化工具往redis裡存資料,這樣很佔redis的記憶體,為何不用fastjson之類的序列化工具序列化物件後往redis裡存json字串呢,更加輕量快捷。

但是json在序列化和反序列化的時候需要提供型別,但是型別在springcache中並沒有提供,那就自己做個吧!

/**

* 快取註解

*/@target(elementtype.method)

@retention(retentionpolicy.runtime)

public @inte***ce

rediscache

/**

* 刪除快取註解

*/@target(elementtype.method)

@retention(retentionpolicy.runtime)

public @inte***ce

redisevict ;

class type();

}

/**

* redis快取切面處理

*/@aspect

@component

public

class

rediscacheaspect

//得到被**的方法上的註解

class modeltype = method.getannotation(rediscache.class).type();

//檢查redis是否有快取

string value = (string) redistemplate.opsforhash().get(modeltype.getname(), key);

object result;

if (null == value)

//去資料庫查詢

result = jp.proceed(jp.getargs());

//把序列化結果放入快取

redistemplate.opsforhash().put(modeltype.getname(), key, serialize(result));

// 設定失效時間

redistemplate.expire(modeltype.getname(), cache.expire(), timeunit.seconds);

} else

//得到被**方法的返回值型別

class returntype = ((methodsignature) jp.getsignature()).getreturntype();

//反序列化從快取中拿到的json

result = deserialize(value, returntype, modeltype);

}return result;

}/**

* 刪除快取

*/@around("@annotation(com.common.cache.redis.redisevict)")

public object redisevict(final proceedingjoinpoint jp) throws throwable

//判斷是否指定了field

string fields = method.getannotation(redisevict.class).field();

if (fields.length == 0) else

}if (objects.size() > 0)

}return jp.proceed(jp.getargs());

}//fastjson序列化物件

private string serialize(object result)

//fastjson反序列化獲得物件

@suppresswarnings("unchecked")

private object deserialize(string json, class clazz, class modeltype)

//返回結果是普通物件

return json.parseobject(json, clazz);

}/**

* 獲取被攔截方法物件

* methodsignature.getmethod() 獲取的是頂層介面或者父類的方法物件

* 而快取的註解在實現類的方法上

* 所以應該使用反射獲取當前物件的方法物件

*/private method getmethod(proceedingjoinpoint pjp) catch (nosuchmethodexception e)

return method;

}private string parsekey(string field, method method, object args)

//_號分割

string spel = field.replace("_", "+'_'+");

//獲得被攔截方法引數列表

localvariabletableparameternamediscoverer nd = new localvariabletableparameternamediscoverer();

string parameternames = nd.getparameternames(method);

//使用spel進行key的解析

expressionparser parser = new spelexpressionparser();

//spel上下文

standardevaluationcontext context = new standardevaluationcontext();

//把方法引數放入spel上下文中

for (int i = 0; i < parameternames.length; i++)

return method.getname() + parser.parseexpression(spel).getvalue(context, string.class);

}}

base-package="com.common.cache.redis"/>

這樣就可以很輕鬆地使用自定義的快取註解了

@rediscache(field = "#page_#rows_#conditions.pid", type = dict.class)

public easyuipageselectbypagewithconditions(integer page, integer rows, dict conditions)

自定義 如何自定義協議

何為自定義協議,其實是相對標準協議來說的,這裡主要針對的是應用層協議 常見的標準的應用層協議如http ftp smtp等,如果我們在網路通訊的過程中不去使用這些標準協議,那就需要自定義協議,比如我們常用的rpc框架 dubbo,thrift 分布式快取 redis,memcached 等都是自定義...

自定義控制項 自定義鐘錶

private context mcontext 畫筆 private paint mpaint 控制項的寬 private int mwidth x方向的圓心座標 private int center 鐘錶的半徑 private int mradio 圓環的寬 private int stroke...

自定義控制項及自定義屬性

自定義控制項在android開發中的重要性,是不言而喻,眾人皆知的。希望通過這二天的學習,能讓大家了解自定義控制項的原理,熟悉自定義控制項的使用步驟,並能寫出一些普通的效果。內容介紹 1 使用系統控制項,實現自定義的效果,案例有 優酷環形選單 廣告條 viewpager 下拉列表 spinner 2...