抛丸机网站排名优化,网页qq邮箱怎么发文件,亚马逊网站的建设和维护,ui界面设计说明范文一、前言 关于EnableCaching最简单使用#xff0c;个人感觉只需提供一个CacheManager的一个实例就好了。springboot为我们提供了cache相关的自动配置。引入cache模块#xff0c;如下。 二、maven依赖 dependencygroupIdorg.springframework.boot/groupId… 一、前言 关于EnableCaching最简单使用个人感觉只需提供一个CacheManager的一个实例就好了。springboot为我们提供了cache相关的自动配置。引入cache模块如下。 二、maven依赖 dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-cache/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-redis/artifactId/dependencydependencygroupIdorg.springframework.integration/groupIdartifactIdspring-integration-redis/artifactId/dependencydependencygroupIdredis.clients/groupIdartifactIdjedis/artifactId/dependency 三、缓存类型 本人也仅仅使用了redis、guava、ehcache。更多详情请参考 spring cache官方文档。 https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-caching.html 四、常用注解 Cacheable 触发缓存填充 CacheEvict 触发缓存驱逐 CachePut 更新缓存而不会干扰方法执行 Caching 重新组合要在方法上应用的多个缓存操作 CacheConfig 在类级别共享一些常见的缓存相关设置 五、Spring Cache提供的SpEL上下文数据 下表直接摘自Spring官方文档 名字 位置 描述 示例 methodName root对象 当前被调用的方法名 #root.methodName method root对象 当前被调用的方法 #root.method.name target root对象 当前被调用的目标对象 #root.target targetClass root对象 当前被调用的目标对象类 #root.targetClass args root对象 当前被调用的方法的参数列表 #root.args[0] caches root对象 当前方法调用使用的缓存列表如Cacheable(value{cache1, cache2})则有两个cache #root.caches[0].name argument name 执行上下文 当前被调用的方法的参数如findById(Long id)我们可以通过#id拿到参数 #user.id result 执行上下文 方法执行后的返回值仅当方法执行之后的判断有效如‘unless’cache evict的beforeInvocationfalse #result 六、RedisCacheManager配置 基于jedis ConfigurationEnableCaching
public class RedisCacheConfig extends CachingConfigurerSupport {Autowiredprivate RedisProperties redisProperties;Beanpublic JedisConnectionFactory jedisConnectionFactory() {// 获取服务器数组(这里要相信自己的输入所以没有考虑空指针问题)String[] serverArray redisProperties.getClusterNodes().split(,);RedisClusterConfiguration redisClusterConfiguration new RedisClusterConfiguration(Arrays.asList(serverArray));JedisPoolConfig jedisPoolConfig new JedisPoolConfig();// 最大空闲连接数, 默认8个jedisPoolConfig.setMaxIdle(100);// 最大连接数, 默认8个jedisPoolConfig.setMaxTotal(500);// 最小空闲连接数, 默认0jedisPoolConfig.setMinIdle(0);// 获取连接时的最大等待毫秒数(如果设置为阻塞时BlockWhenExhausted),如果超时就抛异常, 小于零:阻塞不确定的时间,// 默认-1jedisPoolConfig.setMaxWaitMillis(2000); // 设置2秒// 对拿到的connection进行validateObject校验jedisPoolConfig.setTestOnBorrow(true);return new JedisConnectionFactory(redisClusterConfiguration,jedisPoolConfig);}/** * 注入redis template * * return */BeanQualifier(redisTemplate)public RedisTemplate redisTemplate(JedisConnectionFactoryjedisConnectionFactory, Jackson2JsonRedisSerializer jackson2JsonRedisSerializer) {RedisTemplate template new RedisTemplate();template.setConnectionFactory(jedisConnectionFactory);template.setKeySerializer(new JdkSerializationRedisSerializer());template.setValueSerializer(jackson2JsonRedisSerializer);template.afterPropertiesSet();return template;}/** * redis cache manager * * return */BeanPrimarypublic RedisCacheManager redisCacheManager(JedisConnectionFactory jedisConnectionFactory, ObjectProviderListRedisCacheConfigurationProvider configurationProvider) {MapString, RedisCacheConfiguration redisCacheConfigurationMap Maps.newHashMap();ListRedisCacheConfigurationProvider configurations configurationProvider.getIfAvailable();if (!CollectionUtils.isEmpty(configurations)) {for (RedisCacheConfigurationProvider configuration : configurations) {redisCacheConfigurationMap.putAll(configuration.resolve());}}RedisCacheManager cacheManager RedisCacheManager.RedisCacheManagerBuilder.fromConnectionFactory(jedisConnectionFactory).cacheDefaults(resovleRedisCacheConfiguration(Duration.ofSeconds(300), JacksonHelper.genJavaType(Object.class))).withInitialCacheConfigurations(redisCacheConfigurationMap).build();return cacheManager;}private static RedisCacheConfiguration resovleRedisCacheConfiguration(Duration duration, JavaType javaType) {return RedisCacheConfiguration.defaultCacheConfig().serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())).serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new Jackson2JsonRedisSerializer(javaType))).entryTtl(duration);}/** * 配置一个序列器, 将对象序列化为字符串存储, 和将对象反序列化为对象 */Beanpublic Jackson2JsonRedisSerializer jackson2JsonRedisSerializer() {Jackson2JsonRedisSerializer jackson2JsonRedisSerializer new Jackson2JsonRedisSerializer(Object.class);ObjectMapper om new ObjectMapper();om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);jackson2JsonRedisSerializer.setObjectMapper(om);return jackson2JsonRedisSerializer;}public static abstract class RedisCacheConfigurationProvider {// key 缓存名称 value 缓存时间 和 缓存类型protected MapString, PairDuration, JavaType configs;protected abstract void initConfigs();public MapString, RedisCacheConfiguration resolve() {initConfigs();Assert.notEmpty(configs, RedisCacheConfigurationProvider 配置不能为空...);MapString, RedisCacheConfiguration result Maps.newHashMap();configs.forEach((cacheName, pair) - result.put(cacheName, resovleRedisCacheConfiguration(pair.getKey(), pair.getValue())));return result;}}} 基于Lettuce Configuration
EnableCaching
public class RedisCacheConfig extends CachingConfigurerSupport {Autowiredprivate RedisProperties redisProperties;Beanpublic LettuceConnectionFactory lettuceConnectionFactory() {String[] serverArray redisProperties.getClusterNodes().split(,);// 获取服务器数组(这里要相信自己的输入所以没有考虑空指针问题)RedisClusterConfiguration redisClusterConfiguration new RedisClusterConfiguration(Arrays.asList(serverArray));GenericObjectPoolConfig poolConfig new GenericObjectPoolConfig();// 最大空闲连接数, 默认8个poolConfig.setMaxIdle(100);// 最大连接数, 默认8个poolConfig.setMaxTotal(500);// 最小空闲连接数, 默认0poolConfig.setMinIdle(0);LettuceClientConfiguration lettuceClientConfiguration LettucePoolingClientConfiguration.builder().commandTimeout(Duration.ofSeconds(15)).poolConfig(poolConfig).shutdownTimeout(Duration.ZERO).build();return new LettuceConnectionFactory(redisClusterConfiguration, lettuceClientConfiguration);}/** * 注入redis template * * return */BeanQualifier(redisTemplate)public RedisTemplate redisTemplate(LettuceConnectionFactory lettuceConnectionFactory, Jackson2JsonRedisSerializer jackson2JsonRedisSerializer) {RedisTemplate template new RedisTemplate();template.setConnectionFactory(lettuceConnectionFactory);template.setKeySerializer(new JdkSerializationRedisSerializer());template.setValueSerializer(jackson2JsonRedisSerializer);template.afterPropertiesSet();return template;}/** * redis cache manager * * return */BeanPrimarypublic RedisCacheManager redisCacheManager(LettuceConnectionFactory lettuceConnectionFactory, ObjectProviderListRedisCacheConfigurationProvider configurationProvider) {MapString, RedisCacheConfiguration redisCacheConfigurationMap Maps.newHashMap();ListRedisCacheConfigurationProvider configurations configurationProvider.getIfAvailable();if (!CollectionUtils.isEmpty(configurations)) {for (RedisCacheConfigurationProvider configuration : configurations) {redisCacheConfigurationMap.putAll(configuration.resolve());}}RedisCacheManager cacheManager RedisCacheManager.RedisCacheManagerBuilder.fromConnectionFactory(lettuceConnectionFactory).cacheDefaults(resovleRedisCacheConfiguration(Duration.ofSeconds(300), JacksonHelper.genJavaType(Object.class))).withInitialCacheConfigurations(redisCacheConfigurationMap).build();return cacheManager;}private static RedisCacheConfiguration resovleRedisCacheConfiguration(Duration duration, JavaType javaType) {return RedisCacheConfiguration.defaultCacheConfig().serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())).serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new Jackson2JsonRedisSerializer(javaType))).entryTtl(duration);}Beanpublic RedisLockRegistry redisLockRegistry(LettuceConnectionFactory lettuceConnectionFactory) {return new RedisLockRegistry(lettuceConnectionFactory, recharge-plateform, 60000 * 20);}/** * 配置一个序列器, 将对象序列化为字符串存储, 和将对象反序列化为对象 */Beanpublic Jackson2JsonRedisSerializer jackson2JsonRedisSerializer() {Jackson2JsonRedisSerializer jackson2JsonRedisSerializer new Jackson2JsonRedisSerializer(Object.class);ObjectMapper om new ObjectMapper();om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);jackson2JsonRedisSerializer.setObjectMapper(om);return jackson2JsonRedisSerializer;}public static abstract class RedisCacheConfigurationProvider {// key 缓存名称 value 缓存时间 和 缓存类型protected MapString, PairDuration, JavaType configs;protected abstract void initConfigs();public MapString, RedisCacheConfiguration resolve() {initConfigs();Assert.notEmpty(configs, RedisCacheConfigurationProvider 配置不能为空...);MapString, RedisCacheConfiguration result Maps.newHashMap();configs.forEach((cacheName, pair) - result.put(cacheName, resovleRedisCacheConfiguration(pair.getKey(), pair.getValue())));return result;}}} Jedis和Lettuce比较 Jedis 是直连模式在多个线程间共享一个 Jedis 实例时是线程不安全的如果想要在多线程环境下使用 Jedis需要使用连接池 每个线程都去拿自己的 Jedis 实例当连接数量增多时物理连接成本就较高了。 Lettuce的连接是基于Netty的连接实例可以在多个线程间共享 所以一个多线程的应用可以使用同一个连接实例而不用担心并发线程的数量。当然这个也是可伸缩的设计一个连接实例不够的情况也可以按需增加连接实例。通过异步的方式可以让我们更好的利用系统资源而不用浪费线程等待网络或磁盘I/O。 只在基于Lettuce的配置中加入了RedisLockRegistry对应bean的配置由于在集群的模式下基于Jedis的配置下通过RedisLockRegistry 获取分布式锁的时候报错 EvalSha is not supported in cluster environment 具体的解决方案就是切换至基于Lettuce的配置请参考 https://stackoverflow.com/questions/47092475/spring-boot-redistemplate-execute-sc RedisCacheConfigurationProvider 作用为不同的cache提供特定的缓存时间以及key、value序列化和反序列化的方式。具体使用方式如下。 Componentpublic class CouponRedisCacheConfigurationProvider extends RedisCacheConfig.RedisCacheConfigurationProvider {Overrideprotected void initConfigs() {this.configs Maps.newHashMap();this.configs.put(CouponConstants.COUPON_ALL_CACHE, new Pair(Duration.ofHours(1), JacksonHelper.genMapType(HashMap.class, Integer.class, Coupon.class)));this.configs.put(CouponConstants.COUPON_GOOD_CACHE, new Pair(Duration.ofHours(1), JacksonHelper.genCollectionType(List.class, String.class)));this.configs.put(CouponConstants.COUPON_HANDLE_TELEPHONE_STATUS_CACHE, new Pair(Duration.ofMinutes(10), JacksonHelper.genCollectionType(List.class, CouponHandle.class)));this.configs.put(CouponConstants.COUPON_HANDLE_TELEPHONE_GOOD_CACHE, new Pair(Duration.ofMinutes(10), JacksonHelper.genCollectionType(List.class, CouponHandle.class)));}} JacksonHelper 作用是根据不同的类型的对象获取对应的JavaType对象在构造RedisTempalte序列化和反序列化器Jackson2JsonRedisSerializer对象需要。具体代码如下。 public class JacksonHelper {private static Logger LOGGER LoggerFactory.getLogger(JacksonHelper.class);private static final SimpleModule module initModule();private static final ObjectMapper objectMapper;private static final ObjectMapper prettyMapper;public JacksonHelper() {}private static SimpleModule initModule() {return (new SimpleModule()).addSerializer(BigDecimal.class, new BigDecimalSerializer()).addSerializer(LocalTime.class, new LocalTimeSerializer()).addDeserializer(LocalTime.class, new LocalTimeDeserializer()).addSerializer(LocalDate.class, new LocalDateSerializer()).addDeserializer(LocalDate.class, new LocalDateDeserializer()).addSerializer(LocalDateTime.class, new LocalDateTimeSerializer()).addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer()).addSerializer(Date.class, new DateSerializer()).addDeserializer(Date.class, new DateDeserializer());}public static JavaType genJavaType(TypeReference? typeReference) {return getObjectMapper().getTypeFactory().constructType(typeReference.getType());}public static JavaType genJavaType(Class? clazz) {return getObjectMapper().getTypeFactory().constructType(clazz);}public static JavaType genCollectionType(Class? extends Collection collectionClazz, Class? javaClazz) {return getObjectMapper().getTypeFactory().constructCollectionType(collectionClazz, javaClazz);}public static JavaType genMapType(Class? extends Map mapClazz, Class? keyClass, Class? valueClazz) {return getObjectMapper().getTypeFactory().constructMapType(mapClazz, keyClass, valueClazz);}public static ObjectMapper getObjectMapper() {return objectMapper;}public static ObjectMapper getPrettyMapper() {return prettyMapper;}static {objectMapper (new ObjectMapper()).registerModule(module).configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false).configure(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL, true).configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);prettyMapper objectMapper.copy().configure(SerializationFeature.INDENT_OUTPUT, true);}}class LocalDateDeserializer extends JsonDeserializerLocalDate {public LocalDateDeserializer() {}public LocalDate deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {String dateString ((JsonNode) jp.getCodec().readTree(jp)).asText();return LocalDate.parse(dateString, DateTimeFormatter.ISO_LOCAL_DATE);}}class DateDeserializer extends JsonDeserializerDate {public DateDeserializer() {}public Date deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {String dateTimeStr ((JsonNode) jp.getCodec().readTree(jp)).asText();SimpleDateFormat sdf new SimpleDateFormat(CouponConstants.DATE_TIME_FORMATER);ParsePosition pos new ParsePosition(0);return sdf.parse(dateTimeStr, pos);}}class LocalDateTimeDeserializer extends JsonDeserializerLocalDateTime {public LocalDateTimeDeserializer() {}public LocalDateTime deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {String dateTimeStr ((JsonNode) jp.getCodec().readTree(jp)).asText();return LocalDateTime.parse(dateTimeStr, DateTimeFormatter.ISO_LOCAL_DATE_TIME);}}class LocalTimeDeserializer extends JsonDeserializerLocalTime {public LocalTimeDeserializer() {}public LocalTime deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {String dateString ((JsonNode) jp.getCodec().readTree(jp)).asText();return LocalTime.parse(dateString, DateTimeFormatter.ISO_LOCAL_TIME);}}class BigDecimalSerializer extends JsonSerializerBigDecimal {public BigDecimalSerializer() {}public void serialize(BigDecimal value, JsonGenerator jgen, SerializerProvider provider) throws IOException {jgen.writeString(value.toString());}}class LocalDateSerializer extends JsonSerializerLocalDate {public LocalDateSerializer() {}public void serialize(LocalDate value, JsonGenerator jgen, SerializerProvider provider) throws IOException {jgen.writeString(DateTimeFormatter.ISO_LOCAL_DATE.format(value));}}class LocalDateTimeSerializer extends JsonSerializerLocalDateTime {public LocalDateTimeSerializer() {}public void serialize(LocalDateTime value, JsonGenerator jgen, SerializerProvider provider) throws IOException {jgen.writeString(DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(value));}}class DateSerializer extends JsonSerializerDate {public DateSerializer() {}public void serialize(Date value, JsonGenerator jgen, SerializerProvider provider) throws IOException {SimpleDateFormat sdf new SimpleDateFormat(CouponConstants.DATE_TIME_FORMATER);jgen.writeString(sdf.format(value));}}class LocalTimeSerializer extends JsonSerializerLocalTime {public LocalTimeSerializer() {}public void serialize(LocalTime value, JsonGenerator jgen, SerializerProvider provider) throws IOException {jgen.writeString(DateTimeFormatter.ISO_LOCAL_TIME.format(value));}} 业务代码 Component
public class ServiceImpl { OverrideCacheEvict(cacheNames CouponConstants.COUPON_HANDLE_TELEPHONE_STATUS_CACHE, key #telephone##status, beforeInvocation true)public void evictCouponHandles(String telephone, Integer status) {}OverrideCacheable(cacheNames CouponConstants.COUPON_HANDLE_TELEPHONE_STATUS_CACHE, key #telephone##status, sync true)public ListCouponHandle searchCouponHandles(String telephone, Integer status) {}} 不同的缓存对应不同的存储类型不同的存储类型对应着不同的序列化和反序列化器这就保证了再调用注有Cacheable注解的代码时获取到的对象不会发生类型转换错误。关于设置不同的cache下过期时间以及序列化和反序列器请参考下面更直接明了的例子。 Configurationpublic class RedisCacheConfig {Beanpublic KeyGenerator simpleKeyGenerator() {return (o, method, objects) - {StringBuilder stringBuilder new StringBuilder();stringBuilder.append(o.getClass().getSimpleName());stringBuilder.append(.);stringBuilder.append(method.getName());stringBuilder.append([);for (Object obj : objects) {stringBuilder.append(obj.toString());}stringBuilder.append(]);return stringBuilder.toString();};}Beanpublic CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {return new RedisCacheManager(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory),this.getRedisCacheConfigurationWithTtl(600), // 默认策略未配置的 cache 会使用这个this.getRedisCacheConfigurationMap() // 指定 cache 策略);}private MapString, RedisCacheConfiguration getRedisCacheConfigurationMap() {MapString, RedisCacheConfiguration redisCacheConfigurationMap new HashMap();redisCacheConfigurationMap.put(UserInfoList, this.getRedisCacheConfigurationWithTtl(3000));redisCacheConfigurationMap.put(UserInfoListAnother, this.getRedisCacheConfigurationWithTtl(18000));return redisCacheConfigurationMap;}private RedisCacheConfiguration getRedisCacheConfigurationWithTtl(Integer seconds) {Jackson2JsonRedisSerializerObject jackson2JsonRedisSerializer new Jackson2JsonRedisSerializer(Object.class);ObjectMapper om new ObjectMapper();om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);jackson2JsonRedisSerializer.setObjectMapper(om);RedisCacheConfiguration redisCacheConfiguration RedisCacheConfiguration.defaultCacheConfig();redisCacheConfiguration redisCacheConfiguration.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer)).entryTtl(Duration.ofSeconds(seconds));return redisCacheConfiguration;}} Cacheable(value UserInfoList, keyGenerator simpleKeyGenerator) // 3000秒
Cacheable(value UserInfoListAnother, keyGenerator simpleKeyGenerator) // 18000秒
Cacheable(value DefaultKeyTest, keyGenerator simpleKeyGenerator) // 600秒未指定的cache使用默认策略 转载于:https://www.cnblogs.com/hujunzheng/p/9660681.html