A. 如何在service層加入redis緩存
//放入緩存註解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Inherited
public@interfaceCacheable{//放入
Stringkey();//緩存key
StringfieldKey();//field值
intexpireTime()default3600;
}
//從緩存中銷毀註解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public@interfaceCacheEvict{//銷毀
Stringkey();
String[]fieldKey();
intexpireTime()default3600;
}
Aspect類
//環繞切入
@Around(value="@annotation(com.xx.cache.annotation.Cacheable)")
publicObjectcache(ProceedingJoinPointpjp){
Objectresult=null;
Methodmethod=getMethod(pjp);
Cacheablecacheable=method.getAnnotation(Cacheable.class);
StringfieldKey=cacheable.fieldKey();
if(cacheable.fieldKey().indexOf("#")==0){//動態變數存入方式
fieldKey=parseKey(cacheable.fieldKey(),method,pjp.getArgs());
}
if(useCache){//判斷是否開啟緩存開啟緩存從緩存獲取result
//獲取方法的返回類型,讓緩存可以返回正確的類型
ClassreturnType=((MethodSignature)pjp.getSignature()).getReturnType();
//使用redis的hash進行存取,易於管理
//result=JedisUtils.hget(cacheable.key(),fieldKey,method.getReturnType());
result=JedisUtils.hget(cacheable.key(),fieldKey,returnType);
if(result==null){
try{
result=pjp.proceed();
//Assert.notNull(fieldKey);
JedisUtils.hset(cacheable.key(),fieldKey,result);
logger.debug("The"+cacheable.key()+"addtoredis,thefieldKeyis"+fieldKey);
}catch(Throwablee){
e.printStackTrace();
}
}
returnresult;
}
try{
returnpjp.proceed();
}catch(Throwablethrowable){
throwable.printStackTrace();
returnnull;
}
}
//環繞切入
@Around(value="@annotation(com.xx.cache.annotation.CacheEvict)")
publicObjectevict(ProceedingJoinPointpjp){
//和cache類似,使用Jedis.hdel()刪除緩存即可
if(useCache){//判斷是否開啟緩存
Methodmethod=getMethod(pjp);
CacheEvictcacheEvict=method.getAnnotation(CacheEvict.class);
String[]fieldKeys=cacheEvict.fieldKey();
intdeleteSuccessFlag=0;
for(StringfieldKey:fieldKeys){
if(fieldKey.indexOf("#")==0){//動態變數存入方式
Stringt=fieldKey;
fieldKey=parseKey(fieldKey,method,pjp.getArgs());
if(fieldKey==null){
logger.error("cacheevictfieldkey{}connotbenull,thatmaybecausedataconnotsync",t);
t=null;
}
}
deleteSuccessFlag+=JedisUtils.hdel(cacheEvict.key(),fieldKey==null?"":fieldKey);
logger.debug("Thereferencefieldkey:"+fieldKey+"for"+cacheEvict.key()+"hasbeendeletefromredis");
}
logger.debug("Delete"+deleteSuccessFlag+""+cacheEvict.key()+"fromredis");
}
try{
returnpjp.proceed();
}catch(Throwablee){
e.printStackTrace();
returnnull;
}
}
/**
*獲取緩存的key
*key定義在註解上,支持SPEL表達式
*
*@paramkey
*@parammethod
*@paramargs
*@return
*/
privateStringparseKey(Stringkey,Methodmethod,Object[]args){
//獲取被攔截方法參數名列表(使用Spring支持類庫)
=();
String[]paraNameArr=u.getParameterNames(method);
//使用SPEL進行key的解析
ExpressionParserparser=newSpelExpressionParser();
//SPEL上下文
=newStandardEvaluationContext();
//把方法參數放入SPEL上下文中
for(inti=0;i<paraNameArr.length;i++){
context.setVariable(paraNameArr[i],args[i]);
}
returnparser.parseExpression(key).getValue(context,String.class);
}
使用,在service調用前使用:
@Cacheable(key="biz_member",fieldKey="#id")publicMemberget(Stringid){returnsuper.get(id);}@CacheEvict(key="member",fieldKey={"#member.id","#member.account"})publicSerializablesave(Membermember){return.insert(member);}@CacheEvict(key="member",fieldKey={"#member.id","#member.account"})publicvoiddelete(Membermember){.delete(member);}
B. 自定義微信分享鏈接(使用JS-SDK) + 實現預覽pdf
可參考:微信JS-SDK說明文檔 >
此時可能出現白名單錯誤(忘截圖了),需要在微信公眾號中設置錯誤中的IP
注意:access_token和ticket都需要緩存
4. 獲取簽名 signature
將以上內容以鍵值對形式拼接,類似如下
本地引入sha1演算法(需網上查找)
將上述拼接的字元串以參數的形式傳遞到sha1中得到 signature
signature = sha1(拼接完的字元串)
驗證 signature 是否正確 >
將appId,nonceStr,timestamp和signature返回給前端
官網上是這樣描述的:
這時候調用 updateAppMessageShareData , updateTimelineShareData 的時候就可以生效了,具體原理不清楚。。
注意:imgUrl配置有嚴格的要求
尺寸120 x 120,大小不超過10K,不支持GIF格式。必須採用https協議(最好寫完整url),不支持base64。由於我使用的是vue,在webpack打包時圖片小於10k的是會自動打包成base64導致無法正常顯示余冊圖片,因此在webpack.base.config.js中修改默認配置
由於在網頁中直接查看pdf的路徑是無法在微信中查看(安卓)和分享(ios),因此使用pdf插件進行優化 --- pdf.js 。其原理是繪製成canvas,最終在真機上放大時可能出現模糊的問題悶毀信。
創建之後控制台會報錯出現跨域問題,因為pdf.js不支持跨域訪問。此時可以將錯誤跨域信息在上一步你引入的文件中查找,然後將其判斷語句注釋掉即可解決這個問題。最後會發現pdf出現在這個容器中(忘截圖了),螞輪也實現了微信中預覽和分享的功能。