SpringBoot之redis
SpringBoot之redis
王念博客 发表于2年前
SpringBoot之redis
  • 发表于 2年前
  • 阅读 11502
  • 收藏 16
  • 点赞 1
  • 评论 11

腾讯云 技术升级10大核心产品年终让利>>>   

        redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。    

 

1.导入jar包依赖

<dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-redis</artifactId>
</dependency>

2.相应的配置

# REDIS (RedisProperties)
#spring.redis.database=
spring.redis.host=
spring.redis.password=
spring.redis.port=6379 
spring.redis.pool.max-idle=100 
spring.redis.pool.min-idle=1
spring.redis.pool.max-active=1000
spring.redis.pool.max-wait=-1
server.port=8081

3.编写cache管理类

package com.example;
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;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
    /**
     * 缓存管理(注解用)
     * @author Administrator
     *
     */
    @Configuration
    @EnableCaching
    public class CacheService extends CachingConfigurerSupport {
            
        /**
     * 生成key的策略
     *
     * @return
     */
    @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();
            }
        };
    }
    
    /**
     * 管理缓存
     *
     * @param redisTemplate
     * @return
     */
    @SuppressWarnings("rawtypes")
    @Bean
    public CacheManager cacheManager(RedisTemplate redisTemplate) {
        RedisCacheManager rcm = new RedisCacheManager(redisTemplate);
        //设置缓存过期时间
        // rcm.setDefaultExpiration(60);//秒
        //设置value的过期时间
        Map<String,Long> map=new HashMap();
        map.put("test",60L);
        rcm.setExpires(map);
        return rcm;
    }
    
    /**
     * RedisTemplate配置
     * @param factory
     * @return
     */
    @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);//如果key是String 需要配置一下StringSerializer,不然key会乱码 /XX/XX
        template.afterPropertiesSet();
        return template;
    }
}

4.常用的操作redis的方法

package com.example;
import java.io.Serializable;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
/**
 * redicache 工具类
 * 
 */
