您的位置:首页 > 汽车 > 新车 > 手机上怎么制作网站_设计本和游戏本区别_产品推广文案怎么写_seo公司推广宣传

手机上怎么制作网站_设计本和游戏本区别_产品推广文案怎么写_seo公司推广宣传

2024/12/28 0:45:38 来源:https://blog.csdn.net/qq_34207422/article/details/144647534  浏览:    关键词:手机上怎么制作网站_设计本和游戏本区别_产品推广文案怎么写_seo公司推广宣传
手机上怎么制作网站_设计本和游戏本区别_产品推广文案怎么写_seo公司推广宣传

1、概述

Spring Cache是Spring框架提供的一个缓存抽象层,旨在简化应用程序中的缓存管理。通过使用Spring Cache,开发者可以轻松地将缓存机制集成到业务逻辑中,而无需关心具体的缓存实现细节。

Spring Cache支持多种缓存提供者(如EhCache、Caffeine、Redis、Hazelcast等),并且提供了统一的API来操作缓存。

Spring Cache的主要目标是减少对后端数据源(如数据库、远程服务等)的访问次数,从而提高应用的性能和响应速度。它通过缓存计算结果或查询结果,避免重复执行相同的业务逻辑或数据库查询。

2、Spring Cache的核心概念

(1)、CacheManager

CacheManager是Spring Cache的核心接口之一,负责管理多个Cache实例。每个Cache实例对应一个缓存区域(cache region),用于存储特定类型的缓存数据。
CacheManager负责创建、获取和管理这些缓存区域。

常见的 CacheManager 实现包括:

  • ConcurrentMapCacheManager:基于内存的缓存,默认使用ConcurrentHashMap。
  • EhCacheCacheManager:基于EhCache的缓存。
  • CaffeineCacheManager:基于Caffeine的缓存。
  • RedisCacheManager:基于Redis的分布式缓存。
  • HazelcastCacheManager:基于Hazelcast的分布式缓存。

(2)、Cache

Cache接口表示一个具体的缓存区域,负责存储和检索缓存数据。每个Cache实例通常与一个命名空间相关联,例如user-cache或product-cache。
Cache提供了基本的缓存操作,如get()、put()和evict()。

(3)、@Cacheable

@Cacheable注解用于标记需要缓存的方法。当方法被调用时,Spring Cache会首先检查缓存中是否存在相同参数的结果。如果存在,则直接返回缓存中的结果,此时不会执行方法中的代码;如果不存在,则执行方法并将结果存入缓存。
示例:

@Cacheable(value = "user-cache", key = "id")
public User getUserById(Long id) {// 查询数据库或远程服务return userRepository.findById(id).orElse(null);
}

解释:

  • value:指定缓存的名称,即缓存区域的名称。你可以为不同的业务逻辑配置不同的缓存区域。
  • key:指定缓存的键生成策略。默认情况下,Spring Cache会根据方法参数自动生成缓存键。你也可以使用SpEL(Spring Expression Language)来定义更复杂的键生成规则。
  • condition:指定缓存条件。只有当条件为true时,才会将结果存入缓存。
  • unless:指定不缓存的条件。即使方法执行成功,只有当条件为false时,才会将结果存入缓存。

@Cacheable 注意的点:
1、当方法中抛出异常时,不会缓存任何数据。
2、当方法中返回null时,默认情况下不会缓存null,但是可以通过配置cache-null-values属性实现缓存null。
例如:

@Cacheable(value = "user-cache", key = "id", cache-null-values = true)
public User getUserById(Long id) {// 查询数据库或远程服务return userRepository.findById(id).orElse(null);
}

3、当方法中存在不确定因素时,不建议使用@Cacheable注解。
如:方法中你返回了对象,同时也打印数据信息到日志中。第一次请求会按照你的预期执行。但第二次请求会直接走缓存,不会走方法,从而造成无法打印日志。
所以在使用@Cacheable注解时,方法内建议使用最少且确定的查询操作。可以mapper文件中执行,如果有其他操作建议放在之前的service中去完成。

4、假设我们只想缓存非空的用户信息,使用unless示例。
注意unless是指定不缓存的条件,这里设置result==null,实际会缓存result!=null的数据。
示例:

@Cacheable(value = "user-cache", key = "id", unless = "result == null")
public User getUserById(Long id) {// 查询数据库或远程服务return userRepository.findById(id).orElse(null);
}

