这里要先注意2个概念:
buffer和cache,很多人会讲这两个概念混用。但其实这是两个概念!
buffer:一般是指存储临时数据的实体。只能读写一次,对于程序员来说buffer是可见的,比如TCB中,接收tcp数据的buffer。
cache:对于程序员来说是不可见的。允许多次获取相同的数据。这也就是EhCache不叫EhBuffer的原因。
程序结构如下:
首先来看下pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.10.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
下面是EhCache的配置
ehcache的配置文件需要放到资源文件下面,如上图的目录结构。
新建ehcache.xml内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">
<!-- default cache configurations if no cache configuration is defined -->
<defaultCache eternal="true" maxElementsInMemory="100"
overflowToDisk="false" memoryStoreEvictionPolicy="LFU" />
<!-- define our own cache configuration -->
<cache name="employee" maxElementsInMemory="10000"
eternal="false" overflowToDisk="false" memoryStoreEvictionPolicy="LFU" />
</ehcache>
上面的xml配置了自定义的缓存配置,还指定了放入缓存的元素的最大个数。以及内存回收策略采用LFU(最不长使用)。并且还设置了如果内存满了要不要存到磁盘上。
下面是在application.properties中指定ehcache.xml文件路径:
spring.cache.ehcache.config=classpath:ehcache.xml
下面创建一个实体类,缓存中保存的就是这个实体类的数据(逻辑上是一个对象,物理上得看EhCache的存储规则)
Employee.java
@Data
public class Employee {
private int id;
private String name;
private String role;
public Employee() {
}
public Employee(int id, String name, String role) {
this.id = id;
this.name = name;
this.role = role;
}
}
下面是缓存服务层的代码:
@Service
public class EmployeeService {
@Cacheable(value = "employee")
public List<Employee> getListOfEmployees(){
System.out.println("getListOfEmployees is running...");
List<Employee> employees = new ArrayList<Employee>(4);
employees.add(new Employee(1000, "Sumit", "Manager"));
employees.add(new Employee(1001, "Souvik", "Java Developer"));
employees.add(new Employee(1002, "Liton", "SQl Developer"));
employees.add(new Employee(1003, "Debina", "Leader"));
return employees;
}
@Cacheable(value = "employee", key = "#name")
public Employee findEmployeeByName(String name, List<Employee> employees) {
System.out.println("findEmployeeByName is running...");
for (Employee emp : employees) {
if (emp.getName().equalsIgnoreCase(name)) {
return emp;
}
}
return null;
}
}
@Cacheable:这个注解和ehcache.xml文件对应。如value为employee对应ehcache.xml中的
下面是启动类DemoApplication.java
@EnableCaching
@SpringBootApplication
public class DemoApplication implements CommandLineRunner {
@Autowired
private EmployeeService employeeService;
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
List<Employee> listOfEmployees = employeeService.getListOfEmployees();
System.out.println(listOfEmployees);
System.out.println("---------------------------------------------------");
listOfEmployees = employeeService.getListOfEmployees();
System.out.println(listOfEmployees);
System.out.println("---------------------------------------------------");
Employee employee = employeeService.findEmployeeByName("Sumit", listOfEmployees);
System.out.println(employee);
System.out.println("---------------------------------------------------");
employee = employeeService.findEmployeeByName("Sumit", listOfEmployees);
System.out.println(employee);
System.out.println("---------------------------------------------------");
employee = employeeService.findEmployeeByName("Liton", listOfEmployees);
System.out.println(employee);
System.out.println("---------------------------------------------------");
}
}
程序运行结果如下:
可见,前两次调用一样的数据,第二次是直接从缓存中拿的。
源码打包下载地址:
https://github.com/fengfanchen/Java/tree/master/ehcacheDemo