SpringMVC通过Redis实现缓存主页
程序员文章站
2022-07-10 16:29:34
...
这里说的缓存只是为了提供一些动态的界面没办法作静态化的界面来减少数据库的访问压力,如果能够做静态化的话的还是采用nginx来做界面的静态化,这样可以承受高并发的访问能力。
好了,废话少说直接看实现代码吧,
实现机制主要是通过过滤器拦截方案,有两个地方要注意的
1,Servlet过虑器中使用Spring容器
2,截获JSP渲染结果保存redis中
首先看第一个Servlet过虑器中使用Spring容器
定义一个filter, 实现ApplicationContextAware接口
配置spring的bean
web.xml中的声明
这时,我们就可以在doFilter()方法中直接通过ApplicationContext检索需要的bean了
二,截获JSP渲染结果
好了,废话少说直接看实现代码吧,
实现机制主要是通过过滤器拦截方案,有两个地方要注意的
1,Servlet过虑器中使用Spring容器
2,截获JSP渲染结果保存redis中
首先看第一个Servlet过虑器中使用Spring容器
定义一个filter, 实现ApplicationContextAware接口
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
<bean class="com.zhang.example.servlet.CacheFilter" id="cacheFilter"></bean>
web.xml中的声明
<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了
StringRedisTemplate redis = (StringRedisTemplate)ctx.getBean("redisTemplate");
二,截获JSP渲染结果
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(); } }
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分钟。这样下次请求时就可以直接从缓存中读取
上一篇: ngrok内网穿透工具服务器搭建
下一篇: VUE axios 加载中提示封装
推荐阅读
-
redis服务器环境下mysql实现lnmp架构缓存
-
JAVAEE——宜立方商城06:Redis安装、数据类型和持久化方案、Redis集群分析与搭建、实现缓存和同步
-
【转载】在AspNetCore 中 使用Redis实现分布式缓存
-
SpringBoot使用Redis缓存的实现方法
-
通过Nginx+Tomcat+Redis实现持久会话
-
通过c++11的condition_variable实现的有最大缓存限制的队列
-
laravel使用Redis实现网站缓存读取的方法详解
-
thinkPHP框架通过Redis实现增删改查操作的方法详解
-
spring-boot-2.0.3之redis缓存实现,不是你想的那样哦!
-
Django使用redis缓存服务器的实现代码示例