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

手机靓号网站建设谷歌云服务器永久免费

手机靓号网站建设,谷歌云服务器永久免费,鹤壁网站建设鹤壁,江门 网站设计1. 简介 为了体现我们的实力#xff0c;首先我们要有造轮子的能力。这意味着我们不仅要熟练掌握现有的技术栈和框架#xff0c;还要具备深厚的技术功底。通过自主设计和实现关键组件#xff0c;如高性能缓存系统#xff0c;我们能够深入理解技术背后的原理#xff0c;掌握…1. 简介 为了体现我们的实力首先我们要有造轮子的能力。这意味着我们不仅要熟练掌握现有的技术栈和框架还要具备深厚的技术功底。通过自主设计和实现关键组件如高性能缓存系统我们能够深入理解技术背后的原理掌握核心技术的精髓从而在面对复杂问题时能够提出独到见解和解决方案。 本篇文章将带大家实现一个简化版但功能类似Spring Cache的缓存组件。虽然不会像Spring Cache那样全面和复杂但我们将通过动手实践掌握缓存机制的核心原理。 2. 实战案例 2.1 环境准备 既然是基于redis实现那么我们通过引入以下依赖来简化环境配置 dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-data-redis/artifactId/dependency通过data-redis我们需要做的就是配置redis服务器信息即可。 spring:redis:timeout: 10000connectTimeout: 20000host: 127.0.0.1password: xxxooolettuce:pool:maxActive: 8maxIdle: 100minIdle: 10maxWait: -1通过以上的配置在项目中我们就可以直接通过SpringBoot自动配置的StringRedisTemplate来实现各种操作。 2.2 自定义注解 这里我们仿照spring-cache定义如下两个注解Cacheable 触发缓存, CacheEvict 删除缓存。 **Cacheable**设置缓存或读取缓存如果缓存中存在直接返回如果不存在则将方法返回值设置到缓存中。 **CacheEvict**将当前指定key从缓存中删除。 触发缓存: Target({ElementType.TYPE, ElementType.METHOD}) Retention(RetentionPolicy.RUNTIME) public interface Cacheable {// 缓存KeyString key() default ;// 缓存名称类似分组String name() default ; }删除缓存 Target({ElementType.TYPE, ElementType.METHOD}) Retention(RetentionPolicy.RUNTIME) public interface CacheEvict {// 缓存KeyString key() default ;// 缓存名称类似分组String name() default ; }以上2个注解基本相同分别完成读写清除缓存操作。 注为了灵活我们需要让上面注解中的key支持SpEL表达式。 2.3 定义切面 该切面用来处理带有上面注解的类或方法如方法上有**Cacheable**注解那么先从缓存中读取内容如果缓存中不存在则将当前方法返回值写入缓存中。 Component Aspect public class CacheAspect {private static final Logger logger LoggerFactory.getLogger(CacheAspect.class) ;private final StringRedisTemplate stringRedisTemplate ;public CacheAspect(StringRedisTemplate stringRedisTemplate) {this.stringRedisTemplate stringRedisTemplate ;}private DefaultParameterNameDiscoverer discoverer new DefaultParameterNameDiscoverer() ;Pointcut(annotation(com.pack.redis.cache.Cacheable))private void cacheable() {}Pointcut(annotation(com.pack.redis.cache.CacheEvict))private void cacheevict() {}Around(cacheable() || cacheevict()) public Object proceed(ProceedingJoinPoint pjp) throws Throwable {Object ret null ;Method method ((MethodSignature) pjp.getSignature()).getMethod() ;Object[] args pjp.getArgs() ;// SPEL 表达式解析SpelExpressionParser parser new SpelExpressionParser() ;StandardEvaluationContext context new StandardEvaluationContext() ;// 获取参数名称String[] parameterNames discoverer.getParameterNames(method) ;for (int i 0, len parameterNames.length; i len; i) {context.setVariable(parameterNames[i], args[i]) ;}// 类上的注解不做处理了只处理方法上Cacheable cacheable method.getAnnotation(Cacheable.class) ;if (cacheable ! null) {// 假设都配置了name和keyString name cacheable.name() ;String expression cacheable.key() ;Object value parser.parseExpression(expression).getValue(context) ;String cacheKey name : value;boolean hasKey this.stringRedisTemplate.hasKey(cacheKey) ;if (!hasKey) {ret pjp.proceed() ;this.stringRedisTemplate.opsForValue().set(cacheKey, new ObjectMapper().writeValueAsString(ret)) ;logger.info(写缓存【{}】,数据{}, cacheKey, ret) ;return ret ; }logger.info(从缓存【{}】获取, cacheKey);String result this.stringRedisTemplate.opsForValue().get(cacheKey) ;return new ObjectMapper().readValue(result, method.getReturnType()) ;}CacheEvict cacheevict method.getAnnotation(CacheEvict.class) ;if (cacheevict ! null) {String name cacheevict.name() ;String expression cacheevict.key() ;Object value parser.parseExpression(expression).getValue(context) ;String cacheKey name : value ;this.stringRedisTemplate.delete(cacheKey) ;}return pjp.proceed() ;}}上面的环绕通知通过或(||)表达式的方式拦截2个注解实现比较的简单主要是结合了SpEL表达式。上面的代码我们假设是你key进行了配置如果没有配置我们可以通过如下方式去生成key private String getKey(Class? targetType, Method method) {StringBuilder builder new StringBuilder();builder.append(targetType.getSimpleName());builder.append(#).append(method.getName()).append(();Class?[] types method.getParameterTypes() ;for (Class? clazz : types) {builder.append(clazz.getSimpleName()).append(,) ;}if (method.getParameterTypes().length 0) {builder.deleteCharAt(builder.length() - 1);}return (builder.append()).toString()).replaceAll([^a-zA-Z0-9], ) ; }如果你没有配置key可以通过当前执行的类及方法生成唯一的key。 2.4 测试 这里我是通过JPA实现CRUD操作 Service public class UserService {private final UserRepository userRepository ;public UserService(UserRepository userRepository) {this.userRepository userRepository ;}Cacheable(name user, key #id)public User queryById(Long id) {return this.userRepository.findById(id).orElse(null) ;}CacheEvict(name user, key #user.id)public void clearUserById(User user) {this.userRepository.deleteById(user.getId()) ;} }这里的clearUserById方法是有意将方法参数设置为User对象就是为了方便演示SpEL表达式的使用。 测试接口 GetMapping(/{id}) public User getUser(PathVariable(id) Long id) {return this.userService.queryById(id) ; }DeleteMapping(/{id}) public void removeUser(PathVariable(id) Long id) {User user new User() ;user.setId(id) ;this.userService.clearUserById(user) ; } 到此一个简单的缓存组件就实现了。这里待完善及优化的还是非常多的比如更新缓存并发量大时缓存那里是不是应该加锁不然肯定会有很多的线程都执行查询再存入缓存我们这里是不是还可以借助本地缓存做多级缓存的优化呢可以参考下面这篇文章。 [[Redis结合Caffeine实现二级缓存提高应用程序性能]]
http://www.hkea.cn/news/14578435/