@SuppressWarnings("unchecked")
@Component
public class RedisUtil {
@SuppressWarnings("rawtypes")
@Autowired
private RedisTemplate redisTemplate;
/**
 * 批量删除对应的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 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;
}
}

 

5.在方法前面加上缓存

@RequestMapping("/")
@Cacheable(value="test")
public String getSessionId(HttpSession session){
redisUtil.set("123", "测试");
System.out.println("进入了方法");
String string= redisUtil.get("123").toString();
return string;
}

@Cacheable参数

value  指明缓存将被存到什么地方。

key     Spring默认使用被@Cacheable注解的方法的签名来作为key

condition = "#age < 25" 数将指明方法的返回结果是否被缓存。

本文地址(防爬虫不标注来源):http://my.oschina.net/wangnian/blog/661389

标签: springboot redis
共有 人打赏支持
粉丝 120
博文 92
码字总数 52286
评论 (11)
absurd717
你好。如果使用缓存,返回的是一个分页对象org.springframework.data.domain.Page会报
2016-09-21 13:28:50.226 ERROR 17716 --- [nio-7878-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.data.redis.serializer.SerializationException: Could not read JSON: Can not construct instance of org.springframework.data.domain.PageImpl: no suitable constructor found, can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?)
at [Source: [B@206540; line: 1, column: 46]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of org.springframework.data.domain.PageImpl: no suitable constructor found, can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?)
at [Source: [B@206540; line: 1, c
absurd717
com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of org.springframework.data.domain.PageImpl: no suitable constructor found, can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?)
at [Source: [B@206540; line: 1, column: 46]
  at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:261) ~[jackson-databind-2.8.3.jar:2.8.3]
意思是PageImpl没有无参构造函数,怎么解决?
王念博客
这不是缓存的问题 而是jackson的异常,你可以把PageImpl类拷贝出来手动加个构造方法 或者看看jackson有没有注解解决这个问题。
absurd717

引用来自“王念博客”的评论

这不是缓存的问题 而是jackson的异常,你可以把PageImpl类拷贝出来手动加个构造方法 或者看看jackson有没有注解解决这个问题。
public class PageImplBean extends PageImpl {

private static final long serialVersionUID = 1L;
private int number;
private int size;
private int totalPages;
private int numberOfElements;
private long totalElements;
private boolean previousPage;
private boolean firstPage;
private boolean nextPage;
private boolean lastPage;
private List content;
private Sort sort;

public PageImplBean() {
super(new ArrayList());
}

public int getNumber() {
return number;
}

public void setNumber(int number) {
this.number = number;
}

public int getSize() {
return size;
}

public void setSize(int size) {
this.size = size;
}

public int getTotalPages() {
return totalPages;
}

public void setTotalPages(int totalPages) {
this.totalPages = totalPages;
}

public int getNumberOfElements() {
return numberOfElements;
}

public void setNumberOfElements(int numberOfElements) {
this.numberOfElements = numberOfElements;
}

public long getTotalElements() {
return totalElements;
}

public void setTotalElements(long totalElements) {
this.totalElements = totalElements;
}

public boolean isPreviousPage() {
return previousPage;
}

public void setPreviousPage(boolean previousPage) {
this.previousPage = previousPage;
}

public boolean isFirstPage() {
return firstPage;
}

public void setFirstPage(boolean firstPage) {
this.firstPage = firstPage;
}

public boolean isNextPage() {
return nextPage;
}

public void setNextPage(boolean nextPage) {
this.nextPage = nextPage;
}

public boolean isLastPage() {
return lastPage;
}

public void setLastPage(boolean lastPage) {
this.lastPage = lastPage;
}

public List getContent() {
return content;
}

public void setContent(List content) {
this.content = content;
}

public Sort getSort() {
return sort;
}

public void setSort(Sort sort) {
this.sort = sort;
}

public PageImpl pageImpl() {
return new PageImpl(getContent(), new PageRequest(getNumber(),
getSize(), getSort()), getTotalElements());
}
}
absurd717

引用来自“王念博客”的评论

这不是缓存的问题 而是jackson的异常,你可以把PageImpl类拷贝出来手动加个构造方法 或者看看jackson有没有注解解决这个问题。
结果报了Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.ClassCastException: org.springframework.data.domain.PageImpl cannot be cast to com.absurd.core.model.PageImplBean] with root cause
Kevin_Zhan
配置文件都没引用到,spring怎么知道这个redis的配置在哪呢,对应的key是什么呢
王念博客

引用来自“Kevin_Zhan”的评论

配置文件都没引用到,spring怎么知道这个redis的配置在哪呢,对应的key是什么呢
这是springBoot的配置,不是spring xml配置的方式。
Kevin_Zhan

引用来自“Kevin_Zhan”的评论

配置文件都没引用到,spring怎么知道这个redis的配置在哪呢,对应的key是什么呢

引用来自“王念博客”的评论

这是springBoot的配置,不是spring xml配置的方式。
你的意思是 他默认会去application.properties去寻找对应的redis的属性,比如host,timeout,然后注入到redis吗?
王念博客

引用来自“Kevin_Zhan”的评论

配置文件都没引用到,spring怎么知道这个redis的配置在哪呢,对应的key是什么呢

引用来自“王念博客”的评论

这是springBoot的配置,不是spring xml配置的方式。

引用来自“Kevin_Zhan”的评论

你的意思是 他默认会去application.properties去寻找对应的redis的属性,比如host,timeout,然后注入到redis吗?
差不多就是这个意思,你如果加了spring-boot-starter实现的包,再启动Springboot项目就会去application.properties里找对应的配置初始化第三方包的配置,如果你之前不了解Springboot的话可能跑个简单的例子就明白啦。
彬彬彬彬

引用来自“王念博客”的评论

这不是缓存的问题 而是jackson的异常,你可以把PageImpl类拷贝出来手动加个构造方法 或者看看jackson有没有注解解决这个问题。

引用来自“absurd717”的评论

结果报了Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.ClassCastException: org.springframework.data.domain.PageImpl cannot be cast to com.absurd.core.model.PageImplBean] with root cause
哥们、请教一下、这个问题你解决了没有?
PERFECTDAY
RedisUtil报错: No qualifying bean of type 'org.springframework.data.redis.core.RedisTemplate<?, ?>' available: expected at least 1 bean which qualifies as autowire candidate.
×
王念博客
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: