spring boot 整合 redis
来源:互联网 发布:淘宝一比一高仿奢侈品 编辑:程序博客网 时间:2024/06/06 09:22
1 引入依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <version>1.5.6.RELEASE</version></dependency>
2 添加配置
配置默认是写在application.properties或application.yml中,也可以自己新建一个资源文件,但是在RedisCacheConfig用需要注解出配置具体的文件
###########################################################REDIS (RedisProperties) redis基本配置######################################################### database namespring.redis.database=0# Redis服务器IPspring.redis.host=10.176.65.137# Redis密码spring.redis.password=redis# Redis端口号spring.redis.port=6379# 连接超时时间 单位 ms(毫秒)spring.redis.timeout=3000###########################################################REDIS (RedisProperties) redis线程池设置######################################################### 控制一个pool最多有多少个状态为idle(空闲的)的jedis实例,默认值也是8。spring.redis.pool.max-idle=20# 控制一个pool最少有多少个状态为idle(空闲的)的jedis实例,默认值也是0。spring.redis.pool.min-idle=10# 如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽)。spring.redis.pool.max-active=60# 等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。如果超过等待时间,则直接抛出JedisConnectionExceptionspring.redis.pool.max-wait=3000#######################################################################################REDIS (RedisProperties) redis哨兵设置,和上面的host和port不要同时配置##################################################################################### Redis服务器master的名字#spring.redis.sentinel.master=master8026# redis-sentinel的配置地址和端口(注意:不是redis的地址和端口)#spring.redis.sentinel.nodes=10.189.80.25:26379,10.189.80.26:26379,10.189.80.26:26378###########################################################REDIS (RedisProperties) redis 自定义参数#########################################################默认生命周期30天spring.redis.defaultExpiration = 2592000#服务器上下文路径spring.redis.contextPath = contextPath
3 redis配置代码实现
import com.fasterxml.jackson.annotation.JsonAutoDetect;import com.fasterxml.jackson.annotation.PropertyAccessor;import com.fasterxml.jackson.databind.ObjectMapper;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.cache.Cache;import org.springframework.cache.annotation.*;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.PropertySource;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.serializer.Jackson2JsonRedisSerializer;import org.springframework.data.redis.serializer.RedisSerializer;import org.springframework.data.redis.serializer.StringRedisSerializer;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.util.*;/** * @author qianjianfeng * @version 1.0.0 * @since 1.0.0 */@Configuration@ConfigurationProperties(prefix = "spring.redis")@PropertySource(value = "classpath:/META-INF/redis.properties")@EnableCachingpublic class RedisCacheConfig extends CachingConfigurerSupport { private Logger logger = LoggerFactory.getLogger(this.getClass()); private Long defaultExpiration; private String contextPath; public Long getDefaultExpiration() { return defaultExpiration; } public void setDefaultExpiration(Long defaultExpiration) { this.defaultExpiration = defaultExpiration; } public String getContextPath() { return contextPath; } public void setContextPath(String contextPath) { this.contextPath = contextPath; } /** * 自定义key. * key --> 项目名 + 缓存空间值 + 所有参数的值 * 即使@Cacheable中的value属性一样,key也会不一样。 */ @Bean @Override public KeyGenerator keyGenerator() { return new KeyGenerator(){ @Override public String generate(Object o, Method method, Object... objects) { // This will generate a unique key of the class name, the method name //and all method parameters appended. StringBuilder sb = new StringBuilder(); sb.append(contextPath).append("/:"); Cacheable cacheable = method.getAnnotation(Cacheable.class); CachePut cachePut = method.getAnnotation(CachePut.class); CacheEvict cacheEvict = method.getAnnotation(CacheEvict.class); if (cacheable != null) { sb.append(Arrays.toString(cacheable.value())).append(":"); }else if (cachePut != null) { sb.append(Arrays.toString(cachePut.value())).append(":"); }else if (cacheEvict != null) { sb.append(Arrays.toString(cacheEvict.value())).append(":"); } Map valueMap = new HashMap(); for (Object obj : objects) { try { getStringValueMap(obj,valueMap); } catch (IllegalAccessException e) { logger.info("生成key的时候,[{}]转换map异常,生成的key丢弃了该值。",obj.getClass(),e); } } sb.append(valueMap.toString()); System.err.println(sb.toString()); return sb.toString(); } }; } /** * redis模板操作类,类似于jdbcTemplate的一个类; * 虽然CacheManager也能获取到Cache对象,但是操作起来没有那么灵活; * 这里在扩展下:RedisTemplate这个类不见得很好操作,我们可以在进行扩展一个我们 * 自己的缓存类,比如:RedisStorage类; * @param factory : 通过Spring进行注入,参数在application.properties进行配置; * @return */ @Bean public RedisTemplate<String,String> redisTemplate(RedisConnectionFactory factory) { RedisTemplate<String,String> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(factory); //key序列化方式;(不然会出现乱码;),但是如果方法上有Long等非String类型的话,会报类型转换错误; //所以在没有自己定义key生成策略的时候,以下这个代码建议不要这么写,可以不配置或者自己实现ObjectRedisSerializer //或者JdkSerializationRedisSerializer序列化方式; RedisSerializer<String> redisSerializer = new StringRedisSerializer();//Long类型不可以会出现异常信息; redisTemplate.setKeySerializer(redisSerializer); redisTemplate.setHashKeySerializer(redisSerializer); 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); redisTemplate.setValueSerializer(jackson2JsonRedisSerializer); redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer); redisTemplate.afterPropertiesSet(); return redisTemplate; } /** * 缓存管理器 * @param redisTemplate * @return */ @Bean public RedisCacheManager cacheManager(RedisTemplate<?,?> redisTemplate) { RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate); cacheManager.setDefaultExpiration(defaultExpiration);//默认生命周期30天 return cacheManager; } /** * redis数据操作异常处理 * 这里的处理:在日志中打印出错误信息,但是放行 * 保证redis服务器出现连接等问题的时候不影响程序的正常运行,使得能够出问题时不用缓存 * @return */ @Bean @Override public CacheErrorHandler errorHandler() { CacheErrorHandler cacheErrorHandler = new CacheErrorHandler() { @Override public void handleCacheGetError(RuntimeException e, Cache cache, Object key) { logger.error("redis异常:key=[{}]",key,e); } @Override public void handleCachePutError(RuntimeException e, Cache cache, Object key, Object value) { logger.error("redis异常:key=[{}]",key,e); } @Override public void handleCacheEvictError(RuntimeException e, Cache cache, Object key) { logger.error("redis异常:key=[{}]",key,e); } @Override public void handleCacheClearError(RuntimeException e, Cache cache) { logger.error("redis异常:",e); } }; return cacheErrorHandler; } /** * 取出对象及其父类定义的字段名和值存入map中 * @param obj * @param valueMap * @throws IllegalAccessException */ private void getStringValueMap(Object obj, Map valueMap) throws IllegalAccessException { List<Field> fields = scanfields(obj.getClass()); for (Field field : fields){ Boolean accessFlag = field.isAccessible(); field.setAccessible(true); Object o = field.get(obj); if (o != null){ if (o instanceof Integer || o instanceof Long || o instanceof Float || o instanceof Double || o instanceof String || o instanceof Collections || o instanceof Map || o instanceof Byte){ valueMap.put(field.getName(), o.toString()); }else { getStringValueMap(o,valueMap); } } field.setAccessible(accessFlag); } } /** * 对一个类扫描取出它和它父类定义的字段 * @param clazz * @return */ private List<Field> scanfields(Class clazz){ List<Field> fields = new ArrayList<>(); if (clazz == Object.class) { return fields; } Field[] fieldArray = clazz.getDeclaredFields(); String fieldName; for (int i = 0; i < fieldArray.length; i++){ fieldName = fieldArray[i].getName(); if (!("$staticClassInfo".equals(fieldName) || "__$stMC".equals(fieldName) || "metaClass".equals(fieldName) || "$staticClassInfo$".equals(fieldName) || "$callSiteArray".equals(fieldName))){ fields.add(fieldArray[i]); } } fields.addAll(scanfields(clazz.getSuperclass())); return fields; }}
4 测试
目前为止,所有的配置都已经写完了,接下来就是测试了。既然我们整合的是springboot,那接下来再依赖一个启动器,当然他的parent依赖也要加上,具体看springboot文档
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>1.5.6.RELEASE</version></dependency>
测试用的service,需要缓存操作的加上Cacheable、CacheEvict或CachePut,必须要赋予value值
import org.springframework.cache.annotation.CacheEvict;import org.springframework.cache.annotation.Cacheable;import org.springframework.stereotype.Service;@Servicepublic class TestService { @Cacheable(value = "hello") public Person hello(Person person){ System.err.println("2"); return person; } @Cacheable(value = "hello2") public Person hello2(Person person){ System.err.println("2"); return person; } @CacheEvict(value = "hello") public Person bye(Person person){ System.err.println("2"); return person; } @CacheEvict(value = "hello2") public Person bye2(Person person){ System.err.println("2"); return person; } @Cacheable(value = "door") public Door door(Door door){ System.err.println("2"); return door; }}
import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestControllerpublic class TestController { @Autowired private TestService testService; @RequestMapping("/hello/{age}") public Person hello(@PathVariable int age){ Person person = new Person("link",age,new Head(2,1)); return testService.hello(person); } @RequestMapping("/hello2/{age}") public Person hello2(@PathVariable int age){ Person person = new Person("link",age,new Head(2,1)); return testService.hello2(person); } @RequestMapping("/bye/{age}") public Person bye(@PathVariable int age){ Person person = new Person("link",age,new Head(2,1)); return testService.bye(person); } @RequestMapping("/bye2/{age}") public Person bye2(@PathVariable int age){ Person person = new Person("link",age,new Head(2,1)); return testService.bye2(person); } @RequestMapping("/door/{id}") public Door door(@PathVariable int id){ Door door = new Door(id); return testService.door(door); }}
spring boot的启动文件
import org.springframework.boot.SpringApplicationimport org.springframework.boot.autoconfigure.SpringBootApplication@SpringBootApplicationpublic class Application { static void main(String[] args) { SpringApplication.run(Application.class,args) }}
原本这边放了目录结构和测试的图片,结果发上来一看图片飞走了,还是大家自己动手试试吧~~
阅读全文
0 0
- spring boot整合redis
- spring boot 整合 redis
- spring boot整合redis
- Spring Boot整合Redis
- spring boot redis整合
- spring-boot整合redis 总结
- (七)Spring Boot 整合Redis
- spring boot shiro redis整合
- spring boot中spring cache 整合redis
- spring boot整合redis主从sentinel
- spring boot 中redis与cookie整合
- spring boot整合redis实现缓存机制
- Spring Boot 整合 Redis 实现缓存操作
- Spring Boot 整合 Redis 实现缓存操作
- Spring boot整合redis小例子
- Spring Boot 整合 Redis 实现缓存操作
- spring boot整合redis(单机+集群)
- Spring Boot 整合 Redis 实现缓存操作
- JAVA操作properties文件
- 考试排名 oj115
- 第15章 泛型
- Springmvc 上传文件MultipartFile 转File 笔记
- SSD代码部分笔记附加keras版本代码
- spring boot 整合 redis
- 【DL--20】各种编程语言的深度学习库整理
- 反省
- Android 富文本 SpannableString的使用
- [读书笔记] 《机器学习-实用案例解析》 Wiki
- 三种方式实现二维码(java)
- Mac OS 登录服务器使用 iTerm2 rz/sz命令
- CEF3研究(三)
- QT QSS 记录下 留着以后用