相关文章:

  • 网站改版专题页整站seo排名
  • 做网站服务器配置营销网站建设哪家便宜
  • app商城开发网站建设做爰免费网站
  • 国外采购网站大全wordpress 站长工具
  • 上海网站建设优化seowordpress相册点击弹出框
  • 现在还是和做网站么四大工业设计软件有哪些
  • 软件工程 宣传网站建设在线网页截图
  • 网站制作技术培训wordpress模板淘宝客模板下载
  • 网站备案接入商深圳精品网站建设
  • 广东省两学一做网站xml网站地图生成器
  • 如何在谷歌上做网站厦门集团网站建设
  • 网站后台首页设计wordpress 百家模板
  • 有没有教做川菜的网站网站怎么做 流程图
  • 典型网站开发的流程图品牌建设有效提升城市竞争力例子
  • php网站后台入口公司注册的流程与步骤
  • 郑州旅游网站设计黑群晖 wordpress
  • 做摄影网站的目的是什么意思网页制作模板html
  • 阿里巴巴做短视频网站兰州网站设计
  • 网站开发的毕业设计论文框架app程序定制开发
  • 网站建设怎样上传程序陕西建设监理证书查询网站
  • 如何写代码做网站智慧团建登录口
  • 电商网站开发 参考文献网页编辑工具2022
  • 企业网站都需要备案吗医院网站建设合同
  • 做网站能成功吗怎样选wordpress电商主题
  • 石龙建设网站做一个网站如何赚钱
  • 做网站最好的软件是做一个网站能挣多少钱
  • wordpress站点语言wordpress使用腾讯cos
  • 晋城市公共事业建设局网站学平面设计在哪里学
  • 有哪些设计网站app网页搭建公司
  • 邢台贴吧wordpress 好seo吗