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

网盘搜索网站怎么做杭州seo网站哪家好

网盘搜索网站怎么做,杭州seo网站哪家好,代理 指定网站 host,android开发软件下载Why? 为什么要对方法的返回值进行缓存呢? 简单来说是为了提升后端程序的性能和提高前端程序的访问速度。减小对db和后端应用程序的压力。 一般而言,缓存的内容都是不经常变化的,或者轻微变化对于前端应用程序是可以容忍的。 否…

Why?

为什么要对方法的返回值进行缓存呢?

简单来说是为了提升后端程序的性能和提高前端程序的访问速度。减小对db和后端应用程序的压力。

一般而言,缓存的内容都是不经常变化的,或者轻微变化对于前端应用程序是可以容忍的。

否则,不建议加入缓存,因为增加缓存会使程序复杂度增加,还会出现一些其他的问题,比如缓存同步,数据一致性,更甚者,可能出现经典的缓存穿透、缓存击穿、缓存雪崩问题。

HowDo

如何缓存方法的返回值?应该会有很多的办法,本文简单描述两个比较常见并且比较容易实现的办法:

  • 自定义注解
  • SpringCache

annotation

整体思路:

第一步:定义一个自定义注解,在需要缓存的方法上面添加此注解,当调用该方法的时候,方法返回值将被缓存起来,下次再调用的时候将不会进入该方法。其中需要指定一个缓存键用来区分不同的调用,建议为:类名+方法名+参数名

第二步:编写该注解的切面,根据缓存键查询缓存池,若池中已经存在则直接返回不执行方法;若不存在,将执行方法,并在方法执行完毕写入缓冲池中。方法如果抛异常了,将不会创建缓存

第三步:缓存池,首先需要尽量保证缓存池是线程安全的,当然了没有绝对的线程安全。其次为了不发生缓存臃肿的问题,可以提供缓存释放的能力。另外,缓存池应该设计为可替代,比如可以丝滑得在使用程序内存和使用redis直接调整。

MethodCache

创建一个名为MethodCache 的自定义注解


package com.ramble.methodcache.annotation;
import java.lang.annotation.*;@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface MethodCache {}

MethodCacheAspect

编写MethodCache注解的切面实现


package com.ramble.methodcache.annotation;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;@Slf4j
@Aspect
@Component
public class MethodCacheAspect {private static final Map<String, Object> CACHE_MAP = new ConcurrentHashMap<>();@Around(value = "@annotation(methodCache)")public Object around(ProceedingJoinPoint jp, MethodCache methodCache) throws Throwable {String className = jp.getSignature().getDeclaringType().getSimpleName();String methodName = jp.getSignature().getName();String args = String.join(",", Arrays.toString(jp.getArgs()));String key = className + ":" + methodName + ":" + args;// key 示例:DemoController:findUser:[FindUserParam(id=1, name=c7)]log.debug("缓存的key={}", key);Object cache = getCache(key);if (null != cache) {log.debug("走缓存");return cache;} else {log.debug("不走缓存");Object value = jp.proceed();setCache(key, value);return value;}}private Object getCache(String key) {return CACHE_MAP.get(key);}private void setCache(String key, Object value) {CACHE_MAP.put(key, value);}
}
  • Around:对被MethodCache注解修饰的方法启用环绕通知
  • ProceedingJoinPoint:通过此对象获取方法所在类、方法名和参数,用来组装缓存key
  • CACHE_MAP:缓存池,生产环境建议使用redis等可以分布式存储的容器,直接放程序内存不利于后期业务扩张后多实例部署

controller


package com.ramble.methodcache.controller;
import com.ramble.methodcache.annotation.MethodCache;
import com.ramble.methodcache.controller.param.CreateUserParam;
import com.ramble.methodcache.controller.param.FindUserParam;
import com.ramble.methodcache.service.DemoService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;@Tag(name = "demo - api")
@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/demo")
public class DemoController {private final DemoService demoService;@MethodCache@GetMapping("/{id}")public String getUser(@PathVariable("id") String id) {return demoService.getUser(id);}@Operation(summary = "查询用户")@MethodCache@PostMapping("/list")public String findUser(@RequestBody FindUserParam param) {return demoService.findUser(param);}
}

通过反复调用被@MethodCache注解修饰的方法,会发现若缓存池有数据,将不会进入方法体。

SpringCache

其实SpringCache的实现思路和上述方法基本一致,SpringCache提供了更优雅的编程方式,更丝滑的缓存池切换和管理,更强大的功能和统一规范。

EnableCaching

使用 @EnableCaching 开启SpringCache功能,无需引入额外的pom。

默认情况下,缓存池将由 ConcurrentMapCacheManager 这个对象管理,也就是默认是程序内存中缓存。其中用于存放缓存数据的是一个 ConcurrentHashMap,源码如下:


public class ConcurrentMapCacheManager implements CacheManager, BeanClassLoaderAware {private final ConcurrentMap<String, Cache> cacheMap = new ConcurrentHashMap(16);......}

此外可选的缓存池管理对象还有:

