springboot結合redis做緩存,在@Cacheable中使用如下SpEL時報錯。 @Cacheable(cacheNames = ENTERPRISE_CACHE_KEY, key = "#{T(com.emax.common.RestApiSignUtil).foo(#root.args ...
springboot結合redis做緩存,在@Cacheable中使用如下SpEL時報錯。
@Cacheable(cacheNames = ENTERPRISE_CACHE_KEY, key = "#{T(com.emax.common.RestApiSignUtil).foo(#root.args[0])}")
異常:
org.springframework.expression.spel.SpelParseException: Expression [#{T(com.emax.common.RestApiSignUtil).foo(#root.args[0])}] @1: EL1043E: Unexpected token. Expected 'identifier' but was 'lcurly({)'
異常stacktrace信息:
org.springframework.expression.spel.SpelParseException: Expression [#{T(com.emax.common.RestApiSignUtil).foo(#root.args[0])}] @1: EL1043E: Unexpected token. Expected 'identifier' but was 'lcurly({)' at org.springframework.expression.spel.standard.InternalSpelExpressionParser.internalException(InternalSpelExpressionParser.java:1044) at org.springframework.expression.spel.standard.InternalSpelExpressionParser.eatToken(InternalSpelExpressionParser.java:926) at org.springframework.expression.spel.standard.InternalSpelExpressionParser.maybeEatFunctionOrVar(InternalSpelExpressionParser.java:423) at org.springframework.expression.spel.standard.InternalSpelExpressionParser.eatStartNode(InternalSpelExpressionParser.java:512) at org.springframework.expression.spel.standard.InternalSpelExpressionParser.eatPrimaryExpression(InternalSpelExpressionParser.java:351) at org.springframework.expression.spel.standard.InternalSpelExpressionParser.eatUnaryExpression(InternalSpelExpressionParser.java:345) at org.springframework.expression.spel.standard.InternalSpelExpressionParser.eatPowerIncDecExpression(InternalSpelExpressionParser.java:304) at org.springframework.expression.spel.standard.InternalSpelExpressionParser.eatProductExpression(InternalSpelExpressionParser.java:282) at org.springframework.expression.spel.standard.InternalSpelExpressionParser.eatSumExpression(InternalSpelExpressionParser.java:264) at org.springframework.expression.spel.standard.InternalSpelExpressionParser.eatRelationalExpression(InternalSpelExpressionParser.java:218) at org.springframework.expression.spel.standard.InternalSpelExpressionParser.eatLogicalAndExpression(InternalSpelExpressionParser.java:205) at org.springframework.expression.spel.standard.InternalSpelExpressionParser.eatLogicalOrExpression(InternalSpelExpressionParser.java:192) at org.springframework.expression.spel.standard.InternalSpelExpressionParser.eatExpression(InternalSpelExpressionParser.java:153) at org.springframework.expression.spel.standard.InternalSpelExpressionParser.doParseExpression(InternalSpelExpressionParser.java:131) at org.springframework.expression.spel.standard.SpelExpressionParser.doParseExpression(SpelExpressionParser.java:61) at org.springframework.expression.spel.standard.SpelExpressionParser.doParseExpression(SpelExpressionParser.java:33) at org.springframework.expression.common.TemplateAwareExpressionParser.parseExpression(TemplateAwareExpressionParser.java:52) at org.springframework.expression.common.TemplateAwareExpressionParser.parseExpression(TemplateAwareExpressionParser.java:43) at org.springframework.context.expression.CachedExpressionEvaluator.getExpression(CachedExpressionEvaluator.java:88) at org.springframework.cache.interceptor.CacheOperationExpressionEvaluator.key(CacheOperationExpressionEvaluator.java:104) at org.springframework.cache.interceptor.CacheAspectSupport$CacheOperationContext.generateKey(CacheAspectSupport.java:778) at org.springframework.cache.interceptor.CacheAspectSupport.generateKey(CacheAspectSupport.java:575) at org.springframework.cache.interceptor.CacheAspectSupport.findCachedItem(CacheAspectSupport.java:518) at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:401) at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:345) at org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:61) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688) at com.emax.MyService$$EnhancerBySpringCGLIB$$4de73e25.getEnterpriseByEntId(<generated>) at com.emax.MyServiceTest.getEnterpriseByEntId(MyServiceTest.java:21)View Code
identifier、lcurly都是什麼?一臉懵逼。
順著stacktrace點進去看源碼,才確定lcurly表示左大括弧“{”。看來不能用“{”。下麵是正確答案:
@Cacheable(cacheNames = ENTERPRISE_CACHE_KEY, key = "T(com.emax.common.RestApiSignUtil).foo(#root.args[0])")
在SpEL中可以調用類的方法,足見SpEL的強大!
擴展:@Cacheable中SpEL的用法列舉
// 下麵方式可以同時設置兩個緩存; 取參數可以用#param形式
@Cacheable(cacheNames = {ENTERPRISE_CACHE_KEY, "test-another-key"}, key = "#enterpriseId eq 0 ? 0: #enterpriseId")
public Result baseEnterpriseByEntId(Long enterpriseId) {...}
-------------------------------------------------
// #root代表的是spring-context-***.jar中的CacheExpressionRootObject,該類里有Object[] args屬性及其getter方法。
@Cacheable(cacheNames = ENTERPRISE_CACHE_KEY, key = "#root.args[0]<=0? 0 : #root.args[0]")
public Result getEnterpriseByEntId1(Long enterpriseId) {...}
-------------------------------------------------
// SpEL中調用外部類函數
@Cacheable(cacheNames = ENTERPRISE_CACHE_KEY, key = "T(com.emax.common.MyUtil).foo(#root.args[0])")
public Result getEnterpriseByEntId(Long enterpriseId) {...}
// SpEL中調用外部類函數--- 設置緩存key常用的套路:當緩存key包含一個對象時,則做md5
@Cacheable(cacheNames = ENTERPRISE_CACHE_KEY, key = "T(com.emax.common.Md5Util).sign(T(com.alibaba.fastjson.JSON).toJSONString(#root.args[0]))")
public Result getEnterpriseByEntId2(UserAccountVo userAccountVo, Long enterpriseId) {...}
當看到一些不好的代碼時,會發現我還算優秀;當看到優秀的代碼時,也才意識到持續學習的重要!--buguge
本文來自博客園,轉載請註明原文鏈接:https://www.cnblogs.com/buguge/p/16782597.html