springboot 集成redis 和http请求

2018-12-12  本文已影响225人  Helen_Cat

springboot 集成redis ,使用原生的jedis ,有点繁琐,本身springboot 已经集成了 redis并有 redisTemplate 可以使用,不过还是多少有点坑,需要提前说明的
首先要引入jar包依赖

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

然后在 application 配置文件中 配置redis 的连接项

spring.redis.database=0
spring.redis.host= 10.201.9.23

spring.redis.port=6379
spring.redis.password=88888
spring.redis.auth=88888
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=5000

接着最简单的使用就是

   @Autowired
    protected RedisTemplate<Object ,Object>  redisTemplate;

或者

    @Autowired
  protected StringRedisTemplate redisTemplate;

如果你配置环境对的话,redis 就可以使用了
springboot 在启动会自己初始化 RedisConnectionFactory redisConnectionFactory
这个对象,然后注入 ,并初始化化一个 RedisTemplate 对象,这样感觉无缝连接到redis了,但是吧,平时没问题,一旦时间久了就会出问题,就是redis 的序列化和反序列化问题,之前没有在log 里捕捉 这个反序列化的异常,后来捕捉到这个异常,

ERROR] 2018-03-07 14:05:03,747 XXX - Cannot deserialize; nested exception is org.springframework.core.serializer.support.SerializationFailedException: Failed to deserialize payload. Is the byte array a result of corresponding serialization for DefaultDeserializer?; nested exception is java.io.StreamCorruptedException: invalid stream header: 6E756C6C
--------------------- 
作者:竹子鸠 
来源:CSDN 
原文:https://blog.csdn.net/yexiaojiu1/article/details/79470439 
版权声明:本文为博主原创文章,转载请附上博文链接!

springboot在反序列话 redis,有点bug
如何破解 ,就是在初始化 RedisTemplate 这个bean 的时候就配置一下序列化和反序列化的属性,
声明一个 RedisService 公共类,并加 @Component 注解, 在这个里面初始化化 RedisTemplate,需要注意的是 就是你的key 对应的value存的是什么类型,如果是String
,就用new StringRedisSerializer(),如果是对象类 json ,就使用
new Jackson2JsonRedisSerializer(Object.class);或者
new GenericJackson2JsonRedisSerializer()),不然这个还会报错,
然后我们在这个里面 声明 get set exist remove redis key 的操作

最后使用 redis 的时候 ,直接注入 RedisService 就可以了

  @Autowired
  private RedisService redisService;

RedisService

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.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Component
public class RedisService {




    protected  final Logger logger=LoggerFactory.getLogger(RedisService.class);

//    @Autowired
//    protected   RedisConnectionFactory redisConnectionFactory;

    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory)  {
        //RedisTemplate<String, String>
        logger.info("尝试初始化redis template");
        RedisTemplate<Object ,Object>  redisTemplate= new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);


        //使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值
        Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);

        ObjectMapper mapper = new ObjectMapper();
        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        serializer.setObjectMapper(mapper);


        //使用StringRedisSerializer来序列化和反序列化redis的key值
        redisTemplate.setKeySerializer(new StringRedisSerializer());
//        redisTemplate.setValueSerializer(serializer);
        redisTemplate.setStringSerializer(new StringRedisSerializer());
       redisTemplate.setValueSerializer(new StringRedisSerializer());
//        redisTemplate.setEnableDefaultSerializer(true);
       // redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());

        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(serializer);

        redisTemplate.afterPropertiesSet();

        logger.info("redis init successful 初始化成功");
        this.redisTemplate=redisTemplate;
   

        return this.redisTemplate;
    }

    @Autowired
    protected RedisTemplate<Object ,Object>  redisTemplate;
    /**
     * 写入redis缓存(不设置expire存活时间)
     * @param key
     * @param value
     * @return
     */
    public boolean set(final String key, String value){
        boolean result = false;
        try {
            logger.info("正在insert设置  "+key+"的redis 值"+value);
            ValueOperations operations =redisTemplate.opsForValue();
            operations.set(key, value);
            result = true;
            logger.info(key+" 插入redis 成功 "+value);
        } catch (Exception e) {
            logger.error("写入redis缓存失败!错误信息为:" + e.getMessage());
        }
        return result;
    }

    /**
     * 写入redis缓存(设置expire存活时间)
     * @param key
     * @param value
     * @param expire
     * @return
     */
    public boolean set(final String key, String value, Long expire){
        boolean result = false;
        try {
            logger.info("正在设置  "+key+"的redis 值"+value+" expire "+expire);

            ValueOperations operations = redisTemplate.opsForValue();
            operations.set(key, value);
            redisTemplate.expire(key, expire, TimeUnit.SECONDS);
            result = true;
            logger.info(key+" 插入redis 成功 "+value);
        } catch (Exception e) {
            logger.error("写入redis缓存(设置expire存活时间)失败!错误信息为:" + e.getMessage());
        }
        return result;
    }


    /**
     * 读取redis缓存
     * @param key
     * @return
     */
    public Object get(final String key){
        Object result = null;
        try {
            logger.info("正在尝试获取 "+key+"的redis 值");
            ValueOperations operations = redisTemplate.opsForValue();
            result = operations.get(key);
            logger.info("get 得到  "+key+"的redis 值"+result);
        } catch (Exception e) {

            logger.error("读取redis缓存失败!错误信息为:" + e.getMessage());
            String connect=redisTemplate.getConnectionFactory().getConnection().toString();
            logger.error(connect);
        }
        return result;
    }

    /**
     * 判断redis缓存中是否有对应的key
     * @param key
     * @return
     */
    public boolean exists(final String key){
        boolean result = false;
        try {
            logger.info("正在查看  "+key+"的redis 值 是否存在");
            result = redisTemplate.hasKey(key);
            logger.info("查看  "+key+"的redis 值 存在 结果 "+result);
        } catch (Exception e) {
            logger.error("判断redis缓存中是否有对应的key失败!错误信息为:" + e.getMessage());
        }
        return result;
    }

    /**
     * redis根据key删除对应的value
     * @param key
     * @return
     */
    public boolean remove(final String key){
        boolean result = false;
        try {
            if(exists(key)){
                logger.info("移除  "+key+"的redis 值");
                redisTemplate.delete(key);
            }
            result = true;
        } catch (Exception e) {
            logger.error("redis根据key删除对应的value失败!错误信息为:" + e.getMessage());
        }
        return result;
    }

    /**
     * redis根据keys批量删除对应的value
     * @param keys
     * @return
     */
    public void remove(final String... keys){
        for(String key : keys){
            remove(key);
            logger.info("remove redis key "+key);
        }
    }
}

}

另外 springboot 请求外部http的时候使用 RestTemplate 也有一个坑,就是默认的request buffer不释放,导致时间越久,请求头巨大,最后 就无法请求外部了,所以 可以这样使用



import com.fasterxml.jackson.databind.SerializationFeature;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.client.RestTemplate;
@Component
public class RestHttpConfig {


  @Bean
    public  RestTemplate restTemplate(){

        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
        factory.setBufferRequestBody(false);
        RestTemplate restTemplate = new RestTemplate(factory);
        MappingJackson2HttpMessageConverter jsonHttpMessageConverter = new MappingJackson2HttpMessageConverter();        jsonHttpMessageConverter.getObjectMapper().configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        restTemplate.getMessageConverters().add(jsonHttpMessageConverter);

        return  restTemplate;
    }
}


上一篇下一篇

猜你喜欢

热点阅读