注解参数解释:
value :缓存的名称(相当于组名),在 spring 配置文件中定义,必须指定至少一个 例如:
@Cacheable(value=”mycache”)
@Cacheable(value={”cache1”,”cache2”}
key :缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合 @Cacheable(value=”testcache”,key=”#userName”)
condition :缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存 @Cacheable(value=”testcache”,condition=”#userName.length()>2”)
unless:达到此条件缓存失效。使用spel编写,返回ture不走缓存。
//key是spel编写,如果不指定,会默认所有参数的集合
//key自定义方式:一是通过参数名直接指定;
// 二是通过p+数字组合,第一个参数就是p0,以此类推
..
@Cacheable(value="users", key="#id")
public User find(Integer id) {
returnnull;
}
@Cacheable(value="users", key="#p0")
public User find(Integer id) {
returnnull;
}
@Cacheable(value="users", key="#user.id")
public User find(User user) {
returnnull;
}
@Cacheable(value="users", key="#p0.id")
public User find(User user) {
returnnull;
}
//注意spel写法
@Cacheable(value = "getAllMap", key = "'getAllMap'")
public Optional<Map<Integer, Integer>> getAllMap() {
缓存存哪里:
查看项目CacheConfig 配置的地址
要看你自己配置的cacheManager是使用的redis还是本地存储
然后看看配置:
j2cache.properties或者redis.properties
示例:
## connection
redis.host=
redis.port=
redis.timeout=
redis.password=
redis.database=
redis.maxWait=
redis.maxTotal=
## properties
redis.maxIdle=80
##最小空闲数
redis.minIdle=10
##最大连接数:能够同时建立的“最大链接个数”
redis.maxTotal=500
#每次最大连接数
redis.numTestsPerEvictionRun=1024
##最大建立连接等待时间:单位ms
##当borrow一个jedis实例时,最大的等待时间,如果超过等待时间,则直接抛出JedisConnectionException;
redis.maxWait=5000
##使用连接时,检测连接是否成功
redis.testOnBorrow=true
#连接耗尽时是否阻塞,false报异常,true阻塞超时,默认true
redis.blockWhenExhausted=false
##在return给pool时,是否提前进行validate操作
redis.testOnReturn=true
##当客户端闲置多长时间后关闭连接,如果指定为0,表示关闭该功能,单位毫秒
redis.timeout=3000
#在空闲时检查有效性,默认false
redis.testWhileIdle=true
#连接的最小空闲时间,连接池中连接可空闲的时间
redis.minEvictableIdleTimeMills=30000
#释放扫描的扫描间隔,单位毫秒数;检查一次连接池中空闲的连接,把空闲时间超过minEvictableIdleTimeMillis毫秒的连接断开,直到连接池中的连接数到minIdle为止
redis.timeBetweenEvictionRunsMillis=60000
ehcache.xml
示例:
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">
<diskStore path="user.home"/>
<defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="30" timeToLiveSeconds="30"
overflowToDisk="false">
</defaultCache>
<!--
配置自定义缓存
maxElementsInMemory:缓存中允许创建的最大对象数
eternal:缓存中对象是否为永久的,如果是,超时设置将被忽略,对象从不过期。
timeToIdleSeconds:缓存数据的钝化时间,也就是在一个元素消亡之前,
两次访问时间的最大时间间隔值,这只能在元素不是永久驻留时有效,
如果该值是 0 就意味着元素可以停顿无穷长的时间。
timeToLiveSeconds:缓存数据的生存时间,也就是一个元素从构建到消亡的最大时间间隔值,
这只能在元素不是永久驻留时有效,如果该值是0就意味着元素可以停顿无穷长的时间。
overflowToDisk:内存不足时,是否启用磁盘缓存。
memoryStoreEvictionPolicy:缓存满了之后的淘汰算法。
-->
<cache name="other"
maxElementsInMemory="100000"
overflowToDisk="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="36000"
memoryStoreEvictionPolicy="LFU">
</cache>
</ehcache>
补充知识点sepl
//person类
@Data
public class Person implements Serializable {
private static final long serialVersionUID = 4305013886991449314L;
private int id;
private String username;// 用户姓名
private String sex;// 性别
private int age;
private Date birthday;// 生日
private String name;
public Person() {
}
public Person(int id, String username, Date birthday) {
this.id = id;
this.username = username;
this.birthday = birthday;
}
}
//测试类
package com.zqm.controller;
import com.zqm.vo.Person;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* @describe: Spring的SpEL可以单独使用,可以使用SpEL对表达式计算、求值。SpEL主要提供了如下三个接口(位于org.springframework.expression包):
* <p>
* ExpressionParser:该接口的实例负责解析一个SpEL表达式,返回一个Expression对象
* Expression:该接口的实例代表一个表达式
* EvaluationContext:代表计算表达式值的上下文,当SpEL表达式中含有变量时,程序将需要使用该API来计算表达式的值
* Expression实例代表一个表达式,它包含了如下方法用于计算,得到表达式的值:
* <p>
* Object getValue():计算表达式的值
* <T> T getValue(Class<T> desiredResultType):计算表达式的值,而且尝试将该表达式的值当成desiredResultType类型处理
* Object getValue(EvaluationContext context):使用指定的EvaluationContext来计算表达式的值(其中EvaluationContext相当于容器包含着Expression表达式中所需要用到的值,如果是根对象,那么连对象名称都可以省略直接使用)
* <T> T getValue(EvaluationContext context,Class<T> desiredResultType):使用指定的EvaluationContext来计算表达式的值,而且尝试将该表达式的值当成desiredResultType类型处理
* Object getValue(Object rootObject):以rootObject作为表达式的root对象来计算表达式的值
* <T> T getValue(Object rootObject,Class<T> desiredResultType):以rootObject作为表达式的root对象来计算表达式的值,而且尝试将该表达式的值当成desiredResultType类型处理
* @author:zqm
*/
public class SpelTestController {
public static void main(String[] args) {
// 创建一个ExpressionParser对象,用于解析表达式
ExpressionParser parser = new SpelExpressionParser();
// 最简单的字符串表达式
Expression exp = parser.parseExpression("'HelloWorld'");
System.out.println("'HelloWorld'的结果: " + exp.getValue());
// 调用方法的表达式
exp = parser.parseExpression("'HelloWorld'.concat('!')");
System.out.println("'HelloWorld'.concat('!')的结果: " + exp.getValue());
// 调用对象的getter方法
exp = parser.parseExpression("'HelloWorld'.bytes");
System.out.println("'HelloWorld'.bytes的结果: " + exp.getValue());
// 访问对象的属性(d相当于HelloWorld.getBytes().length)
exp = parser.parseExpression("'HelloWorld'.bytes.length");
System.out.println("'HelloWorld'.bytes.length的结果:" + exp.getValue());
// 使用构造器来创建对象
exp = parser.parseExpression("new String('helloworld')" + ".toUpperCase()");
System.out.println("new String('helloworld')" + ".toUpperCase()的结果是: " + exp.getValue(String.class));
Person person = new Person(1, "孙悟空", new Date());
exp = parser.parseExpression("name");
// 以指定对象作为root来计算表达式的值
// 相当于调用person.name表达式的值
System.out.println("以persn为root,name表达式的值是: " + exp.getValue(person, String.class));
exp = parser.parseExpression("name=='孙悟空'");
;
// 创建一个List
List<String> list = new ArrayList<>();
list.add("Java");
list.add("Spring");
// 创建一个EvaluationContext对象,作为SpEL解析变量的上下文
EvaluationContext ctx = new StandardEvaluationContext();
// 设置一个变量
ctx.setVariable("myList", list);
// 对集合的第一个元素进行赋值
parser.parseExpression("#myList[0]='我爱你中国'").getValue(ctx);
// 下面测试输出
System.out.println("List更改后的第一个元素的值为:" + list.get(0));
// 使用三目运算符
System.out.println(parser.parseExpression("#myList.size()>3 ? 'myList长度大于3':'myList长度不大于于3'").getValue(ctx));
}
}