手動編寫spring快取管理器
阿新 • • 發佈:2018-12-06
引入spring快取依賴 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>18.0</version> </dependency> package com.us.example.config; import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.guava.GuavaCacheManager; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * Created by yangyibo on 17/3/2. */ @Configuration @EnableCaching public class CacheConfig { //此方法是在容器啟動時候把所有的查詢物件放入快取中。 /*@Bean public CacheManager getCacheManager() { List<Person> personList = demoService.findAll(); //所有快取的名字 List<String> cacheNames = new ArrayList(); GuavaCacheManager cacheManager = new GuavaCacheManager(); //GuavaCacheManager 的資料結構類似 Map<String,Map<Object,Object>> map =new HashMap<>(); //將資料放入快取 personList.stream().forEach(person -> { //用person 的id cacheName String cacheName=person.getId().toString(); if(cacheManager.getCache(cacheName)==null){ //為每一個person 如果不存在,建立一個新的快取物件 cacheNames.add(cacheName); cacheManager.setCacheNames(cacheNames); } Cache cache = cacheManager.getCache(cacheName); //快取物件用person的id當作快取的key 用person 當作快取的value cache.put(person.getId(),person); System.out.println("為 ID 為"+cacheName+ "的person 資料做了快取"); }); return cacheManager; }*/ //此方法在容器啟動時候只是初始化快取管理器 @Bean public GuavaCacheManager getCacheManager() { //建立快取管理器 GuavaCacheManager cacheManager = new GuavaCacheManager(); //GuavaCacheManager 的資料結構類似 Map<String,Map<Object,Object>> map =new HashMap<>(); return cacheManager; } }
二:
初始化資料來源 package com.us.example.config; /** * Created by yangyibo on 17/1/13. */ import java.beans.PropertyVetoException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.env.Environment; import com.mchange.v2.c3p0.ComboPooledDataSource; @Configuration public class DBConfig { @Autowired private Environment env; @Bean(name="dataSource") public ComboPooledDataSource dataSource() throws PropertyVetoException { ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setDriverClass(env.getProperty("ms.db.driverClassName")); dataSource.setJdbcUrl(env.getProperty("ms.db.url")); dataSource.setUser(env.getProperty("ms.db.username")); dataSource.setPassword(env.getProperty("ms.db.password")); dataSource.setMaxPoolSize(20); dataSource.setMinPoolSize(5); dataSource.setInitialPoolSize(10); dataSource.setMaxIdleTime(300); dataSource.setAcquireIncrement(5); dataSource.setIdleConnectionTestPeriod(60); return dataSource; } }
三:配置JPA持久層配置類
package com.us.example.config; import java.util.HashMap; import java.util.Map; import javax.persistence.EntityManagerFactory; import javax.sql.DataSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; /** * Created by yangyibo on 17/1/13. */ @Configuration @EnableJpaRepositories("com.us.example.dao") @EnableTransactionManagement @ComponentScan public class JpaConfig { @Autowired private DataSource dataSource; @Bean public EntityManagerFactory entityManagerFactory() { HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); //vendorAdapter.setShowSql(true); //vendorAdapter.setGenerateDdl(true); LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); factory.setJpaVendorAdapter(vendorAdapter); factory.setPackagesToScan("com.us.example.bean"); factory.setDataSource(dataSource); Map<String, Object> jpaProperties = new HashMap<>(); jpaProperties.put("hibernate.ejb.naming_strategy","org.hibernate.cfg.ImprovedNamingStrategy"); jpaProperties.put("hibernate.jdbc.batch_size",50); //jpaProperties.put("hibernate.show_sql",true); factory.setJpaPropertyMap(jpaProperties); factory.afterPropertiesSet(); return factory.getObject(); } @Bean public PlatformTransactionManager transactionManager() { JpaTransactionManager txManager = new JpaTransactionManager(); txManager.setEntityManagerFactory(entityManagerFactory()); return txManager; } }
四:查詢測試首次查詢走資料庫。然後快取物件。再次查詢從快取中取。命中這不走資料庫
package com.us.example.service;
import com.us.example.bean.Person;
import com.us.example.dao.PersonRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.guava.GuavaCacheManager;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
* Created by yangyibo on 17/3/2.
*/
@Service
public class PersonService {
@Autowired
private GuavaCacheManager cacheManager;
@Autowired
private PersonRepository personRepository;
public Person findOne(Long id) {
Person person = getCache(id, cacheManager);
if (person != null) {
System.out.println("從快取中取出:" + person.toString());
} else {
person = personRepository.findOne(id);
System.out.println("從資料庫中取出:" + person.toString());
putCache(person);
System.out.println("物件放入快取中:" + person.toString());
}
return person;
}
public Person save(Person person) {
Person p = personRepository.save(person);
return p;
}
public Person getCache(Long id, CacheManager cacheManager) {
Person person = null;
Cache cache = cacheManager.getCache(id.toString());
Cache.ValueWrapper valueWrapper = cache.get(id);
if(valueWrapper!=null){
person = (Person) valueWrapper.get();
}
return person;
}
public void putCache(Person person) {
List<String> cacheNames = new ArrayList();
String cacheName=person.getId().toString();
if(cacheManager.getCache(cacheName)==null){
//為每一個person 如果不存在,建立一個新的快取物件
cacheNames.add(cacheName);
cacheManager.setCacheNames(cacheNames);
}
Cache cache = cacheManager.getCache(cacheName);
cache.put(person.getId(),person);
}
}
紅色標註的程式碼即為快取的具體邏輯