5、带条件的缓存condition
假设我们只在用户年龄大于18岁时缓存用户信息
示例:

@Cacheable(value = "user-cache", key = "id", condition = "id > 18")
public User getUserById(Long id) {// 查询数据库或远程服务return userRepository.findById(id).orElse(null);
}

6、指定缓存key的格式
可以使用SpEL表达式来组合多个参数,生成更复杂的缓存键
示例:

@Cacheable(value = "user-cache", key = "id + '_' + username")
public User getUserByIdAndUsername(Long id, String username) {// 查询数据库或远程服务return userRepository.findByIdAndUsername(id, username).orElse(null);
}

(4)、@CachePut

@CachePut注解用于更新缓存中的数据。与@Cacheable不同,@CachePut总是会执行方法,并将结果存入缓存。它通常用于更新缓存中的数据,而不影响方法的正常执行。
示例:

@CachePut(value = "user-cache", key = "user.id")
public User updateUser(User user) {// 更新数据库或远程服务userRepository.save(user);return user;
}

解释:

  • value:指定缓存的名称。
  • key:指定缓存的键生成策略。
  • condition:指定缓存条件。

(5)、@CacheEvict

@CacheEvict注解用于清除缓存中的数据。它可以用于删除单个缓存条目,也可以清除整个缓存区域。它通常用于在数据发生变更时清理过期的缓存数据。
示例:

@CacheEvict(value = "user-cache", key = "id")
public void deleteUser(Long id) {// 删除数据库或远程服务中的数据userRepository.deleteById(id);
}

解释:

  • value:指定缓存的名称。
  • key:指定要清除的缓存条目的键。
  • allEntries:如果设置为true,则清除整个缓存区域中的所有条目。
  • beforeInvocation:如果设置为 true,则在方法执行之前清除缓存;否则,在方法执行之后清除缓存。

(6)、@Caching

@Caching注解允许你组合多个缓存注解(如@Cacheable、@CachePut和@CacheEvict),以便在同一方法上应用多个缓存策略。
示例1:
保存user-cache中的键,同时删除user-stats-cache中的键

@Caching(cacheable = @Cacheable(value = "user-cache", key = "id"),evict = @CacheEvict(value = "user-stats-cache", key = "id")
)
public User getUserById(Long id) {// 查询数据库或远程服务return userRepository.findById(id).orElse(null);
}

示例2:
一条信息保存到多个缓存区域。

