Java项目中使用Redis缓存案例

缓存的目的是为了提高系统的性能,缓存中的数据主要有两种: 

                1.热点数据。我们将经常访问到的数据放在缓存中,降低数据库I/O,同时因为缓存的数据的高速查询,加快整个系统的响应速度,也在一定程度上提高并发量。

                2.查询耗时的数据。如果有一些数据查询十分耗时,那么每次请求这些数据时,都去数据库查询的话,会使得系统响应速度特别低,数据库cpu 100%。将这些数据放缓存,会极大提高系统响应速度,但同时数据实时性较差。

  最近工作中有碰到需要使用缓存的情况,场景如下:app端看板统计数据汇总,在打开app时加载看板数据,汇总数据来源于不同的库,各个数据的生成接口已经写好,只需要去调用接口整合数据返回即可。

  具体我们来看看是怎么实现的吧。

 第一步,取mysql中查询各个接口的信息:

 getPanelInfo.java

/* service代码略*/
List panels = panelService.getAllPanels();   //得到接口的名称,接口的url

第二步,根据拿到的信息生成请求参数:

getPanelInfo.java

WrapResponseModel resonseModel = new WrapResponseModel();
  Map headers = new HashMap<>();
  headers.put("username", username);
  headers.put("token",token);
  List content = new ArrayList();
  for(PanelDto panelDto:panel){
  //发送http请求
       content.add(HttpRequestUtils.get(panelDto.getUrl(), headers));
}
// 返回格式
  responseModel.setCode(SUCCESS_CODE);
  responseModel.setData(content);

第三步,发送http请求调用接口:

HttpRequestUtils.java

public static String get(String url, Map headers) {
        RequestConfig config = RequestConfig.custom().setConnectTimeout(TIME_OUT).setConnectionRequestTimeout(TIME_OUT).setSocketTimeout(TIME_OUT).build();
        String ret = null;
        //创建HttpClient对象
        CloseableHttpClient closeHttpClient = HttpClients.createDefault();
        CloseableHttpResponse httpResponse = null;
        //发送get请求
        HttpGet httpGet = new HttpGet(url);
        try {
            // add header
            if (Objects.nonNull(headers)) {
                Set keys = headers.keySet();
                for (Iterator i = keys.iterator(); i.hasNext(); ) {
                    String key = i.next();
                    httpGet.addHeader(key, headers.get(key));
                }
            }

            httpGet.setConfig(config);
            //执行Get请求 得到Response对象
            httpResponse = closeHttpClient.execute(httpGet);
            //httpResponse.getStatusLine() 响应头信息
            int httpResponseCode = httpResponse.getStatusLine().getStatusCode();

            if (200 != httpResponseCode) {
                logger.error("http返回值异常, httpResponseCode = " + httpResponseCode);
            }

            //返回对象
            HttpEntity httpEntity = httpResponse.getEntity();
            ret = EntityUtils.toString(httpEntity, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            logger.error(e.getMessage(), e);
        } catch (ClientProtocolException e) {
            logger.error(e.getMessage(), e);
        } catch (IOException e) {
            //logger.error(e.getMessage(), e);
        } finally {
            if (httpResponse != null) {
                try {
                    httpResponse.close();
                } catch (IOException e) {
                    logger.error(e.getMessage(), e);
                }
            }
            if (closeHttpClient != null) {
                try {
                    closeHttpClient.close();
                } catch (IOException e) {
                    logger.error(e.getMessage(), e);
                }
            }
        }
        return ret;
    }

第四步,查询数据set进redis,之后返回查询的数据:

 getPanelInfo.java

if (!Objects.equals(redisCache, "false")) {
//redisttl过期时间
redisProxyHandler.set(redisKey, JSON.toJSONString(responseModel), REDIS_TTL); logger.error("set succeed!!!!!!!!!!!!!!!!"); }

redisHandler.java

public void set(String key, String value, int seconds) {
      redisCacheProvider.set(key, value, seconds);
 }

redisProvider.java

@Autowired
    private JedisPool jedisPool;

    public Jedis getJedis() {
        Jedis jedis = this.jedisPool.getResource();
        // 使用index为2的database
        jedis.select(2);
        return jedis;
    }

    public void set(String key, String value, int seconds) {
        Jedis jedis = null;
        try {
            jedis = getJedis();
            jedis.setex(key, seconds, value);
            Long exp = jedis.ttl(key);
            if (exp < 0) {
                throw new RuntimeException("data time out!");19             }
        } catch (Throwable e) {
            logger.error(e.getMessage(), e);
            throw new TokenException(e.getMessage());
        } finally {
            if(jedis != null){jedis.close;}
        }
    }

第五步,请求接口的时候,先请求redis缓存,如果命中则返回命中数据,否则,将执行上面的发送http请求在拼凑数据返回的代码:

getPanelInfo.java

String panelInfo = redisProxyHandler.get(redisKey);
                Long expire = redisProxyHandler.getExpire(redisKey);
               //命中才返回,否则会去发http请求
                if (Objects.nonNull(panelInfo) && (expire > 0) && expire 

redisHandler.java

public String get(String key) 
       return redisCacheProvider.get(key);
}

redisProvider.java

public String get(String key) {
        String value = null;
        Jedis jedis = null;
        try {
            jedis = getJedis();
            value = jedis.get(key);
        } catch (Throwable e) {
            logger.error(e.getMessage(), e);
            throw new TokenException(e.getMessage());
        } finally {
            if(jedis != null){
                jedis.close();
           }
        }
        return value;
    }

 redis相关配置文件如下

applicationContext.xml



    

    
    
        
        
        
        
    

    
        
        
        
    

redis.properties

# 控制一个pool可分配多少个jedis实例
redis.pool.maxTotal=1000
# 控制一个pool最多有多少个状态为idle(空闲)的jedis实例
redis.pool.maxIdle=200
# 表示当borrow一个jedis实例时,最大的等待时间,如果超过等待时间,则直接抛出JedisConnectionException
redis.pool.maxWaitMillis=2000
#在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的
redis.pool.testOnBorrow=true
# redis 单机
# 单机 host
jedis.host=127.0.0.1
# 单机 port
jedis.port=6379

你可能感兴趣的:(redis)