1.springboot 中 RedisCacheManager rm = new RedisCacheManager(redisTemplate);我的源码项目没这个构造
2.Java中间件-ehcache
3.Spring缓存注解@Cacheable、@CacheEvict、源码@CachePut使用
4.SpringBoot的源码Cacheable缓存注解
5.一些小众冷门但却非常实用的.NET(Core)开源库推荐
6.RedisCacheManager设置Value序列化器技巧
springboot 中 RedisCacheManager rm = new RedisCacheManager(redisTemplate);我的项目没这个构造
pom.xml 引入redis 开启缓存
<!-- cache -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
application.properties 配置文件
# Redis数据库索引(默认为0)spring.redis.database=0
# Redis服务器地址spring.redis.host=localhost
# Redis服务器连接端口spring.redis.port=
# Redis服务器连接密码(默认为空)spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=-1
# 连接池中的最大空闲连接
spring.redis.pool.max-idle=8
# 连接池中的最小空闲连接
spring.redis.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.timeout=0
添加cache的配置类
package www.ijava.com.configure;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.lang.reflect.Method;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.Jackson2JsonRedisSerializer;
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport{
@Bean
public KeyGenerator keyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object target, Method method, Object... params) {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(method.getName());
for (Object obj : params) {
sb.append(obj.toString());
}
return sb.toString();
}
};
}
@SuppressWarnings("rawtypes")
@Bean
public CacheManager cacheManager(RedisTemplate redisTemplate) {
RedisCacheManager rcm = new RedisCacheManager(redisTemplate);
//设置缓存过期时间
//rcm.setDefaultExpiration();//秒
return rcm;
}
@Bean
public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
StringRedisTemplate template = new StringRedisTemplate(factory);
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);
template.setValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
RedisService
package www.ijava.com.service;
import java.io.Serializable;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Service;
/
***/
@Service
public class RedisService {
@Autowired
private RedisTemplate redisTemplate;
/
** //操作字符串
* redisTemplate.opsForValue();
//操作hash
redisTemplate.opsForHash();
//操作
redisTemplate.opsForList();
//操作
list redisTemplate.opsForSet();
//操作有序set
set redisTemplate.opsForZSet();
*/
/
*** 写入缓存
* @param key
* @param value
* @return
*/
public boolean set(final String key, Object value) {
boolean result = false;
try {
ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
operations.set(key, value);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/
*** 写入缓存设置时效时间
* @param key
* @param value
* @return
*/
public boolean set(final String key, Object value, Long expireTime) {
boolean result = false;
try {
ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
operations.set(key, value);
redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/
*** 批量删除对应的value
* @param keys
*/
public void remove(final String... keys) {
for (String key : keys) {
remove(key);
}
}
/
*** 批量删除key
* @param pattern
*/
public void removePattern(final String pattern) {
Set<Serializable> keys = redisTemplate.keys(pattern);
if (keys.size() > 0)
redisTemplate.delete(keys);
}
/
*** 删除对应的value
* @param key
*/
public void remove(final String key) {
if (exists(key)) {
redisTemplate.delete(key);
}
}
/
*** 判断缓存中是否有对应的value
* @param key
* @return
*/
public boolean exists(final String key) {
return redisTemplate.hasKey(key);
}
/
*** 读取缓存
* @param key
* @return
*/
public Object get(final String key) {
Object result = null;
ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
result = operations.get(key);
return result;
}
/
*** 哈希 添加
* @param key
* @param hashKey
* @param value
*/
public void hmSet(String key, Object hashKey, Object value){
HashOperations<String, Object, Object> hash = redisTemplate.opsForHash();
hash.put(key,hashKey,value);
}
/
*** 哈希获取数据
* @param key
* @param hashKey
* @return
*/
public Object hmGet(String key, Object hashKey){
HashOperations<String, Object, Object> hash = redisTemplate.opsForHash();
return hash.get(key,hashKey);
}
/
*** 列表添加
* @param k
* @param v
*/
public void lPush(String k,Object v){
ListOperations<String, Object> list = redisTemplate.opsForList();
list.rightPush(k,v);
}
/
*** 列表获取
* @param k
* @param l
* @param l1
* @return
*/
public List<Object> lRange(String k, long l, long l1){
ListOperations<String, Object> list = redisTemplate.opsForList();
return list.range(k,l,l1);
}
/
*** 集合添加
* @param key
* @param value
*/
public void add(String key,Object value){
SetOperations<String, Object> set = redisTemplate.opsForSet();
set.add(key,value);
}
/
*** 集合获取
* @param key
* @return
*/
public Set<Object> setMembers(String key){
SetOperations<String, Object> set = redisTemplate.opsForSet();
return set.members(key);
}
/
*** 有序集合添加
* @param key
* @param value
* @param scoure
*/
public void zAdd(String key,Object value,double scoure){
ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
zset.add(key,value,scoure);
}
/
*** 有序集合获取
* @param key
* @param scoure
* @param scoure1
* @return
*/
public Set<Object> rangeByScore(String key,double scoure,double scoure1){
ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
return zset.rangeByScore(key, scoure, scoure1);
}
}
测试用的Controller
package www.ijava.com.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import www.ijava.com.service.RedisService;
@RestController
public class DemoController {
@Autowired
private RedisService redisService ;
@RequestMapping(value = "/test")
public String demoTest(){
boolean result = redisService.set("1","value");
Object object = redisService.get("1");
Object name = redisService.get("name");
System.out.println(object);
return result+"-------"+object+" ---"+name;
}
}
使用Redis-cli客户端查看
Java中间件-ehcache
ehcache是一个用于管理缓存的工具,其核心组件是源码cacheManager,负责创建、源码管理缓存。源码荒野套牛源码缓存由cacheManager下的源码cache实例实现,而cache内部存储的源码是键值对。cacheManager用于创建、源码移除和访问cache。源码
创建cacheManager的源码方式多样,可通过构造方法或静态方法实现。源码使用构造方法创建cacheManager时,源码会使用默认配置或自定义配置。源码默认配置下,源码ehcache会查找类根路径下的ehcache.xml配置文件,若未找到则使用ehcache-failsafe.xml作为默认配置。构造方法允许指定名称、存储路径及配置文件,同时能控制是否允许动态修改配置。
静态方法创建cacheManager时,提供两种方式:create()和newInstance()。create()方法创建单例,newInstance()方法创建的实例可能为单例或非单例,取决于前一次创建的实例是否存在。create()方法首先检查内部singleton对象是否为空,非空则直接返回,空则根据参数创建实例并赋值给singleton。newInstance()方法在有同名实例时返回现有实例,c 抽奖动画源码避免抛出异常。使用newInstance()方法创建时,会检查是否有同名实例存在,如有则直接返回,无则新建实例。
ehcache的配置文件(ehcache.xml)包含缓存大小、生命周期、缓存策略等信息,允许自定义缓存行为。通过构造方法或静态方法结合配置文件,可灵活创建和管理cacheManager,实现高效的数据缓存。ehcache通过缓存策略减少数据库访问,提高应用程序性能,适用于需要频繁访问数据的场景。
Spring缓存注解@Cacheable、@CacheEvict、@CachePut使用
首先,我们需要在我们的缓存方法上添加对应的注解以标识其为缓存方法。
使用@Cacheable注解表示一个方法的结果会被缓存,当再次调用该方法时,会先从缓存中查找结果,如果存在则直接返回,若不存在则执行方法并缓存结果。
其次,我们需要在我们的缓存配置类中,通过CacheManager或CacheFactoryBean配置缓存管理器,定义缓存的动能线指标源码相关属性,如缓存名称、过期时间、缓存策略等。
在配置完成后,可以在需要缓存的方法上使用@Cacheable注解,如:@Cacheable(value = "myCache", key = "#id"),表示该方法的结果会被缓存到名为"myCache"的缓存中,同时使用方法参数$id作为缓存的键。
若某个方法的执行结果需要从缓存中删除,可以使用@CacheEvict注解,如:@CacheEvict(value = "myCache", key = "#id"),表示当执行该方法时,会删除缓存中与方法参数$id对应的键值对。
如果某个方法的结果需要在缓存中更新,可以使用@CachePut注解,如:@CachePut(value = "myCache", key = "#id"),表示在执行方法后,会将方法执行结果存入缓存中与方法参数$id对应的键值对。
使用Spring Cache可以有效提升应用性能,减少数据库访问,提高响应速度。正确合理地使用缓存策略,可以帮助我们构建更高效、更稳定的系统。
SpringBoot的Cacheable缓存注解
为了提升应用程序的性能,我们在处理大量数据读取和写入操作时,往往会采用缓存技术。Spring Boot 提供了一套高效便捷的从源码编译recovery缓存解决方案,支持将数据缓存至 Redis 中。
在 Spring Boot 中,我们只需在方法上添加相应的注解即可实现缓存功能。
首先,您需要在项目中引入 Redis 依赖。以下是在 pom.xml 中添加 Redis 依赖的示例:
引入 Redis 依赖后,接下来需要配置 Redis 相关信息。以下是一个 Redis 配置的示例:
在此配置中,host 和 port 属性分别指定了 Redis 服务器的主机名和端口号,password 属性用于指定 Redis 服务器的密码(如果有的话),而 database 属性则指定了 Redis 服务器使用的数据库编号。
Redis 默认序列化器为 JdkSerializationRedisSerializer,但通常我们更倾向于使用 StringRedisSerializer 或 Jackson2JsonRedisSerializer 将缓存值序列化为字符串或 JSON 格式。以下是一个自定义序列化器的示例配置:
在这个示例中,我们通过自定义 Bean 配置了 RedisTemplate,使用 StringRedisSerializer 序列化 Redis 键,并使用 Jackson2JsonRedisSerializer 序列化 Redis 值为 JSON 格式。
使用 Cacheable 注解来标记需要进行缓存的方法。以下是一个带有 Cacheable 注解的示例方法:
在这个例子中,@Cacheable 注解用于标记 getUserById 方法,value 属性用于指定缓存的存储区域名称。由于我们正在使用 Redis 作为缓存,因此 Redis 中的 key 将由 Cacheable 注解中的 key 属性指定。在此示例中,key 属性设置为 "#id",这意味着我们将使用方法参数 id 作为 Redis 缓存的键。
在某些情况下,我们需要以多个参数作为 key 来缓存数据。怎么阅读框架源码此时,我们可以使用表达式语言(SpEL)来设置多个参数,如下所示:
在这个示例中,我们使用了表达式语言(SpEL)将 id 和 name 两个参数组合成了一个 Redis 缓存键。
缓存的有效期对缓存的性能和可靠性有很大影响。可以使用 @Cacheable 注解上的 expire 属性来设置缓存的过期时间。以下是一个设置缓存时效的示例:
在此示例中,我们添加了名为 expire 的属性,该属性用于指定缓存的过期时间(以秒为单位)。在此示例中,我们设置了缓存过期时间为 秒,即 分钟。
有时候,我们需要清除 Redis 缓存中的某些数据,以便在下一次访问时重建缓存。在 Spring Boot 中,可以使用 @CacheEvict 注解来清除 Redis 缓存中的数据。以下是一个使用 @CacheEvict 注解的示例:
在这个例子中,我们添加了删除单个用户和删除所有用户的方法,使用 @CacheEvict 注解来删除 Redis 缓存中的相应数据。请注意,我们设置了 allEntries 属性为 true,以删除所有缓存中的数据。
有时候,我们需要在特定条件下才进行缓存操作。例如,只有当用户年龄大于 岁时才进行缓存。在 Spring Boot 中,可以使用 @Cacheable、@CachePut 和 @CacheEvict 注解上的 condition 属性来设置缓存条件。以下是一个使用 condition 属性的示例:
在这个例子中,我们添加了一个名为 condition 的属性,该属性用于指定缓存的条件。在此示例中,我们将 condition 属性设置为 "#age > ",这意味着只有当 age 大于 时,才进行缓存操作。
在实际使用中,应用程序缓存数据的管理也是非常重要的。Spring Boot 提供了一个名为 CacheManager 的接口,您可以使用它来创建并管理缓存对象。以下是一个使用 CacheManager 的示例:
在这个示例中,我们创建了一个名为 CacheConfig 的配置类,并使用 @EnableCaching 注解来开启缓存支持。然后,我们通过实现 CachingConfigurerSupport 接口,覆盖 cacheManager 方法,创建了一个 RedisCacheManager 对象,并将其返回。在此 RedisCacheManager 中,我们使用默认的 RedisCacheConfiguration 进行了一些配置,例如设置缓存的过期时间,同时指定了 Redis 的连接信息。
本文介绍了如何在 Spring Boot 应用程序中使用 Redis 进行缓存,包括配置 RedisTemplate、使用 Cacheable 注解、设置缓存有效期、使用 @CacheEvict 清除缓存数据以及使用 CacheManager 管理缓存等。
一些小众冷门但却非常实用的.NET(Core)开源库推荐
今天,我要向大家介绍一些我个人在.NET(Core)开发中使用的、虽然不太热门但极其实用的开源库。这些库虽然点赞数不高,但它们在实际项目中的价值不可小觑。本文聚焦于那些小众且鲜为人知的工具库,避免了大家耳熟能详的如AutoMapper、Autofac等。
首先,是我的开源作品Masuit.Tools,它集合了丰富的功能,涵盖了数据库操作、日期时间处理、文件操作、硬件监控、HTML操作、日志管理、多媒体文件操作、网络通信、Nosql操作、反射、加密安全、字符串扩展、WinAPI以及全局扩展等。它的存在使得我的代码更加简洁高效,几乎不可或缺。目前,该库在GitHub上的star数超过个,证明了它的实用性和价值。
其次,Masuit.LuceneEFCore.SearchEngine是一个本地搜索引擎,基于EntityFrameworkCore和Lucene.NET,提供高性能全文检索,适用于基于EntityFrameworkCore的数据库应用。它支持权重查询,响应快速。
CacheManager是强大的缓存中间件,简化了开发者的工作,支持多种缓存提供者和高级功能。它不仅提供统一的编程模型,还支持多层缓存和高级功能如缓存同步。
htmldiff.net-core用于比较HTML文件,提供直观的差异显示,方便调试。IP2Region和MaxMind.GeoIP2则用于IP地址的地理信息查询,具有极高的准确性和查询速度。
Karambolo.AspNetCore.Bundling.NUglify解决了.NET Core MVC中静态资源压缩的痛点,提供了与.NET Framework相似的使用体验,有助于前端性能优化。
OpenXmlPowerTools扩展了Open XML SDK,支持DOCX、XLSX和PPTX文件的编程操作,如数据填充、转换和搜索替换等。
其他的库如Svg用于SVG图形操作,TimeZoneConverter处理时区转换,RssSyndication支持RSS订阅接口,Z.EntityFramework.Plus.EFCore优化了EFCore性能,SharpCompress提供文件压缩功能,DnsClient高效DNS查询,HtmlAgilityPack解析HTML,HtmlSanitizer防止XSS攻击,ObjectsComparer用于对象比较,SearchExtensions提供简单全文检索,都各有其独特的实用价值。
以上就是我精心挑选的开源库,虽然小众,但它们在提升开发效率和项目质量上发挥了重要作用。如果你也发现有类似的宝藏库,欢迎分享,让我们一起提高编程效率,减少加班时间。
RedisCacheManager设置Value序列化器技巧
配置CacheManager时,需参考博文:springboot2.0 redis EnableCaching的配置和使用。RedisCacheManager构造函数需提供RedisOperations实例,即RedisTemplate。在创建缓存时,通过RedisCache构造函数传入redisOperations。
采用全局通用的序列化器GenericJackson2JsonRedisSerializer,调试发现序列化内容加入对象的类型信息。此序列化器通过Jackson的ObjectMapper实现序列化与反序列化,开启默认类型配置。使用Protostuff自定义序列化与反序列化工具,测试结果显示同样加入对象类型信息。JdkSerializationRedisSerializer内部使用ObjectInputStream与ObjectOutputStream完成序列转换与反序列化,发现序列化内容同样加入类型信息。若要缓存的Java对象需实现Serializable接口,否则将引发特定错误。
当设置Jackson2JsonRedisSerializer,内部序列化过程通过Jackson ObjectMapper完成,不包含对象类型信息。使用此序列化器时需指定缓存对象类型。通过实现不同RedisCache对应不同RedisTemplate(即不同序列化器)的策略,实现自定义RedisCacheManager。RedisCacheManager通过加载自定义配置实现类RedisCacheConfigurationProvider获取不同RedisCache的配置。自定义RedisCache配置提供者抽象类,根据不同的缓存类型设置不同序列化器,允许用户根据缓存名称设置不同存储类型。
复合CacheManager通过实现给定的委托CacheManager实例集合,配置多个CacheManager,每个CacheManager可配置不同序列化器。注意,如果复合管理器委托的常规CacheManagers在请求时回退到命名缓存的延迟创建,需确保它们能处理未知缓存名称的情况,或在请求时自动创建缓存区域。通过这种方式,可以灵活配置不同缓存的序列化策略。