当前位置: 首页 > news >正文

网站内链seo平面设计公司网站

网站内链seo,平面设计公司网站,新闻式软文范例,上海网站建设不好1. 项目背景 Spring Cache是Spring框架提供的一个缓存抽象层#xff0c;它简化了缓存的使用和管理。Spring Cache默认使用服务器内存#xff0c;并无法控制缓存时长#xff0c;查找缓存中的数据比较麻烦。 因此Spring Cache支持将缓存数据集成到各种缓存中间件中。本文已常…1. 项目背景 Spring Cache是Spring框架提供的一个缓存抽象层它简化了缓存的使用和管理。Spring Cache默认使用服务器内存并无法控制缓存时长查找缓存中的数据比较麻烦。 因此Spring Cache支持将缓存数据集成到各种缓存中间件中。本文已常用的Redis作为缓存中间件作为示例详细讲解项目中如何使用Cache提高系统性能。 2. Spring Cache介绍 Spring Cache是Spring框架提供的一种缓存解决方案基于AOP原理实现了基于注解的缓存功能只需要简单地加一个注解就能实现缓存功能对业务代码的侵入性很小。 使用Spring Cache的方法很简单只需要在方法上添加注解即可实现将方法返回数据存入缓存以及清理缓存等注解的使用。 2.1 主要特点 统一的缓存抽象Spring Cache为应用提供了一种统一的缓存抽象可以轻松集成各种缓存提供者如Ehcache、Redis、Caffeine等使用统一的API。注解驱动Spring Cache通过简单的注解配置如Cacheable、CachePut、CacheEvict等可以快速实现缓存功能而无需处理底层缓存逻辑。灵活性和扩展性Spring Cache允许根据业务需求自定义缓存策略如缓存的失效时间、缓存的淘汰策略等。同时它也提供了CacheManager接口和Cache接口可以实现降低对各种缓存框架的耦合。 2.2 常用注解 EnableCaching 作用开启Spring的缓存注解支持。使用场景在配置类上添加此注解以启用Spring Cache的注解处理功能。注意此注解本身并不提供缓存实现而是允许你使用Cacheable、CachePut、CacheEvict等注解来定义缓存行为。 Cacheable 作用在方法执行前检查缓存如果缓存中存在数据则直接返回否则执行方法并将结果缓存。value指定缓存的名称或名称数组。缓存名称与CacheManager中配置的缓存对应。key用于生成缓存键的表达式可选。如果不指定则默认使用方法的参数值作为键。condition条件表达式可选用于决定是否执行缓存操作。unless否定条件表达式可选用于在方法执行后决定是否缓存返回值。 Cacheable注解配置参数说明 value/cacheNames 用于指定缓存的名称或名称数组缓存名称作为缓存key的前缀。这是缓存的标识符用于在CacheManager中查找对应的缓存。value和cacheNames是互斥的即只能指定其中一个。 key 用于生成缓存键的表达式。这个键用于在缓存中唯一标识存储的值。如果不指定key则默认使用方法的参数值经过某种转换作为键。可以使用Spring Expression LanguageSpEL来编写key表达式以实现动态键的生成。 keyGenerator 指定一个自定义的键生成器实现 org.springframework.cache.interceptor.KeyGenerator 接口的类用于生成缓存的键。与 key 属性互斥二者只能选其一。如果同时指定了key和keyGenerator则会引发异常因为它们是互斥的。开发者可以编写自己的KeyGenerator实现并将其注册到Spring容器中然后在Cacheable注解中引用。 cacheManager CacheManager表示缓存管理器通过缓存管理器可以设置缓存过期时间。用于指定要使用的CacheManager。这是一个可选参数通常不需要显式指定因为Spring会默认使用配置的CacheManager。如果系统中配置了多个CacheManager则需要通过此参数指定使用哪一个。 cacheResolver 缓存解析器用于解析缓存名称并返回相应的Cache对象。这也是一个可选参数。类似于cacheManager如果系统中配置了多个缓存解析逻辑可以通过此参数指定使用哪一个。 condition 条件表达式用于决定是否执行缓存操作。这是一个可选参数。条件表达式使用SpEL编写如果表达式返回true则执行缓存操作否则不执行。 unless 否定条件表达式用于在方法执行后决定是否缓存返回值。这也是一个可选参数。与condition类似unless也使用SpEL编写但它是在方法执行后才进行评估的。如果unless表达式返回true则不缓存返回值否则缓存。 sync 是否使用异步模式进行缓存操作。这是一个可选参数通常不需要显式指定。在多线程环境中如果多个线程同时请求相同的数据并触发缓存操作使用异步模式可以避免线程阻塞和重复计算。 Cacheable注解的这些参数是互斥或相互关联的例如value和cacheNames不能同时指定key和keyGenerator也不能同时指定。此外cacheManager和cacheResolver也是互斥的因为它们都用于指定缓存的解析和管理方式。 对于前两个注解的应用 Cacheable(cacheNames cache:cacheByKey, key #id)public Integer cacheByKey(PathVariable(id) Integer id) throws InterruptedException {Thread.sleep(5000);log.info(执行了cacheByKey方法 id);return id;}看注释掉的那行取缓存名称为cache:cacheByKey参数id的值作为key最终缓存key为缓存名称“::”key例如上述代码id为123,最终的key为cache:cacheByKey::123 SpELSpring Expression Language是一种在 Spring 框架中用于处理字符串表达式的强大工具它可以实现获取对象的属性调用对象的方法操作。 单个缓存名称Cacheable(value myCache) 表示使用名为myCache的缓存。多个缓存名称Cacheable(value {cache1, cache2}) 表示方法的结果将同时缓存到cache1和cache2中。与CacheConfig结合使用如果类上使用了CacheConfig注解并且指定了cacheNames属性那么类中的方法在使用Cacheable时可以省略value属性直接使用类级别的缓存配置。 CacheEvict 作用从缓存中删除数据。value指定要删除的缓存的名称或名称数组。key用于指定要删除的缓存键可选。如果不指定则默认使用方法的参数值作为键。allEntries布尔值指定是否删除缓存中的所有条目而不是仅删除与指定键匹配的条目。beforeInvocation布尔值指定是否在方法执行之前删除缓存默认为false即在方法执行之后删除。 CachePut 作用更新缓存中的数据无论方法是否成功执行都会将结果放入缓存。value、key、condition、unless与Cacheable中的这些属性相同。 Caching 作用允许在同一个方法上组合使用多个缓存注解如Cacheable、CachePut、CacheEvict。属性包含一个或多个缓存注解。 CacheConfig 作用为类级别提供缓存相关的默认配置。cacheNames指定该类中所有方法使用的默认缓存名称或名称数组。keyGenerator指定自定义的键生成器可选。cacheManager指定要使用的CacheManager可选。 3. 示例代码 项目依赖于Redis配置这里就不多赘述了。 缓存管理器配置 定义了两个缓存管理器默认cacheManager使用Primary标注一个缓存返回值为null的管理器cacheNullManager详情看下面代码。 package com.maple.redis.config;import lombok.extern.slf4j.Slf4j; 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.context.annotation.Primary; 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.serializer.RedisSerializationContext; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer;import java.lang.reflect.Method; import java.time.Duration;/*** author 笑小枫* date 2025/1/7*/ Slf4j Configuration EnableCaching public class CacheConfig extends CachingConfigurerSupport {/*** 默认缓存管理器* 只有CacheManger才能扫描到cacheable注解* spring提供了缓存支持Cache接口实现了很多个缓存类其中包括RedisCache。但是我们需要对其进行配置这里就是配置RedisCache*/BeanPrimarypublic CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {return RedisCacheManager.RedisCacheManagerBuilder//Redis链接工厂.fromConnectionFactory(redisConnectionFactory)//缓存配置 通用配置 默认存储一小时.cacheDefaults(getCacheConfigurationWithTtl(Duration.ofHours(1)))//配置同步修改或删除 put/evict.transactionAware()//对于不同的cacheName我们可以设置不同的过期时间.withCacheConfiguration(cache2:cacheByUser, getCacheConfigurationWithTtl(Duration.ofHours(2))).build();}/*** 创建并返回一个CacheManager Bean用于管理Redis缓存。* 主要返回结果为null时使用会缓存null值缓存时间为10分钟防止缓存穿透。* 使用时通过 cacheManager cacheNullManager 指定使用该缓存管理器。*/Beanpublic CacheManager cacheNullManager(RedisConnectionFactory redisConnectionFactory) {return RedisCacheManager.RedisCacheManagerBuilder//Redis链接工厂.fromConnectionFactory(redisConnectionFactory)//缓存配置 通用配置 默认存储一小时.cacheDefaults(RedisCacheConfiguration.defaultCacheConfig()// 设置key为String.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))// 设置value 为自动转Json的Object.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(RedisSerializer.json())).entryTtl(Duration.ofMinutes(10)))//配置同步修改或删除 put/evict.transactionAware().build();}/*** 缓存的基本配置对象*/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(RedisSerializer.json()))// 不缓存null.disableCachingNullValues()// 设置缓存的过期时间.entryTtl(duration);}/*** 缓存的异常处理*/BeanOverridepublic CacheErrorHandler errorHandler() {// 异常处理当Redis发生异常时打印日志但是程序正常走log.info(初始化 - [{}], Redis CacheErrorHandler);return new CacheErrorHandler() {Overridepublic void handleCacheGetError(RuntimeException e, Cache cache, Object key) {log.error(Redis occur handleCacheGetErrorkey - [{}], key, e);}Overridepublic void handleCachePutError(RuntimeException e, Cache cache, Object key, Object value) {log.error(Redis occur handleCachePutErrorkey - [{}]value - [{}], key, value, e);}Overridepublic void handleCacheEvictError(RuntimeException e, Cache cache, Object key) {log.error(Redis occur handleCacheEvictErrorkey - [{}], key, e);}Overridepublic void handleCacheClearError(RuntimeException e, Cache cache) {log.error(Redis occur handleCacheClearError, e);}};}OverrideBean(myKeyGenerator)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();}};} } 使用案例 User对象就id、name两个字段大家随意~ package com.maple.redis.controller;import com.maple.redis.bean.User; import lombok.extern.slf4j.Slf4j; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CachePut; import org.springframework.cache.annotation.Cacheable; import org.springframework.cache.annotation.Caching; import org.springframework.web.bind.annotation.*;/*** author 笑小枫* date 2025/1/7*/ Slf4j RestController RequestMapping(/cache) public class TestCacheController {/*** 获取简单缓存数据。** p通过Cacheable注解该方法的结果会被缓存到名为cache:simpleCache的缓存中。* 如果在缓存中找到相同请求的结果将直接返回缓存的值避免重复执行方法体中的逻辑。** p方法内部使用Thread.sleep(5000)模拟了一个耗时操作*/GetMapping(/simpleCache)Cacheable(cacheNames cache:simpleCache)public String simpleCache() throws InterruptedException {Thread.sleep(5000);log.info(执行了simpleCache方法);return test;}/*** 如果缓存中存在对应的ID则直接从缓存中获取结果避免重复执行耗时操作。* 如果缓存中不存在则执行方法体中的逻辑将结果存入缓存并返回。* 方法执行过程中通过Thread.sleep模拟了一个耗时操作。*/GetMapping(/{id})Cacheable(cacheNames cache:cacheByKey, key #id)public Integer cacheByKey(PathVariable(id) Integer id) throws InterruptedException {Thread.sleep(5000);log.info(执行了cacheByKey方法 id);return id;}/*** p该方法使用Caching注解集成了多个缓存策略/p* ul* li* 当方法返回值为null时即缓存穿透情况使用名为cacheNullManager的CacheManager进行缓存处理* 缓存名称为cache2:cacheByKey缓存键为传入的用户ID并设置缓存过期时间为10分钟。* 这通过Cacheable注解的cacheManager属性指定缓存管理器unless属性设置缓存条件当结果为null时缓存。* /li* li* 当方法返回值不为null时使用默认的CacheManager进行缓存处理* 缓存名称和键的设置与上述相同但此时缓存管理器为默认配置。* 这通过另一个Cacheable注解实现其unless属性设置为当结果为null时不缓存。* /li* /ul** p在方法执行过程中通过Thread.sleep模拟了一个耗时操作。/p*/Caching(cacheable {//result为null时,属于缓存穿透情况使用cacheNullManager缓存管理器进行缓存并且设置过期时间为10分钟。Cacheable(cacheNames cache2:cacheByKey, key #id, unless #result ! null, cacheManager cacheNullManager),//result不为null时,使用默认缓存管理器进行缓存。Cacheable(cacheNames cache2:cacheByKey, key #id, unless #result null)})GetMapping(/cacheMore/{id})public User cacheMore(PathVariable(id) Integer id) throws InterruptedException {Thread.sleep(5000);if (id 100) {return null;} else {return new User(id, zhangsan);}}PostMapping(/cacheByUser)Cacheable(cacheNames cache2:cacheByUser, key #user.id)public User cacheByUser(RequestBody User user) throws InterruptedException {Thread.sleep(5000);log.info(执行了cacheByUser方法 user.getId());return user;}PostMapping(/cacheByIdAndName)Cacheable(cacheNames cache2:cacheByUser, key #user.id)public User cacheByIdAndName(RequestBody User user) throws InterruptedException {Thread.sleep(5000);log.info(执行了cacheByUser方法 user.getId());return user;}/*** 根据用户ID大于100的条件进行缓存处理。** param user 用户对象包含用户ID等信息。* return 返回传入的用户对象。* throws InterruptedException 如果线程被中断则抛出此异常。** 通过Cacheable注解实现了缓存功能当请求的用户ID大于100时会触发缓存机制。* 缓存的名称设置为cache2:cacheByUser缓存的键为传入的用户对象的ID。* 如果缓存中已存在对应的用户数据则直接从缓存中获取并返回避免重复执行耗时操作。* 如果缓存中不存在则执行方法体中的逻辑将结果存入缓存并返回。* 在方法执行过程中通过Thread.sleep模拟了一个耗时操作。*/PostMapping(/cacheByUserIdGt100)Cacheable(cacheNames cache2:cacheByUser, key #user.id, condition #user.id 100)public User cacheByUserIdGt100(RequestBody User user) throws InterruptedException {Thread.sleep(5000);log.info(执行了cacheByUser方法 user.getId());return user;}/*** 更新用户信息。* p* 使用CachePut注解将更新后的用户信息存入缓存中。* 缓存的名称设置为cache2:cacheByUser缓存的键为传入的User对象的ID。* 如果缓存中已存在对应的用户数据则更新缓存中的值如果不存在则创建新的缓存条目。* 在方法执行过程中通过Thread.sleep模拟了一个耗时操作。*/PostMapping(/updateUser)CachePut(cacheNames cache2:cacheByUser, key #user.id)public User updateUser(RequestBody User user) throws InterruptedException {Thread.sleep(5000);log.info(执行了saveUser方法 user.getId());return user;}/*** 删除指定ID的用户并从缓存中移除对应的数据。* p* 使用CacheEvict注解用于从缓存中移除指定ID的用户数据。* 缓存的名称设置为cache2:cacheByUser缓存的键为传入的用户ID。* 在执行删除操作前方法通过Thread.sleep模拟了一个耗时操作。*/DeleteMapping(/{id})CacheEvict(cacheNames cache2:cacheByUser, key #id)public void deleteUser(PathVariable(id) Integer id) throws InterruptedException {Thread.sleep(10000);log.info(执行了deleteUser方法 id);} }模拟了多种缓存使用的方式 updateUser使用CachePut对数据进行缓存或更新。deleteUser使用CacheEvict删除缓存。cacheMore根据条件选择不同的缓存管理器进行缓存数据。 简单附几张测试截图吧 第一次查询没有缓存截图 后续查询走缓存的截图 redis缓存数据格式 redis缓存数据详情 4. SpEL在Spring Cache中的应用 4.1 SpEL概述 SpEL是Spring框架提供的一种功能强大的表达式语言它能够在运行时查询和操作对象图。SpEL的语法简洁支持方法调用、字符串模板、集合操作、逻辑运算等复杂功能使得在Spring配置和代码中能够更轻松地处理复杂的逻辑和数据结构。 4.2 SpEL应用 动态生成缓存键 在Spring Cache中缓存键Key用于在缓存中唯一标识数据。通过使用SpEL表达式可以根据方法参数、返回值等动态生成缓存键。例如在Cacheable注解中可以使用key属性配合SpEL表达式来指定缓存键的生成规则。 条件缓存 Spring Cache允许通过condition属性来指定缓存的条件。当条件满足时才会执行缓存操作如缓存数据或移除缓存。 除非条件 unless属性与condition属性类似但它用于指定不执行缓存操作的条件。当unless条件满足时即使方法被调用其结果也不会被缓存。unless属性同样支持SpEL表达式。 4.3 SpEL表达式在Spring Cache中的常用变量 #参数名 表示方法参数。可以通过参数名来引用方法参数的值。例如#param1表示第一个参数的值。 #result 表示方法的返回值。在CachePut和CacheEvict注解中可以使用#result来引用方法的返回值。 #root 表示缓存表达式根对象CacheExpressionRootObject。它提供了对缓存操作上下文的访问。通过#root可以获取到缓存的详细信息如缓存名称、方法参数等。 注意 condition属性在Spring Cache中用于在方法执行前判断是否执行缓存操作并且不能引用方法的返回值而unless属性则用于在方法执行后根据返回值或其他条件来决定是否缓存数据。 5. 工作原理 Spring Cache是基于AOP原理对添加注解Cacheable的类生成代理对象在方法执行前查看是否有缓存对应的数据如果有直接返回数据如果没有调用源方法获取数据返回并缓存起来下边跟踪Spring Cache的切面类CacheAspectSupport.java中的private Object execute(final CacheOperationInvoker invoker, Method method, CacheOperationContexts contexts)方法。 Nullableprivate Object execute(final CacheOperationInvoker invoker, Method method, CacheOperationContexts contexts) {if (contexts.isSynchronized()) {CacheOperationContext context (CacheOperationContext)contexts.get(CacheableOperation.class).iterator().next();if (!this.isConditionPassing(context, CacheOperationExpressionEvaluator.NO_RESULT)) {return this.invokeOperation(invoker);}Object key this.generateKey(context, CacheOperationExpressionEvaluator.NO_RESULT);Cache cache (Cache)context.getCaches().iterator().next();try {return this.wrapCacheValue(method, this.handleSynchronizedGet(invoker, key, cache));} catch (Cache.ValueRetrievalException var10) {Cache.ValueRetrievalException ex var10;ReflectionUtils.rethrowRuntimeException(ex.getCause());}}this.processCacheEvicts(contexts.get(CacheEvictOperation.class), true, CacheOperationExpressionEvaluator.NO_RESULT);Cache.ValueWrapper cacheHit this.findCachedItem(contexts.get(CacheableOperation.class));ListCachePutRequest cachePutRequests new ArrayList();if (cacheHit null) {this.collectPutRequests(contexts.get(CacheableOperation.class), CacheOperationExpressionEvaluator.NO_RESULT, cachePutRequests);}Object cacheValue;Object returnValue;if (cacheHit ! null !this.hasCachePut(contexts)) {//如果缓存有则从缓存取cacheValue cacheHit.get();returnValue this.wrapCacheValue(method, cacheValue);} else {//缓存没有执行原始方法returnValue this.invokeOperation(invoker);cacheValue this.unwrapReturnValue(returnValue);//再存缓存}this.collectPutRequests(contexts.get(CachePutOperation.class), cacheValue, cachePutRequests);Iterator var8 cachePutRequests.iterator();while(var8.hasNext()) {CachePutRequest cachePutRequest (CachePutRequest)var8.next();cachePutRequest.apply(cacheValue);}this.processCacheEvicts(contexts.get(CacheEvictOperation.class), false, cacheValue);return returnValue;}6. 本文源码 使用Redis的过程中还会有很多问题比如缓存数据一致性缓存数据持久化内存淘汰机制缓存雪崩等等等在面试的时候也经常会用到博主整理了一份Redis常见的面试感兴趣的朋友可以看下 【面试1v1实景模拟】Redis面试官会怎么提问 本文源码https://github.com/hack-feng/maple-product/ 其中maple-redis模块即为本文的Demo源码。需要的朋友可以看下。 感兴趣的朋友可以帮忙点个star⭐⭐⭐⭐⭐后续会有更多Java相关的集成Demo让我来做你的百宝袋吧。 我是笑小枫全网皆可搜的【笑小枫】
http://www.hkea.cn/news/14300447/

