使用Listener实现Cache

本文介绍如何通过Java中的Servlet Listener实现数据缓存,包括在应用程序启动时初始化数据并在每5分钟自动刷新一次的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    进行Web开发时,常常会遇到一些数据需要经常用到,比如客户列表这类,更新频率较小,但是各个页面频繁用到,针对这些数据,我们可以在系统启动时将它们初始化到一个Application级的变量,然后每隔固定时间进行刷新,这样所有页面就可以直接使用这些资料,而不用每次都重新从数据库捞取数据了,这也就是简单的Cache

 

        Java技术中,我们可以使用Listener来实现这一功能。JSP中有提供一个javax.servlet.ServletContextListener的接口,实现该接口的类可以作为一个Application级的监听器,它可以监听应用程序的启动和终止,并分别触发其contextInitializedcontextDestroyed方法,所以,我们实现这两个方法就可以分别在应用程序加载之前Cache数据,并在应用程序终止之前释放资源。

        其中可以通过参数ServletContextEvent eventgetServletContext方法得到ServletContext,得到ServletContext之后,我们就可以用setAttribute方法往Application变量中写数据了。同样,应用程序终止之前,可以通过removeAttribute方法移除Cache数据,释放资源。

        web.xml中配置监听器,如下:

 

 <listener>
    
<display-name>application listener</display-name>
    
<listener-class>net.moon.listener.ApplicationListener</listener-class>
 
</listener>

        这样可以实现了数据的cache,但是我们的数据必须要自动更新才是有效的,我们假设希望Cache数据会每隔5分钟自动更新,当然,我们的逻辑是这样的:当连接请求到来时,判断Cache是否超时,如果超时,则更新Cache,否则,可以直接读取Cache数据。那么我们需要在context变量中添加一个用来记录Cache建立时间的变量,另外为了确保Cache更新中的同步,在context变量中新增另外一个标志Cache是否正在更新的字段,修改后的ApplicationListener代码如下:

        Cache的更新,我们使用另外一种监听器:javax.servlet.ServletRequestListener,实现该接口同样需要两个实现两个方法,该监听器可以监听一个请求到来的事件,同样,我们在initial时来判断Cache是否超时,并更新Cache,代码如下:

        同样在web.xml中配置该监听器,代码如下:

 <listener>
    
<display-name>request listener</display-name>
    
<listener-class>net.moon.listener.RequestListener</listener-class>
 
</listener>

 

package net.moon.listener;

import java.util.Date;

import javax.servlet.ServletContext;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;

public class RequestListener implements ServletRequestListener{

    
private final static float CACHE_MAX_AGE = 5 * 60 * 1000;
    
public void requestDestroyed(ServletRequestEvent sre) {

    }


    
public void requestInitialized(ServletRequestEvent sre) {
        ServletContext context 
= sre.getServletContext();
        
        
if(!(Boolean)context.getAttribute("isRefreshing"
                
&& ((new Date()).getTime() - ((Date)context.getAttribute("birthDate")).getTime()) > CACHE_MAX_AGE){
            context.setAttribute(
"isRefreshing"true);
            
//update the cache date here
            context.setAttribute("isRefreshing"false);
        }

    }

}

package net.moon.listener;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import java.util.Date;

public class ApplicationListener implements ServletContextListener ...{

    
public void contextDestroyed(ServletContextEvent event) ...{
              
//destroy resource when this application going down
    }


    
public void contextInitialized(ServletContextEvent event) ...{
           
//initial resource and data when start this application
           ServletContext context = event.getServletContext();

           
//set the birth time of the cache
           context.setAttribute("birthTime"new Date());
           context.setAttribute(
"isRefreshing"false);
    }

}
package net.moon.listener;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class ApplicationListener implements ServletContextListener {

    
public void contextDestroyed(ServletContextEvent event{
                              
//destroy resource when this application going down
    }


    
public void contextInitialized(ServletContextEvent event{
           
//initial resource and data when start this application
                            ServletContext context = event.getServletContext();
    }

}

### J2Cache 使用教程与配置指南 J2Cache 是一个高性能的分布式缓存框架,支持两级缓存结构(本地缓存 + 远程缓存),能够有效减少节点间的数据通信压力[^1]。以下是关于 J2Cache使用教程、配置指南以及实践示例的内容: #### 1. J2Cache 的基本概念 J2Cache 的核心思想是通过本地缓存和远程缓存的结合,提升缓存访问的速度并降低远程调用的压力。其缓存传输仅涉及缓存 key,而非完整的 value 数据,这使得它在集群模式下的性能表现优于传统的 Ehcache 等单机缓存工具[^1]。 #### 2. J2Cache 的快速集成 J2Cache 提供了与 Spring Boot 的快速集成模块 `j2cache-spring-boot2-starter`,该模块允许开发者通过简单的配置覆盖默认的 Redis 实现,并支持 RedisTemplate 和 MessageListener 的广播监听功能[^2]。以下是具体的集成步骤: ##### 配置依赖 在项目的 `pom.xml` 文件中添加以下依赖: ```xml <dependency> <groupId>net.oschina.j2cache</groupId> <artifactId>j2cache-spring-boot2-starter</artifactId> <version>2.8.0</version> </dependency> ``` ##### 配置文件 在 `application.yml` 或 `application.properties` 中进行如下配置: ```yaml j2cache: cache_names: cache1,cache2 level1: provider_class: net.oschina.j2cache.cache.support.concurrent.ConcurrentCacheProvider level2: provider_class: net.oschina.j2cache.cache.support.redis.J2CacheRedisProvider config: redis.nodes: 127.0.0.1:6379 redis.database: 0 redis.password: ``` #### 3. J2Cache 的实践示例 以下是一个简单的代码示例,展示如何在 Spring Boot 项目中使用 J2Cache: ##### 缓存注解方式 使用 Spring Cache 的注解实现缓存操作: ```java import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; @Service public class UserService { @Cacheable(value = "user", key = "#id") public User getUserById(String id) { // 模拟从数据库查询 return new User(id, "name" + id); } } ``` ##### 手动操作缓存 如果需要手动管理缓存,可以使用 J2Cache 提供的 API: ```java import net.oschina.j2cache.CacheChannel; import net.oschina.j2cache.J2Cache; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class CacheService { @Autowired private CacheChannel cacheChannel; public void putUser(String id, User user) { cacheChannel.set("user", id, user); } public User getUser(String id) { return (User) cacheChannel.get("user", id); } public void removeUser(String id) { cacheChannel.del("user", id); } } ``` #### 4. 常见问题与解决 - **Q**: 如何确保本地缓存和远程缓存的一致性? **A**: J2Cache 通过广播机制同步缓存更新事件,确保所有节点上的本地缓存能够及时刷新[^2]。 - **Q**: 是否支持多级缓存? **A**: J2Cache 默认支持两级缓存(L1 和 L2),但可以通过自定义扩展支持更多层次的缓存结构。 #### 5. 性能优化建议 - 合理设置缓存过期时间,避免过多的无效数据占用内存。 - 对热点数据进行预热,减少首次访问时的延迟。 - 定期监控缓存命中率,调整缓存策略以提高效率。 ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值