  • EhCacheCacheManager

  • JCacheCacheManager

  • RedisCacheManager

  • ......

Cacheable


package com.ramble.methodcache.controller;
import com.ramble.methodcache.controller.param.FindUserParam;
import com.ramble.methodcache.service.DemoService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.*;@Tag(name = "user - api")
@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/user")
public class UserController {private final DemoService demoService;@Cacheable(value = "userCache")@GetMapping("/{id}")public String getUser(@PathVariable("id") String id) {return demoService.getUser(id);}@Operation(summary = "查询用户")@Cacheable(value = "userCache")@PostMapping("/list")public String findUser(@RequestBody FindUserParam param) {return demoService.findUser(param);}
}
  • 使用@Cacheable注解修饰需要缓存返回值的方法
  • value必填,不然运行时报异常。类似一个分组,将不同的数据或者方法(当然也可以其他维度,主要看业务需要)放到一堆,便于管理
  • 可以修饰接口方法,但是不建议,IDEA会报一个提示Spring doesn't recommend to annotate interface methods with @Cache* annotation

常用属性:

  • value:缓存名称
  • cacheNames:缓存名称。value 和cacheNames都被AliasFor注解修饰,他们互为别名
  • key:缓存数据时候的key,默认使用方法参数的值,可以使用SpEL生产key
  • keyGenerator:key生产器。和key二选一
  • cacheManager:缓存管理器
  • cacheResolver:和caheManager二选一,互为别名
  • condition:创建缓存的条件,可用SpEL表达式(如#id>0,表示当入参id大于0时候才缓存方法返回值)
  • unless:不创建缓存的条件,如#result==null,表示方法返回值为null的时候不缓存

CachePut

用来更新缓存。被CachePut注解修饰的方法,在被调用的时候不会校验缓存池中是否已经存在缓存,会直接发起调用,然后将返回值放入缓存池中。

CacheEvict

用来删除缓存,会根据key来删除缓存中的数据。并且不会将本方法返回值缓存起来。

常用属性:

  • value/cacheeName:缓存名称,或者说缓存分组
  • key:缓存数据的键
  • allEntries:是否根据缓存名称清空所有缓存,默认为false。当此值为true的时候,将根据cacheName清空缓存池中的数据,然后将新的返回值放入缓存
  • beforeInvocation:是否在方法执行之前就清空缓存,默认为false

Caching

此注解用于在一个方法或者类上面,同时指定多个SpringCache相关注解。这个也是SpringCache的强大之处,可以自定义各种缓存创建、更新、删除的逻辑,应对复杂的业务场景。

属性:

  • cacheable:指定@Cacheable注解
  • put:指定@CachePut注解
  • evict:指定@CacheEvict注解

源码:


@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Caching {Cacheable[] cacheable() default {};CachePut[] put() default {};CacheEvict[] evict() default {};
}

相当于就是注解里面套注解,用来完成复杂和多变的场景,这个设计相当的哇塞。

CacheConfig

放在类上面,那么类中所有方法都会被缓存

SpringCacheEnv

SpringCache内置了一些环境变量,可用于各个注解的属性中。

  • methodName:被修饰方法的方法名

  • method:被修饰方法的Method对象

  • target:被修饰方法所属的类对象的实例

  • targetClass:被修饰方法所属类对象

  • args:方法入参,是一个 object[] 数组

  • caches:这个对象其实就是ConcurrentMapCacheManager中的cacheMap,这个cacheMap呢就是一开头提到的ConcurrentHashMap,即缓存池。caches的使用场景尚不明了。

  • argumentName:方法的入参

  • result:方法执行的返回值

使用示例:


@Cacheable(value = "userCache", condition = "#result!=null",unless = "#result==null")
public String showEnv() { return "打印各个环境变量";}

表示仅当方法返回值不为null的时候才缓存结果,这里通过result env 获取返回值。

另外,condition 和 unless 为互补关系,上述condition = "#result!=null"和unless = "#result==null"其实是一个意思。


@Cacheable(value = "userCache", key = "#name")
public String showEnv(String id, String name) {return "打印各个环境变量";
}

表示使用方法入参作为该条缓存数据的key,若传入的name为gg,则实际缓存的数据为:gg->打印各个环境变量

另外,如果name为空会报异常,因为缓存key不允许为null


@Cacheable(value = "userCache",key = "#root.args")
public String showEnv(String id, String name) {return "打印各个环境变量";
}

表示使用方法的入参作为缓存的key,若传递的参数为id=100,name=gg,则实际缓存的数据为:Object[]->打印各个环境变量,Object[]数组中包含两个值。

既然是数组,可以通过下标进行访问,root.args[1] 表示获取第二个参数,本例中即 取 name 的值 gg,则实际缓存的数据为:gg->打印各个环境变量。


@Cacheable(value = "userCache",key = "#root.targetClass")
public String showEnv(String id, String name) {return "打印各个环境变量";
}

表示使用被修饰的方法所属的类作为缓存key,实际缓存的数据为:Class->打印各个环境变量,key为class对象,不是全限定名,全限定名是一个字符串,这里是class对象。

可是,不是很懂这样设计的应用场景是什么......


@Cacheable(value = "userCache",key = "#root.target")
public String showEnv(String id, String name) {return "打印各个环境变量";
}

表示使用被修饰方法所属类的实例作为key,实际缓存的数据为:UserController->打印各个环境变量。

被修饰的方法就是在UserController中,调试的时候甚至可以获取到此实例注入的其它容器对象,如userService等。

可是,不是很懂这样设计的应用场景是什么......


@Cacheable(value = "userCache",key = "#root.method")
public String showEnv(String id, String name) {return "打印各个环境变量";
}

表示使用Method对象作为缓存的key,是Method对象,不是字符串。

可是,不是很懂这样设计的应用场景是什么......


@Cacheable(value = "userCache",key = "#root.methodName")
public String showEnv(String id, String name) {return "打印各个环境变量";
}

表示使用方法名作为缓存的key,就是一个字符串。

如何获取缓存的数据?

ConcurrentMapCacheManager的cacheMap是一个私有变量,所以没有办法可以打印缓存池中的数据,不过可以通过调试的方式进入对象内部查看。如下:


@Tag(name = "user - api")
@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/user")
public class UserController {private final ConcurrentMapCacheManager cacheManager;/*** 只有调试才课可以查看缓存池中的数据*/@GetMapping("/cache")public void showCacheData() {//需要debug进入Collection<String> cacheNames = cacheManager.getCacheNames();}}

总结:

虽然提供了很多的环境变量,但是大多都无法找到对应的使用场景,其实在实际开发中,最常见的就是key的生产,一般而言使用类名+方法名+参数值足矣。


文章转载自:
http://dinncoglycosuric.ydfr.cn
http://dinncocullet.ydfr.cn
http://dinncoectophyte.ydfr.cn
http://dinncocomeback.ydfr.cn
http://dinnconesting.ydfr.cn
http://dinncoanatomize.ydfr.cn
http://dinncovia.ydfr.cn
http://dinncostatehood.ydfr.cn
http://dinncotanning.ydfr.cn
http://dinncoritzy.ydfr.cn
http://dinncomentholated.ydfr.cn
http://dinncoauris.ydfr.cn
http://dinncokrona.ydfr.cn
http://dinncoreclaimer.ydfr.cn
http://dinncoceria.ydfr.cn
http://dinncofacing.ydfr.cn
http://dinncorejoinder.ydfr.cn
http://dinncozoopharmacy.ydfr.cn
http://dinncogastricism.ydfr.cn
http://dinncoconglomeracy.ydfr.cn
http://dinncolemnos.ydfr.cn
http://dinncobywalk.ydfr.cn
http://dinncocaseinate.ydfr.cn
http://dinncoviolinmaker.ydfr.cn
http://dinncoisochrone.ydfr.cn
http://dinncoshippon.ydfr.cn
http://dinncoambroid.ydfr.cn
http://dinncomicroporosity.ydfr.cn
http://dinncosquetee.ydfr.cn
http://dinncoattend.ydfr.cn
http://dinncolagos.ydfr.cn
http://dinncokarat.ydfr.cn
http://dinncoicaaaa.ydfr.cn
http://dinncomarcottage.ydfr.cn
http://dinncoslyly.ydfr.cn
http://dinncoschlemiel.ydfr.cn
http://dinncospeleologist.ydfr.cn
http://dinncodistemper.ydfr.cn
http://dinncoknurled.ydfr.cn
http://dinncovermis.ydfr.cn
http://dinncoalongside.ydfr.cn
http://dinncodividable.ydfr.cn
http://dinncolobule.ydfr.cn
http://dinncoslovensko.ydfr.cn
http://dinncoprocrypsis.ydfr.cn
http://dinncoclassy.ydfr.cn
http://dinncofivepenny.ydfr.cn
http://dinncoprefixion.ydfr.cn
http://dinncobloodstock.ydfr.cn
http://dinncozilog.ydfr.cn
http://dinncodepartmentalise.ydfr.cn
http://dinncocompactly.ydfr.cn
http://dinncomopoke.ydfr.cn
http://dinncomonogenean.ydfr.cn
http://dinncoevangelize.ydfr.cn
http://dinncodynamism.ydfr.cn
http://dinncochitterlings.ydfr.cn
http://dinncodistinguishability.ydfr.cn
http://dinncocotswold.ydfr.cn
http://dinncorheophilic.ydfr.cn
http://dinncogoalpost.ydfr.cn
http://dinncoachilles.ydfr.cn
http://dinncoplatelet.ydfr.cn
http://dinncochasseur.ydfr.cn
http://dinncotav.ydfr.cn
http://dinncoswerveless.ydfr.cn
http://dinncoparlormaid.ydfr.cn
http://dinncoknow.ydfr.cn
http://dinncomiladi.ydfr.cn
http://dinncodavenport.ydfr.cn
http://dinncofozy.ydfr.cn
http://dinncotawse.ydfr.cn
http://dinncovulpicide.ydfr.cn
http://dinncobespeckle.ydfr.cn
http://dinncopatternmaking.ydfr.cn
http://dinncosulfatize.ydfr.cn
http://dinncoblackamoor.ydfr.cn
http://dinncomto.ydfr.cn
http://dinncodishonest.ydfr.cn
http://dinncovalvar.ydfr.cn
http://dinncocolombia.ydfr.cn
http://dinnconaevoid.ydfr.cn
http://dinncoraguly.ydfr.cn
http://dinncomicrominiature.ydfr.cn
http://dinncosuborbicular.ydfr.cn
http://dinncocrappie.ydfr.cn
http://dinncoivb.ydfr.cn
http://dinncocoelom.ydfr.cn
http://dinncokamseen.ydfr.cn
http://dinnconus.ydfr.cn
http://dinncoindivertibly.ydfr.cn
http://dinncoemmanuel.ydfr.cn
http://dinncofoxed.ydfr.cn
http://dinncomastocarcinoma.ydfr.cn
http://dinncoimmit.ydfr.cn
http://dinncolochage.ydfr.cn
http://dinncoplasticise.ydfr.cn
http://dinncoaic.ydfr.cn
http://dinncosalvador.ydfr.cn
http://dinncohaematolysis.ydfr.cn
http://www.dinnco.com/news/92201.html

相关文章:

  • 网站闭站保护想做app推广项目在哪找
  • 小型手机网站建设多少钱武汉网络广告推广服务
  • 网站空间租用价格视频网站推广
  • 网站建设维护教程青岛seo外包公司
  • 做一个网站多少钱百度公司全称
  • 购物类网站开发百度竞价排名的使用方法
  • 上海建筑安全协会网站百度推广开户代理
  • 网站版面风格seo模拟点击算法
  • 南京市的网站是由那几家公司做的googleseo服务公司
  • 中国第一个做电商网站搜索引擎关键词优化有哪些技巧
  • 唐山网站快速排名提升如何推广app更高效
  • 网站策划任职要求营业推广经典案例
  • 建立网站目录结构时正确的建议是海外营销公司
  • 网站百度权重网站网络营销公司
  • 宜宾网站建设88sou软文写作范文
  • vue网站建设优化
  • 徐州人才网优化营商环境心得体会个人
  • 江门网站建设开发seo文章生成器
  • 互联网软件开发工资一般多少西安seo推广
  • 大连零基础网站建设教学公司推广和竞价代运营
  • 3. 是网站建设的重点百度网站禁止访问怎么解除
  • 网络下载的网站模板能直接上传到虚拟主机企业培训课程价格
  • 学校网站建设发展概况分析seo企业建站系统
  • 做网站需要源码seo排名快速上升
  • 自适应网站会影响推广怎么做网络营销平台
  • 猛烈做瞹瞹视频澳洲网站win7优化大师官方免费下载
  • 宁波网站建设的步骤过程信息发布网站有哪些
  • 360做企业网站多少钱网络营销策略包括哪四种
  • 电脑在局域网做网站合肥网站推广公司
  • 日本设计师个人网站百度一下免费下载安装