spring cache example
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
package org.spring.cache.example;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class Employee implements Serializable{
|
||||
|
||||
private int id;
|
||||
private String empname;
|
||||
private int age;
|
||||
private String phone;
|
||||
|
||||
public Employee() {
|
||||
}
|
||||
|
||||
public Employee(int id, String empname, int age, String phone) {
|
||||
super();
|
||||
this.id = id;
|
||||
this.empname = empname;
|
||||
this.age = age;
|
||||
this.phone = phone;
|
||||
}
|
||||
|
||||
public Employee(String empname) {
|
||||
super();
|
||||
this.empname = empname;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
public String getEmpname() {
|
||||
return empname;
|
||||
}
|
||||
public void setEmpname(String empname) {
|
||||
this.empname = empname;
|
||||
}
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
public String getPhone() {
|
||||
return phone;
|
||||
}
|
||||
public void setPhone(String phone) {
|
||||
this.phone = phone;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Employee [id=" + id + ", empname=" + empname + ", age=" + age
|
||||
+ ", phone=" + phone + "]";
|
||||
}
|
||||
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
package org.spring.cache.example;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.CachePut;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class EmployeeService {
|
||||
|
||||
Logger logger = LoggerFactory.getLogger(getClass());
|
||||
|
||||
/**
|
||||
* @Cacheable:负责将方法的返回值加入到缓存中
|
||||
*
|
||||
* @CacheEvict:负责清除缓存
|
||||
*
|
||||
* @Cacheable 支持如下几个参数:
|
||||
*
|
||||
* value:缓存位置名称,不能为空,如果使用EHCache,就是ehcache.xml中声明的cache的name
|
||||
*
|
||||
* key:缓存的key,默认为空,既表示使用方法的参数类型及参数值作为key,支持SpEL
|
||||
*
|
||||
* condition:触发条件,只有满足条件的情况才会加入缓存,默认为空,既表示全部都加入缓存,支持SpEL
|
||||
*
|
||||
* @CacheEvict 支持如下几个参数:
|
||||
*
|
||||
* value:缓存位置名称,不能为空,同上
|
||||
*
|
||||
* key:缓存的key,默认为空,同上
|
||||
*
|
||||
* condition:触发条件,只有满足条件的情况才会清除缓存,默认为空,支持SpEL
|
||||
*
|
||||
* allEntries:true表示清除value中的全部缓存,默认为false
|
||||
*/
|
||||
|
||||
@Cacheable(value = "employeeCache"/*,condition="#empname.length() <= 4"*/)
|
||||
// 使用了一个缓存名叫 employeeCache
|
||||
public Employee getEmployeeByName(String empname) {
|
||||
// 方法内部实现不考虑缓存逻辑,直接实现业务
|
||||
return getFromDB(empname);
|
||||
}
|
||||
|
||||
@Cacheable(value = "employeeCache", key = "#id")
|
||||
// 使用了一个缓存名为employeeCache的缓存
|
||||
public String getEmployee(Integer id) {
|
||||
logger.info("get employee called " + id);
|
||||
return "getEmployee" + id;
|
||||
}
|
||||
|
||||
@Cacheable(value = "employeeCache", key = "#id", condition = "#id <= 10")
|
||||
// 使用了一个缓存名为employeeCache的缓存,缓存id小于等于10
|
||||
public String findEmployee(Integer id) {
|
||||
logger.info("get employee called");
|
||||
return "findEmployee" + id;
|
||||
}
|
||||
|
||||
@CacheEvict(value = "employeeCache", allEntries = true)
|
||||
public List<Employee> listEmployee() {
|
||||
List<Employee> emps = new ArrayList<Employee>();
|
||||
return emps;
|
||||
}
|
||||
|
||||
@CachePut(value = "employeeCache", key = "#employee.getEmpname()")
|
||||
// 清空 employeeCache 缓存
|
||||
public void updateEmployee(Employee employee) {
|
||||
updateDB(employee);
|
||||
}
|
||||
|
||||
@CacheEvict(value = "employeeCache", allEntries = true)
|
||||
// 清空 employeeCache 缓存
|
||||
public void reload() {
|
||||
|
||||
}
|
||||
|
||||
private Employee getFromDB(String empname) {
|
||||
System.out.println("real querying db..." + empname);
|
||||
return new Employee(empname);
|
||||
}
|
||||
|
||||
private void updateDB(Employee employee) {
|
||||
System.out.println("real update db..." + employee.getEmpname());
|
||||
}
|
||||
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package org.spring.cache.example;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
@Controller
|
||||
public class WebController {
|
||||
|
||||
@Autowired
|
||||
EmployeeService employeeService;
|
||||
|
||||
@RequestMapping("/index.htm")
|
||||
public String homePage(@RequestParam(required = false) Integer id,
|
||||
HashMap<String, String> map) {
|
||||
map.put("message", employeeService.getEmployee(id));
|
||||
return "index";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ehcache>
|
||||
<diskStore path="java.io.tmpdir" />
|
||||
<cache name="employeeCache" maxElementsInMemory="10000" eternal="false"
|
||||
timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true"
|
||||
maxElementsOnDisk="10000000" diskPersistent="false"
|
||||
diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU" />
|
||||
</ehcache>
|
||||
@@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE log4j:configuration PUBLIC "-//LOGGER"
|
||||
"http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/doc-files/log4j.dtd">
|
||||
<log4j:configuration>
|
||||
|
||||
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
|
||||
<!--<param name="Threshold" value="WARN"/>-->
|
||||
<layout class="org.apache.log4j.PatternLayout">
|
||||
<param name="ConversionPattern" value="%-5p %d{ISO8601} [%C.%M - %t] [%x] - %m%n"/>
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
<appender name="LOGFILE" class="org.apache.log4j.RollingFileAppender">
|
||||
<!-- <param name="Threshold" value="INFO" /> -->
|
||||
<!-- <param name="Append" value="false" /> -->
|
||||
<param name="MaxBackupIndex" value="5"/>
|
||||
<param name="MaxFileSize" value="10MB"/>
|
||||
<param name="File" value="target/log4j.log"/>
|
||||
<layout class="org.apache.log4j.PatternLayout">
|
||||
<!-- <param name="ConversionPattern" value="%-4r [%C.%M - %t] %-5p [%x] - %m%n" /> -->
|
||||
<param name="ConversionPattern" value="%-5p %d [%t] %c: %m%n"/>
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
<logger name="org.spring.cache.example">
|
||||
<level value="DEBUG"/>
|
||||
</logger>
|
||||
|
||||
<logger name="org.springframework.web.accept">
|
||||
<level value="WARN"/>
|
||||
</logger>
|
||||
|
||||
<logger name="org.springframework">
|
||||
<level value="WARN"/>
|
||||
</logger>
|
||||
|
||||
<root>
|
||||
<level value="WARN"/>
|
||||
<appender-ref ref="CONSOLE"/>
|
||||
</root>
|
||||
|
||||
</log4j:configuration>
|
||||
@@ -0,0 +1,57 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:cache="http://www.springframework.org/schema/cache"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:p="http://www.springframework.org/schema/p"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
http://www.springframework.org/schema/context/spring-context.xsd
|
||||
http://www.springframework.org/schema/cache
|
||||
http://www.springframework.org/schema/cache/spring-cache.xsd">
|
||||
|
||||
<!-- Scans within the base package of the application for @Components to
|
||||
configure as beans -->
|
||||
<context:component-scan base-package="org.spring.cache.example" />
|
||||
|
||||
<!-- Process cache annotations -->
|
||||
<cache:annotation-driven cache-manager="cacheManager"/>
|
||||
|
||||
<bean id="viewResolver"
|
||||
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
|
||||
<property name="viewClass">
|
||||
<value>org.springframework.web.servlet.view.JstlView</value>
|
||||
</property>
|
||||
<property name="prefix" value="/WEB-INF/views/" />
|
||||
<property name="suffix" value=".jsp" />
|
||||
</bean>
|
||||
|
||||
|
||||
|
||||
<!-- Configuration for using Ehcache as the cache manager -->
|
||||
<!-- 使用ehcache配置缓存 -->
|
||||
|
||||
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager" p:cache-manager-ref="ehcache" />
|
||||
<bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" p:config-location="classpath:ehcache.xml" p:shared="true"/>
|
||||
|
||||
<!-- Configuration for using SimpleCacheManager as the cache manager -->
|
||||
<!-- 使用Spring默认的缓存方案SimpleCacheManager,其内部使用了缺省的内存存储方案 ConcurrentMapCacheFactoryBean,它是基于 java.util.concurrent.ConcurrentHashMap 的一个内存缓存实现方案。 -->
|
||||
<!--
|
||||
<bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
|
||||
<property name="caches">
|
||||
<set>
|
||||
<bean
|
||||
class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean"
|
||||
p:name="default" />
|
||||
<bean
|
||||
class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean"
|
||||
p:name="employeeCache" />
|
||||
</set>
|
||||
</property>
|
||||
</bean>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,12 @@
|
||||
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
|
||||
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<title>Cache Example</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>This is ${message }</h1>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
|
||||
|
||||
<servlet>
|
||||
<servlet-name>sample</servlet-name>
|
||||
<servlet-class>
|
||||
org.springframework.web.servlet.DispatcherServlet
|
||||
</servlet-class>
|
||||
<init-param>
|
||||
<param-name>contextConfigLocation</param-name>
|
||||
<param-value>/WEB-INF/applicationContext.xml</param-value>
|
||||
</init-param>
|
||||
<load-on-startup>1</load-on-startup>
|
||||
</servlet>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>sample</servlet-name>
|
||||
<url-pattern>/</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
</web-app>
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
package org.spring.cache.example;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
@ContextConfiguration(locations = "file:src/main/webapp/WEB-INF/applicationContext.xml")
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class EmployeeServiceTest {
|
||||
|
||||
@Autowired
|
||||
EmployeeService employeeService;
|
||||
|
||||
@Test
|
||||
public void getEmployee() {
|
||||
employeeService.getEmployee(1);
|
||||
employeeService.getEmployee(1);
|
||||
employeeService.getEmployee(2);
|
||||
employeeService.getEmployee(2);
|
||||
employeeService.getEmployee(3);
|
||||
employeeService.getEmployee(3);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Test
|
||||
public void testCache() {
|
||||
// 第一次查询,应该走数据库
|
||||
System.out.print("first query...");
|
||||
employeeService.getEmployeeByName("somebody");
|
||||
// 第二次查询,应该不查数据库,直接返回缓存的值
|
||||
System.out.print("second query...");
|
||||
employeeService.getEmployeeByName("somebody");
|
||||
System.out.println();
|
||||
|
||||
System.out.println("start testing clear cache..."); // 更新某个记录的缓存,首先构造两个账号记录,然后记录到缓存中
|
||||
Employee employee1 = employeeService.getEmployeeByName("somebody1");
|
||||
Employee employee2 = employeeService.getEmployeeByName("somebody2");
|
||||
// 开始更新其中一个
|
||||
employee1.setId(1212);
|
||||
employeeService.updateEmployee(employee1);
|
||||
employeeService.getEmployeeByName("somebody1");// 因为被更新了,所以会查询数据库
|
||||
employeeService.getEmployeeByName("somebody2");// 没有更新过,应该走缓存
|
||||
employeeService.getEmployeeByName("somebody1");// 再次查询,应该走缓存 // 更新所有缓存
|
||||
employeeService.reload();
|
||||
employeeService.getEmployeeByName("somebody1");// 应该会查询数据库
|
||||
employeeService.getEmployeeByName("somebody2");// 应该会查询数据库
|
||||
employeeService.getEmployeeByName("somebody1");// 应该走缓存
|
||||
employeeService.getEmployeeByName("somebody2");// 应该走缓存
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCacheCondition() {
|
||||
employeeService.getEmployeeByName("somebody");// 长度大于 4,不会被缓存
|
||||
employeeService.getEmployeeByName("sbd");// 长度小于 4,会被缓存
|
||||
employeeService.getEmployeeByName("somebody");// 还是查询数据库
|
||||
employeeService.getEmployeeByName("sbd");// 会从缓存返回
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCachePut() {
|
||||
Employee employee = employeeService.getEmployeeByName("someone");
|
||||
employee.setAge(18);
|
||||
employeeService.updateEmployee(employee);
|
||||
employee.setAge(28);
|
||||
employeeService.updateEmployee(employee);
|
||||
employee = employeeService.getEmployeeByName("someone");
|
||||
System.out.println(employee.getEmpname());
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user