@Caching(cacheable = {@Cacheable(value = "user-cache", key = "id"),  // 缓存到 user-cache@Cacheable(value = "admin-cache", key = "id", condition = "user.isAdmin()")})public User getUserById(Long id) {return userRepository.findById(id).orElse(null);}

3、Spring Cache的工作原理

1、拦截方法调用:当调用带有缓存注解的方法时,Spring AOP会拦截该方法的执行。
2、检查缓存:Spring Cache会根据注解中的配置(如@Cacheable)检查缓存中是否存在相同参数的结果。

  • 如果存在缓存结果,则直接返回缓存中的数据,跳过方法的实际执行。
  • 如果不存在缓存结果,则继续执行方法。
    3、执行方法:如果缓存中没有找到结果,Spring Cache会执行方法,并将结果存入缓存。
    4、更新或清除缓存:根据注解的配置(如@CachePut或@CacheEvict),Spring Cache可能会在方法执行前后更新或清除缓存。

4、集成Spring Cache

(1)、启用缓存支持

要在Spring Boot项目中启用缓存支持,首先需要在主类或配置类上添加@EnableCaching注解。
示例:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;@SpringBootApplication
@EnableCaching
public class CacheApplication {public static void main(String[] args) {SpringApplication.run(CacheApplication.class, args);}
}

(2)、选择缓存提供者

Spring Cache支持多种缓存提供者。你可以根据需求选择合适的缓存实现。这里以Redis为例。
首先,添加 Redis 的依赖:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId>
</dependency>

然后,配置Redis缓存管理器(application.yml):

spring:cache:type: redis    // 指定spring Cache的方法为Redis(重点)redis:host: localhostport: 6379timeout: 5000   连接超时时间lettuce:pool:max-active: 8max-idle: 8min-idle: 0redis:cache:time-to-live: 60000   默认缓存过期时间为 60 秒(毫秒)

(3)、编写配置类

这里配置类主要是为了设置合理的序列化,以及针对不同域的key设置不同的过期时间。

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.CacheErrorHandler;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.*;import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.time.Duration;@Slf4j
@Configuration
@EnableCaching
@EnableConfigurationProperties(RedisProperties.class)
public class CacheConfig extends CachingConfigurerSupport {private static final FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);//缓存管理器。可以管理多个缓存//只有CacheManger才能扫描到cacheable注解//spring提供了缓存支持Cache接口,实现了很多个缓存类,其中包括RedisCache。但是我们需要对其进行配置,这里就是配置RedisCache@Beanpublic CacheManager cacheManager(RedisConnectionFactory connectionFactory) {RedisCacheManager cacheManager = RedisCacheManager.RedisCacheManagerBuilder//Redis链接工厂.fromConnectionFactory(connectionFactory)//缓存配置 通用配置  默认存储一小时.cacheDefaults(getCacheConfigurationWithTtl(Duration.ofHours(1)))//配置同步修改或删除  put/evict.transactionAware()//对于不同的cacheName我们可以设置不同的过期时间
//                .withCacheConfiguration("app:",getCacheConfigurationWithTtl(Duration.ofHours(5))).withCacheConfiguration("user:",getCacheConfigurationWithTtl(Duration.ofHours(2))).build();return cacheManager;}//缓存的基本配置对象private   RedisCacheConfiguration getCacheConfigurationWithTtl(Duration duration) {return RedisCacheConfiguration.defaultCacheConfig()//设置key value的序列化方式// 设置key为String.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))// 设置value 为自动转Json的Object.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(fastJsonRedisSerializer))// 不缓存null.disableCachingNullValues()// 设置缓存的过期时间.entryTtl(duration);}//缓存的异常处理@Bean@Overridepublic CacheErrorHandler errorHandler() {// 异常处理,当Redis发生异常时,打印日志,但是程序正常走log.info("初始化 -> [{}]", "Redis CacheErrorHandler");return new CacheErrorHandler() {@Overridepublic void handleCacheGetError(RuntimeException e, Cache cache, Object key) {log.error("Redis occur handleCacheGetError:key -> [{}]", key, e);}@Overridepublic void handleCachePutError(RuntimeException e, Cache cache, Object key, Object value) {log.error("Redis occur handleCachePutError:key -> [{}];value -> [{}]", key, value, e);}@Overridepublic void handleCacheEvictError(RuntimeException e, Cache cache, Object key) {log.error("Redis occur handleCacheEvictError:key -> [{}]", key, e);}@Overridepublic void handleCacheClearError(RuntimeException e, Cache cache) {log.error("Redis occur handleCacheClearError:", e);}};}/** @Override@Bean("myKeyGenerator")   // 自定义key的生成策略public KeyGenerator keyGenerator() {return new KeyGenerator() {@Overridepublic Object generate(Object target, Method method, Object... params) {StringBuffer sb = new StringBuffer();sb.append(target.getClass().getName());sb.append(method.getName());for (Object obj : params) {sb.append(obj.toString());}return sb.toString();}};
} 
**/
}

(4)、编写业务,使用注解

在业务需要的mapper文件中定义方法,参考上诉中的注解即使用示例就可以了。

5、Spring Cache实践建议

- 合理选择缓存提供者:根据应用场景选择合适的缓存提供者。对于单机应用,可以选择内存缓存(如Caffeine);对于分布式应用,可以选择分布式缓存(如Redis)。
- 避免缓存雪崩:缓存雪崩是指大量缓存条目同时失效,导致短时间内大量请求直接打到后端数据源。可以通过设置不同的TTL或使用缓存预热机制来避免缓存雪崩。
- 避免缓存穿透:缓存穿透是指查询的缓存键不存在,且后端数据源也没有对应的数据。可以通过设置默认值或使用布隆过滤器来避免缓存穿透。
- 避免缓存击穿:缓存击穿是指某个热点数据恰好在缓存失效时,大量请求同时访问该数据,导致后端数据源压力过大。可以通过加锁或使用互斥锁机制来避免缓存击穿。

  • 定期清理无效缓存:定期清理不再使用的缓存条目,避免缓存占用过多内存资源。

6、总结

Spring Cache是一个强大且灵活的缓存框架,能够显著提升应用的性能和响应速度。通过使用@Cacheable、@CachePut和@CacheEvict等注解,开发者可以轻松地将缓存机制集成到业务逻辑中,而无需关心具体的缓存实现细节。Spring Cache支持多种缓存提供者,开发者可以根据实际需求选择合适的缓存方案。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com