美文网首页
Redis实现网页和json数据缓存

Redis实现网页和json数据缓存

作者: 你值得拥有更好的12138 | 来源:发表于2019-07-09 11:57 被阅读0次

    以下均为本人理解,欢迎大佬指出错误
    github地址:redis缓存网页和json数据

    缓存的原理

    • 1.首先使用redis实现一个计数器(排序set)记录网站的链接被点击的次数。
      1. 链接点击的次数超过一定的阈值后,保存到一个Hash中
    • 3 .当第二次再使用这个链接时,从redis中读取结果

    缓存的数据包括网页和json数据

    java层面需要的组件

    1.一个fitler用于实现计数器和缓存的功能

        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
            HttpServletResponse resp = (HttpServletResponse) servletResponse;
            String path = httpServletRequest.getServletPath();
            LOGGER.info("Recevice request path:" + path);
    
            try {
                //从缓存中取
                 String jsonResult = (String) redisUtil.hget(JSON_CACHE, path);
                String pageResult = (String) redisUtil.hget(WEB_CACHE, path);
                double sorce = redisUtil.zIncreament(CACHE_COUNT, path, 1);
                LOGGER.info("Redis increment successfuly.");
                String result = Strings.isEmpty(pageResult) ? jsonResult : pageResult;
                if (!Strings.isEmpty(jsonResult)) {
                    resp.setContentType("application/json; charset=utf-8");
                } else if (!Strings.isEmpty(pageResult)) {
                    resp.setContentType("text/html; charset=utf-8");
                }
    
                if (Strings.isEmpty(result) && sorce > baseConfig.getClickCount()) {
                    //当缓存中不存在,并且连接的使用次数超过阈值就进行缓存
                    CacheResponseWrapper cacheResponseWrapper = new CacheResponseWrapper(resp);
                    filterChain.doFilter(servletRequest, cacheResponseWrapper);
                    jsonResult = cacheResponseWrapper.getBody();
                    pageResult = cacheResponseWrapper.getBufferd();
    
                    Map<String, String> cache = new HashMap<>();
                    if (!Strings.isEmpty(jsonResult) && isJSONValid2(jsonResult)) {
                        //当结果是JSONResult
                        cache.put(path, jsonResult);
                        redisUtil.hmset(JSON_CACHE, cache);
                        resp.setContentType("application/json; charset=utf-8");
                        LOGGER.info("Redis cache json successfuly from path {}", path);
                    } else {
                        //当结果是网页时
                        cache.put(path, pageResult);
                        redisUtil.hmset(WEB_CACHE, cache);
    
                        LOGGER.info("Redis cache page successfuly from path {}", path);
                    }
                    result = Strings.isEmpty(pageResult) ? jsonResult : pageResult;
                    //将结果重新写入response,并提前结束避免调用 filterChain.doFilter(servletRequest, cacheResponseWrapper)报错
                    resp.getWriter().write(result);
                    return;
                } else {
                    if(!Strings.isEmpty(result)){
                        LOGGER.info("Data from redis cache.");
                        resp.getWriter().write(result);
                        return;
                    }else {
                        LOGGER.info("Path click count < 1");
                    }
                }
            } catch (Exception e) {
                redisUtil.zadd(CACHE_COUNT, path, 1);
                LOGGER.error(e.getCause().toString());
                LOGGER.info("Redis add successfuly.");
            }
            filterChain.doFilter(servletRequest, resp);
        }
    
    

    将结果重新写入response,并提前结束避免调用 filterChain.doFilter(servletRequest, cacheResponseWrapper)报错

    2.CacheResponseWrapper extends HttpServletResponseWrapper 用于从response中获取请求的结果

    public class CacheResponseWrapper extends HttpServletResponseWrapper {
        private CharArrayWriter bufferd;
        private PrintWriter printWriter;
        private ServletOutputStream outputStream;
        private ByteArrayOutputStream byteArrayOutputStream;
    
        public CacheResponseWrapper(HttpServletResponse response) {
            super(response);
            bufferd = new CharArrayWriter();
            printWriter = new PrintWriter(bufferd);
            byteArrayOutputStream = new ByteArrayOutputStream();
            outputStream = new ServletOutputStream() {
                @Override
                public void write(int b) throws IOException {
                    byteArrayOutputStream.write(b);
                }
    
                @Override
                public boolean isReady() {
                    return true;
                }
    
                @Override
                public void setWriteListener(WriteListener writeListener) {
    
                }
            };
        }
    
        @Override
        public PrintWriter getWriter() throws IOException {
            return printWriter;
        }
    
        public String getBufferd() {
            //普通请求方式使用这个获取结果
            return bufferd.toString();
        }
    
        @Override
        public ServletOutputStream getOutputStream() throws IOException {
            return outputStream;
        }
    
        public String getBody() {
            //json请求方式获取这个结果
            return new String(byteArrayOutputStream.toByteArray());
        }
    }
    
    

    3.操作redis的工具类
    比如:

     public  boolean hmset(String key, Map<String, String> value) {
            boolean result = false;
            try {
                redisTemplate.opsForHash().putAll(key, value);
                result = true;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return result;
        }
    
    

    相关文章

      网友评论

          本文标题:Redis实现网页和json数据缓存

          本文链接:https://www.haomeiwen.com/subject/eqgtkctx.html