《JavaEE开发的颠覆者: Spring Boot实战》系列读书笔记
Spring boot的缓存机制
@Cacheable、@CachePut、@CacheEvit都有value属性,指定的是要使用的缓存名称;key属性指定的是 数据在缓存中的存储的键。
开启声名式缓存支持十分简单,只需在配置类上使用@EnableCaching注解即可。
在Spring Boot环境下,使用缓存技术只需在项目中导入相关缓存技术的依赖包,并在配置类使用@EnableCaching开启缓存支持即可。
使用JPA对mysql进行缓存操作。
添加maven依赖
- 主要是需要加入jpa和mysql。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>
- 配置mysql和jpa
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/XX?\
useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&failOverReadOnly=false
spring.datasource.username=XX
spring.datasource.password=XX
mybatis.configuration.map-underscore-to-camel-case=true
server.port=8080
server层
/**
* /@CachePut缓存新增的或更新的数据到缓存,其中缓存名称为cityinfocache,数据的key是cityInfo的id。
* @param cityInfo
* @return
*/
@Override
@Cacheable(value = "cityinfocache",key="#cityInfo.id")
public CityInfo saveCity(CityInfo cityInfo) {
cityRepository.save(cityInfo);
log.info("为" + cityInfo.getId() + "数据做了缓存");
return cityInfo;
}
/**
* //@CacheEvict从缓存cityInfo中删除key为id的数据。
* @param id
*/
@Override
@CacheEvict(value = "cityinfocache")
public void remove(int id) {
log.info("删除了" + id + "数据缓存");
cityRepository.deleteById(id);
}
controller层
/**
* 结合mysql,测试多次查询是否重复调用方法
* @return
*/
@RequestMapping(value = "savedb")
public Result<CityInfo> SaveDb(@RequestBody CityInfo cityInfo) {
CityInfo info = cityInfoDbService.saveCity(cityInfo);
return new Result<CityInfo>(info);
}
/**
* 结合mysql,测试删除
* @return
*/
@RequestMapping(value = "deletedb/{key}")
public Result<CityInfo> DeleteDb(@PathVariable("key") int key) {
CityInfo info = new CityInfo();
cityInfoDbService.remove(key);
return new Result<CityInfo>(info);
}
当被缓存的数据被更新的时候,可以使用@CacheEvict来清除缓存,则可以保证缓存的数据是最新的
redis简介
- redis是一种NOSQL数据库(非关系型的数据库),一个开源的,先进的 key-value存储可用于构建高性能的存储解决方案。它支持数据结构有字符串,哈希,列表,集合等丰富的数据类型。
- 在 Spring Boot 中,默认集成的Redis 就是 Spring Data Redis,默认底层的连接池使用了 lettuce ,开发者可以自行修改为自己的熟悉的,例如 Jedis。
添加redis,使用Mysql+redis进行操作。
添加maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
添加配置
spring.redis.database=0
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=
spring.redis.pool.max-active=8
spring.redis.pool.max-wait=-1
spring.redis.pool.max-idle=8
spring.redis.pool.min-idle=0
spring.redis.timeout=5000
Redis缓存配置
@Configuration
@EnableCaching//启用缓存
public class RedisConfig extends CachingConfigurerSupport{
/**
* 注入 RedisConnectionFactory
*/
@Autowired
RedisConnectionFactory redisConnectionFactory;
/**
* 实例化 RedisTemplate 对象
*
* @return
*/
@Bean
public RedisTemplate<String, Object> functionDomainRedisTemplate() {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
initDomainRedisTemplate(redisTemplate, redisConnectionFactory);
return redisTemplate;
}
/**
* 设置数据存入 redis 的序列化方式
*
* @param redisTemplate
* @param factory
*/
private void initDomainRedisTemplate(RedisTemplate<String, Object> redisTemplate, RedisConnectionFactory factory) {
//定义key生成策略
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new JdkSerializationRedisSerializer());
redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
redisTemplate.setConnectionFactory(factory);
}
/**
* 缓存管理器
* @param redisTemplate
* @return
*/
@Bean
public CacheManager cacheManager(RedisTemplate<?,?> redisTemplate) {
CacheManager cacheManager = new RedisCacheManager(redisTemplate);
return cacheManager;
}
/**
* 实例化 HashOperations 对象,可以使用 Hash 类型操作
*
* @param redisTemplate
* @return
*/
@Bean
public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForHash();
}
/**
* 实例化 ValueOperations 对象,可以使用 String 操作
*
* @param redisTemplate
* @return
*/
@Bean
public ValueOperations<String, Object> valueOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForValue();
}
/**
* 实例化 ListOperations 对象,可以使用 List 操作
*
* @param redisTemplate
* @return
*/
@Bean
public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForList();
}
/**
* 实例化 SetOperations 对象,可以使用 Set 操作
*
* @param redisTemplate
* @return
*/
@Bean
public SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForSet();
}
/**
* 实例化 ZSetOperations 对象,可以使用 ZSet 操作
*
* @param redisTemplate
* @return
*/
@Bean
public ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForZSet();
}
}
创建实体类,注意实现Serializable序列化:
@Entity
@Table(name="city")
public class CityInfo implements Serializable {
private static final long serialVersionUID = 2845294956907027149L;
private String redisKey;
//redis中的key
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String city;
public CityInfo() {
}
public CityInfo(int id, String city) {
this.id = id;
this.city = city;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getRedisKey() {
return redisKey;
}
public void setRedisKey(String redisKey) {
this.redisKey = redisKey;
}
}
定义JPA接口:
@Repository
public interface CityRepository extends JpaRepository<CityInfo,Integer> {
}
定义Service层
/**
* 根据Id查询城市信息
* @param id
* @return
*/
public CityInfo findById(Integer id);
/**
* 查询所有城市信息
* @return
*/
public List<CityInfo> findAll();
/**
* 添加或修改城市信息
* @param user
*/
public void save(CityInfo user);
/**
* 根据Id删除城市信息
* @param id
*/
public void delete(Integer id);
定义Service接口实现类ServiceImpl,在需要缓存的接口上添加注解
//allEntries 清空缓存所有属性 确保更新后缓存刷新
@CacheEvict(value="cityCache", allEntries=true)
@Override
public void save(CityInfo cityInfo) {
// TODO Auto-generated method stub
cityRepository.save(cityInfo);
if(cityInfo.getRedisKey()==null||"".equals(cityInfo.getRedisKey().trim())){
cityInfo.setRedisKey(String.valueOf(cityInfo.getId()));
cityRepository.save(cityInfo);
}
cityRedisService.put(cityInfo.getRedisKey(), cityInfo, -1);
}
//allEntries 清空缓存所有属性 确保更新后缓存刷新
@CacheEvict(value="cityCache", allEntries=true)
@Override
public void delete(Integer id) {
// TODO Auto-generated method stub
CityInfo cityInfo=cityRepository.findById(id).get();
cityRedisService.remove(cityInfo.getRedisKey());
cityRepository.deleteById(id);
}
controller层
/**
* 查询所有城市信息 redis
* @return
*/
@RequestMapping("/findAll")
public List<CityInfo> findAll(){
return cityInfoRdService.findAll();
}