zoukankan      html  css  js  c++  java
  • SpringMVC通过Redis实现缓存主页

    这里说的缓存只是为了提供一些动态的界面没办法作静态化的界面来减少数据库的访问压力,如果能够做静态化的话的还是采用nginx来做界面的静态化,这样可以承受高并发的访问能力。 
         好了,废话少说直接看实现代码吧下载地址, 
         实现机制主要是通过过滤器拦截方案,有两个地方要注意的 
         1,Servlet过虑器中使用Spring容器 
         2,截获JSP渲染结果保存redis中 
    首先看第一个Servlet过虑器中使用Spring容器 
         定义一个filter, 实现ApplicationContextAware接口 
        
    Java代码  收藏代码
    public class CacheFilter implements Filter, ApplicationContextAware {  
        private static ApplicationContext ctx; // 必须声明为static  
        @Override  
        public void init(FilterConfig config) throws ServletException {  
        }  
       
        @Override  
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {  
            filterChain.doFilter(servletRequest, servletResponse);  
        }  
        @Override  
        public void destroy() {  
       
        }  
        @Override  
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {  
            CacheFilter.ctx = applicationContext; // 保存spring容器到static变量中  
        }  
    
    配置spring的bean
    Java代码  收藏代码
    <bean class="com.zhang.example.servlet.CacheFilter" id="cacheFilter"></bean>  
    
    web.xml中的声明 
    Java代码  收藏代码
    <filter>  
            <filter-name>Cache Filter</filter-name>  
            <filter-class>com.zhang.example.servlet.CacheFilter</filter-class>  
        </filter>  
        <filter-mapping>  
            <filter-name>Cache Filter</filter-name>  
            <servlet-name>/</servlet-name>  
        </filter-mapping>  
    
    这时,我们就可以在doFilter()方法中直接通过ApplicationContext检索需要的bean了
    Java代码  收藏代码
    StringRedisTemplate redis = (StringRedisTemplate)ctx.getBean("redisTemplate");  
    
    二,截获JSP渲染结果 
    Java代码  收藏代码
    public class ResponseWrapper extends HttpServletResponseWrapper {  
        private PrintWriter cachedWriter;  
        private CharArrayWriter bufferedWriter;  
       
        public ResponseWrapper(HttpServletResponse response) {  
            super(response);  
            // 这个是我们保存返回结果的地方  
            bufferedWriter = new CharArrayWriter();  
            // 这个是包装PrintWriter的,让所有结果通过这个PrintWriter写入到bufferedWriter中  
            cachedWriter = new PrintWriter(bufferedWriter);  
        }  
       
        @Override  
        public PrintWriter getWriter() {  
            return cachedWriter;  
        }  
       
        /** 
         * 获取原始的HTML页面内容。 
         * 
         * @return 
         */  
        public String getResult() {  
            return bufferedWriter.toString();  
        }  
    }  
    
    Java代码  收藏代码
    public class CacheFilter implements Filter, ApplicationContextAware {  
        private static final Logger log = LoggerFactory.getLogger(CacheFilter.class);  
       
        private static ApplicationContext ctx;  
        @Override  
        public void init(FilterConfig config) throws ServletException {  
        }  
       
        @Override  
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {  
            HttpServletResponse resp = (HttpServletResponse) servletResponse;  
            HttpServletRequest req = (HttpServletRequest) servletRequest;  
            // 如果不是访问主页,放行  
            if (false == req.getRequestURI().equals("/")) {  
                filterChain.doFilter(servletRequest, resp);  
                return;  
            }  
            // 访问的是主页  
            // 从缓存中得到主页html  
            String html = getHtmlFromCache();  
            if (null == html) {  
                // 缓存中没有 截取生成的html并放入缓存  
                log.info("缓存不存在,生成缓存");  
                ResponseWrapper wrapper = new ResponseWrapper(resp);  
                filterChain.doFilter(servletRequest, wrapper);  
                // 放入缓存  
                html = wrapper.getResult();  
                putIntoCache(html);  
            }  
            // 返回响应  
            resp.setContentType("text/html; charset=utf-8");  
            resp.getWriter().print(html);  
        }  
        @Override  
        public void destroy() {  
        }  
       
        @Override  
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {  
            this.ctx = applicationContext;  
        }  
       
        private String getHtmlFromCache() {  
            StringRedisTemplate redis = (StringRedisTemplate)ctx.getBean("redisTemplate");  
            return redis.opsForValue().get("home");  
        }  
       
        private void putIntoCache(String html) {  
            StringRedisTemplate redis = (StringRedisTemplate)ctx.getBean("redisTemplate");  
            redis.opsForValue().set("home", html, TimeUnit.MINUTES.toSeconds(10)); // 10分钟  
        }  
    }  
    按照这个逻辑,当客户的GET请求为/时,CacheFilter会首先向Redis发起请求获取主页的html代码,如果成功,则直接返回给客户端,失败,则通过刚刚写好的ResponseWrapper截获主页JSP的渲染结果,放入Redis,并设置过期时间为10分钟。这样下次请求时就可以直接从缓存中读取
  • 相关阅读:
    浅看网络结构与TCP/IP协议栈
    moectf-re WP
    开启博客之旅
    初始C++类和对象
    最完整的自动化测试流程:Python编写执行测试用例及定时自动发送最新测试报告邮件
    Eclipse+pydev环境搭建
    单例模式应用 | Shared_ptr引用计数管理器
    随笔——统计单词个数
    随笔——算法笔记(未整理)
    C++ | 智能指针初探
  • 原文地址:https://www.cnblogs.com/qingdouchukais/p/5166099.html
Copyright © 2011-2022 走看看