Maven项目JCS缓存无法留存数据,请求重复走DAO层问题
Hey Ashwin, let's break down why your JCS cache keeps returning empty even after the first request—there are a few critical issues in your code that are causing this behavior:
1. Mismatched Cache Keys (Biggest Culprit!)
Look at how you're storing vs retrieving data:
- In your DAO's
putIncachemethod, you're storing individualAlbumobjects with numeric keys like1,2,3:cache.put(new Integer(i+1), a); - But in your Service layer, you're trying to fetch a full list using the string key
"musicCache":List<Album> albumList = (List) cache.get("musicCache");
These are completely different keys—so your cache will never find the data you stored, hence it always falls back to the DAO.
2. Reinitializing Cache Manager Every Time
Your DAO's putIncache method calls CompositeCacheManager.getUnconfiguredInstance().configure(props) on every request. This resets the entire cache configuration each time, wiping out any existing cached data.
3. Improper Cache Instance Sharing
Your Service layer uses a cache variable that's never properly initialized (or is recreated per request), and your singleton MusicCache class isn't actually being used in the Service—so the cache instance you create in the singleton isn't the one the Service checks.
Step-by-Step Fix
1. Create a Reusable Cache Utility (Single Instance)
First, make sure your JCS cache is initialized once at startup, and shared across all layers:
public class CacheUtil { private static JCS musicCache; // Initialize cache once when the class loads static { try { CompositeCacheManager ccm = CompositeCacheManager.getUnconfiguredInstance(); Properties props = new Properties(); // Basic JCS configuration (tweak based on your needs) props.put("jcs.default", "DC"); props.put("jcs.default.cacheattributes", "org.apache.jcs.engine.CompositeCacheAttributes"); props.put("jcs.default.cacheattributes.MaxObjects", "1000"); // Max objects in memory props.put("jcs.default.elementattributes", "org.apache.jcs.engine.ElementAttributes"); props.put("jcs.default.elementattributes.IsEternal", "true"); // Data doesn't expire ccm.configure(props); musicCache = JCS.getInstance("musicCache"); } catch (CacheException e) { e.printStackTrace(); throw new RuntimeException("Failed to initialize JCS cache", e); } } // Get the shared cache instance public static JCS getMusicCache() { return musicCache; } }
2. Fix Service Layer Logic
Rewrite your Service to properly check the cache, fetch from DAO if needed, and store the full list in cache:
public List<Album> getAllMusic() { // Remove repeated log4j initialization—do this once at app startup instead! // Properties props = new Properties(); // props.load(new FileInputStream("src/main/resources/log4j.properties")); // PropertyConfigurator.configure(props); JCS cache = CacheUtil.getMusicCache(); List<Album> albumList = (List<Album>) cache.get("musicCache"); // Cache hit: return cached data if (albumList != null) { System.out.println("Returning data from cache"); return albumList; } // Cache miss: fetch from DAO System.out.println("Putting data in cache"); albumList = musicDao.getAllTopHundredMusic(); // Store the full list in cache with the correct key try { cache.put("musicCache", albumList); } catch (CacheException e) { e.printStackTrace(); // Even if cache fails, return the DAO data to avoid breaking the app } return albumList; }
3. Simplify DAO Layer
Remove the putIncache method entirely—your DAO should only handle fetching data from the source (database, etc.), not managing cache:
public List<Album> getAllTopHundredMusic() { // Your existing logic to fetch data from database/data source List<Album> albumList = new ArrayList<>(); // ... populate albumList with actual data return albumList; }
Why This Works
- Single Cache Instance: The
CacheUtilinitializes the cache once, so all layers use the same instance. - Matching Keys: We store the full
List<Album>under the key"musicCache", which is exactly what the Service checks. - No Reinitialization: The cache manager is configured only once, so cached data persists across requests.
Testing
Now when you call http://localhost:8080/api/hello/getAllMusic:
- First request: Prints
Putting data in cacheand stores the list in cache. - All subsequent requests: Prints
Returning data from cacheand returns cached data immediately.
内容的提问来源于stack exchange,提问作者Ashwin Karki