相关文章:

  • 网站封面如何做的吸引人购买了网站如何使用吗
  • 新建网站怎么保存php动态页面
  • 网站注册实名制怎么做网站公司网站定制
  • 网络营销讲师seo基础知识培训视频
  • seo优化网站的注意事项大连三合一网站制作
  • 眉山建行网站如何做响应式网站视频教程
  • 孝昌县建设局网站网络规划设计师工资
  • 做旅游网站的写手厦门同安网站制作企业
  • 高平市规建设局网站打开百度首页
  • 佛山做企业网站音乐网站禁止做浅度链接
  • 如何在淘宝网做自己的网站网页界面设计使用的单位主要是
  • 家教辅导培训网站建设google play
  • 网站视频主持人哪些网站用户体验好
  • 网站备案快吗wordpress 4.5.2模板
  • h5网站制作案例分析android studio教程
  • 搜索引擎网站排行榜网络平台怎么挣钱的
  • 自己电脑做服务器网站吗以下属于免费推广的方式是
  • 旅游网站建设相关报价表格巴里坤网站建设
  • wordpress历史版本石家庄关键词优化软件
  • 宁波网站建设服务报价0基础做电商从何下手
  • 英文网站标题国内工业设计网站
  • 查找网站域名现在都用什么网站找事做
  • Python做网站难不难免费建网站可信吗
  • 重庆手机网站推广价格建立一个网站需要什么技术
  • 北京南站停车场收费标准百度广告收费
  • 企业网站建设费计入什么科目it企业网站模板下载
  • 网站建设工作室制作平台建立网上商城应考虑哪些问题
  • 找论文的免费网站网站建设职能绩效目标
  • 外贸流程是什么如何优化推广网站
  • 漂亮的网站是什么建设出来的湖州公司网站建设公司